blob: dfe7ee44c4cca86b9a70e4a56efe89a1775f41bd [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)
bsalomon@google.comc2099d22012-03-02 21:26:50 +000021 , fStencilWrapOps(stencilWrapOpsSupport) {
bsalomon@google.com289533a2011-10-27 12:34:25 +000022}
23
24
bsalomon@google.com30085192011-08-19 15:42:31 +000025////////////////////////////////////////////////////////////////////////////////
26// Stencil rules for paths
27
28////// Even/Odd
29
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000030GR_STATIC_CONST_SAME_STENCIL(gEOStencilPass,
31 kInvert_StencilOp,
32 kKeep_StencilOp,
33 kAlwaysIfInClip_StencilFunc,
34 0xffff,
35 0xffff,
36 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000037
38// ok not to check clip b/c stencil pass only wrote inside clip
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000039GR_STATIC_CONST_SAME_STENCIL(gEOColorPass,
40 kZero_StencilOp,
41 kZero_StencilOp,
42 kNotEqual_StencilFunc,
43 0xffff,
44 0x0000,
45 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000046
47// have to check clip b/c outside clip will always be zero.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000048GR_STATIC_CONST_SAME_STENCIL(gInvEOColorPass,
49 kZero_StencilOp,
50 kZero_StencilOp,
51 kEqualIfInClip_StencilFunc,
52 0xffff,
53 0x0000,
54 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000055
56////// Winding
57
58// when we have separate stencil we increment front faces / decrement back faces
59// when we don't have wrap incr and decr we use the stencil test to simulate
60// them.
61
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000062GR_STATIC_CONST_STENCIL(gWindStencilSeparateWithWrap,
bsalomon@google.com30085192011-08-19 15:42:31 +000063 kIncWrap_StencilOp, kDecWrap_StencilOp,
64 kKeep_StencilOp, kKeep_StencilOp,
65 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000066 0xffff, 0xffff,
67 0xffff, 0xffff,
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000068 0xffff, 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000069
70// if inc'ing the max value, invert to make 0
71// if dec'ing zero invert to make all ones.
72// we can't avoid touching the stencil on both passing and
73// failing, so we can't resctrict ourselves to the clip.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000074GR_STATIC_CONST_STENCIL(gWindStencilSeparateNoWrap,
bsalomon@google.com30085192011-08-19 15:42:31 +000075 kInvert_StencilOp, kInvert_StencilOp,
76 kIncClamp_StencilOp, kDecClamp_StencilOp,
77 kEqual_StencilFunc, kEqual_StencilFunc,
tomhudson@google.com62b09682011-11-09 16:39:17 +000078 0xffff, 0xffff,
79 0xffff, 0x0000,
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000080 0xffff, 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000081
82// When there are no separate faces we do two passes to setup the winding rule
83// stencil. First we draw the front faces and inc, then we draw the back faces
84// and dec. These are same as the above two split into the incrementing and
85// decrementing passes.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000086GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapInc,
87 kIncWrap_StencilOp,
88 kKeep_StencilOp,
89 kAlwaysIfInClip_StencilFunc,
90 0xffff,
91 0xffff,
92 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +000093
bsalomon@google.com6b2445e2011-12-15 19:47:46 +000094GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilWithWrapDec,
95 kDecWrap_StencilOp,
96 kKeep_StencilOp,
97 kAlwaysIfInClip_StencilFunc,
98 0xffff,
99 0xffff,
100 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +0000101
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000102GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapInc,
103 kInvert_StencilOp,
104 kIncClamp_StencilOp,
105 kEqual_StencilFunc,
106 0xffff,
107 0xffff,
108 0xffff);
109
110GR_STATIC_CONST_SAME_STENCIL(gWindSingleStencilNoWrapDec,
111 kInvert_StencilOp,
112 kDecClamp_StencilOp,
113 kEqual_StencilFunc,
114 0xffff,
115 0x0000,
116 0xffff);
117
118// Color passes are the same whether we use the two-sided stencil or two passes
119
120GR_STATIC_CONST_SAME_STENCIL(gWindColorPass,
121 kZero_StencilOp,
122 kZero_StencilOp,
123 kNonZeroIfInClip_StencilFunc,
124 0xffff,
125 0x0000,
126 0xffff);
127
128GR_STATIC_CONST_SAME_STENCIL(gInvWindColorPass,
129 kZero_StencilOp,
130 kZero_StencilOp,
131 kEqualIfInClip_StencilFunc,
132 0xffff,
133 0x0000,
134 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +0000135
136////// Normal render to stencil
137
138// Sometimes the default path renderer can draw a path directly to the stencil
139// buffer without having to first resolve the interior / exterior.
bsalomon@google.com6b2445e2011-12-15 19:47:46 +0000140GR_STATIC_CONST_SAME_STENCIL(gDirectToStencil,
141 kZero_StencilOp,
142 kIncClamp_StencilOp,
143 kAlwaysIfInClip_StencilFunc,
144 0xffff,
145 0x0000,
146 0xffff);
bsalomon@google.com30085192011-08-19 15:42:31 +0000147
148////////////////////////////////////////////////////////////////////////////////
149// Helpers for drawPath
150
bsalomon@google.com30085192011-08-19 15:42:31 +0000151#define STENCIL_OFF 0 // Always disable stencil (even when needed)
152
bsalomon@google.com8d033a12012-04-27 15:52:53 +0000153static inline bool single_pass_path(const SkPath& path, GrPathFill fill) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000154#if STENCIL_OFF
155 return true;
156#else
bsalomon@google.com47059542012-06-06 20:51:20 +0000157 if (kEvenOdd_GrPathFill == fill || kWinding_GrPathFill == fill) {
bsalomon@google.com7d72c452012-01-30 14:02:44 +0000158 return path.isConvex();
bsalomon@google.com30085192011-08-19 15:42:31 +0000159 }
160 return false;
161#endif
162}
163
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000164bool GrDefaultPathRenderer::requiresStencilPass(const SkPath& path,
165 GrPathFill fill,
166 const GrDrawTarget* target) const {
bsalomon@google.com7d72c452012-01-30 14:02:44 +0000167 return !single_pass_path(path, fill);
bsalomon@google.com30085192011-08-19 15:42:31 +0000168}
169
bsalomon@google.com30085192011-08-19 15:42:31 +0000170static inline void append_countour_edge_indices(GrPathFill fillType,
171 uint16_t fanCenterIdx,
172 uint16_t edgeV0Idx,
173 uint16_t** indices) {
174 // when drawing lines we're appending line segments along
175 // the contour. When applying the other fill rules we're
176 // drawing triangle fans around fanCenterIdx.
bsalomon@google.com47059542012-06-06 20:51:20 +0000177 if (kHairLine_GrPathFill != fillType) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000178 *((*indices)++) = fanCenterIdx;
179 }
180 *((*indices)++) = edgeV0Idx;
181 *((*indices)++) = edgeV0Idx + 1;
182}
183
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000184bool GrDefaultPathRenderer::createGeom(const SkPath& path,
185 GrPathFill fill,
bsalomon@google.com81712882012-11-01 17:12:34 +0000186 SkScalar srcSpaceTol,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000187 GrDrawTarget* target,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000188 GrPrimitiveType* primType,
189 int* vertexCnt,
bsalomon@google.comb3729422012-03-07 19:13:28 +0000190 int* indexCnt,
191 GrDrawTarget::AutoReleaseGeometry* arg) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000192 {
193 SK_TRACE_EVENT0("GrDefaultPathRenderer::createGeom");
194
bsalomon@google.com81712882012-11-01 17:12:34 +0000195 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol);
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000196 int contourCnt;
197 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt,
bsalomon@google.com30085192011-08-19 15:42:31 +0000198 srcSpaceTol);
199
200 if (maxPts <= 0) {
201 return false;
202 }
203 if (maxPts > ((int)SK_MaxU16 + 1)) {
204 GrPrintf("Path not rendered, too many verts (%d)\n", maxPts);
205 return false;
206 }
207
208 GrVertexLayout layout = 0;
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000209 bool indexed = contourCnt > 1;
bsalomon@google.com30085192011-08-19 15:42:31 +0000210
211 int maxIdxs = 0;
bsalomon@google.com47059542012-06-06 20:51:20 +0000212 if (kHairLine_GrPathFill == fill) {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000213 if (indexed) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000214 maxIdxs = 2 * maxPts;
bsalomon@google.com47059542012-06-06 20:51:20 +0000215 *primType = kLines_GrPrimitiveType;
bsalomon@google.com30085192011-08-19 15:42:31 +0000216 } else {
bsalomon@google.com47059542012-06-06 20:51:20 +0000217 *primType = kLineStrip_GrPrimitiveType;
bsalomon@google.com30085192011-08-19 15:42:31 +0000218 }
219 } else {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000220 if (indexed) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000221 maxIdxs = 3 * maxPts;
bsalomon@google.com47059542012-06-06 20:51:20 +0000222 *primType = kTriangles_GrPrimitiveType;
bsalomon@google.com30085192011-08-19 15:42:31 +0000223 } else {
bsalomon@google.com47059542012-06-06 20:51:20 +0000224 *primType = kTriangleFan_GrPrimitiveType;
bsalomon@google.com30085192011-08-19 15:42:31 +0000225 }
226 }
227
bsalomon@google.comb3729422012-03-07 19:13:28 +0000228
229 if (!arg->set(target, layout, maxPts, maxIdxs)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000230 return false;
231 }
bsalomon@google.comb3729422012-03-07 19:13:28 +0000232
233 uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices());;
234 uint16_t* idx = idxBase;
235 uint16_t subpathIdxStart = 0;
236
237 GrPoint* base = reinterpret_cast<GrPoint*>(arg->vertices());
bsalomon@google.com30085192011-08-19 15:42:31 +0000238 GrAssert(NULL != base);
239 GrPoint* vert = base;
240
bsalomon@google.com30085192011-08-19 15:42:31 +0000241 GrPoint pts[4];
242
243 bool first = true;
244 int subpath = 0;
245
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000246 SkPath::Iter iter(path, false);
bsalomon@google.com30085192011-08-19 15:42:31 +0000247
248 for (;;) {
249 GrPathCmd cmd = (GrPathCmd)iter.next(pts);
250 switch (cmd) {
251 case kMove_PathCmd:
252 if (!first) {
253 uint16_t currIdx = (uint16_t) (vert - base);
bsalomon@google.com30085192011-08-19 15:42:31 +0000254 subpathIdxStart = currIdx;
255 ++subpath;
256 }
257 *vert = pts[0];
258 vert++;
259 break;
260 case kLine_PathCmd:
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000261 if (indexed) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000262 uint16_t prevIdx = (uint16_t)(vert - base) - 1;
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000263 append_countour_edge_indices(fill, subpathIdxStart,
bsalomon@google.com30085192011-08-19 15:42:31 +0000264 prevIdx, &idx);
265 }
266 *(vert++) = pts[1];
267 break;
268 case kQuadratic_PathCmd: {
269 // first pt of quad is the pt we ended on in previous step
270 uint16_t firstQPtIdx = (uint16_t)(vert - base) - 1;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000271 uint16_t numPts = (uint16_t)
bsalomon@google.com30085192011-08-19 15:42:31 +0000272 GrPathUtils::generateQuadraticPoints(
273 pts[0], pts[1], pts[2],
274 srcSpaceTolSqd, &vert,
275 GrPathUtils::quadraticPointCount(pts, srcSpaceTol));
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000276 if (indexed) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000277 for (uint16_t i = 0; i < numPts; ++i) {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000278 append_countour_edge_indices(fill, subpathIdxStart,
bsalomon@google.com30085192011-08-19 15:42:31 +0000279 firstQPtIdx + i, &idx);
280 }
281 }
282 break;
283 }
284 case kCubic_PathCmd: {
285 // first pt of cubic is the pt we ended on in previous step
286 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1;
287 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints(
288 pts[0], pts[1], pts[2], pts[3],
289 srcSpaceTolSqd, &vert,
290 GrPathUtils::cubicPointCount(pts, srcSpaceTol));
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000291 if (indexed) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000292 for (uint16_t i = 0; i < numPts; ++i) {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000293 append_countour_edge_indices(fill, subpathIdxStart,
bsalomon@google.com30085192011-08-19 15:42:31 +0000294 firstCPtIdx + i, &idx);
295 }
296 }
297 break;
298 }
299 case kClose_PathCmd:
300 break;
301 case kEnd_PathCmd:
caryclark@google.comcf6285b2012-06-06 12:09:01 +0000302 // uint16_t currIdx = (uint16_t) (vert - base);
bsalomon@google.com30085192011-08-19 15:42:31 +0000303 goto FINISHED;
304 }
305 first = false;
306 }
307FINISHED:
308 GrAssert((vert - base) <= maxPts);
309 GrAssert((idx - idxBase) <= maxIdxs);
310
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000311 *vertexCnt = vert - base;
312 *indexCnt = idx - idxBase;
bsalomon@google.com30085192011-08-19 15:42:31 +0000313
bsalomon@google.com30085192011-08-19 15:42:31 +0000314 }
bsalomon@google.com30085192011-08-19 15:42:31 +0000315 return true;
316}
317
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000318bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path,
319 GrPathFill fill,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000320 GrDrawTarget* target,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000321 bool stencilOnly) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000322
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000323 GrMatrix viewM = target->getDrawState().getViewMatrix();
bsalomon@google.com81712882012-11-01 17:12:34 +0000324 SkScalar tol = SK_Scalar1;
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000325 tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds());
bsalomon@google.com30085192011-08-19 15:42:31 +0000326
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000327 int vertexCnt;
328 int indexCnt;
329 GrPrimitiveType primType;
bsalomon@google.comb3729422012-03-07 19:13:28 +0000330 GrDrawTarget::AutoReleaseGeometry arg;
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000331 if (!this->createGeom(path,
332 fill,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000333 tol,
334 target,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000335 &primType,
336 &vertexCnt,
bsalomon@google.comb3729422012-03-07 19:13:28 +0000337 &indexCnt,
338 &arg)) {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000339 return false;
bsalomon@google.com30085192011-08-19 15:42:31 +0000340 }
341
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000342 GrAssert(NULL != target);
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000343 GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit);
344 GrDrawState* drawState = target->drawState();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000345 bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
bsalomon@google.com30085192011-08-19 15:42:31 +0000346 // face culling doesn't make sense here
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000347 GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
bsalomon@google.com30085192011-08-19 15:42:31 +0000348
349 int passCount = 0;
350 const GrStencilSettings* passes[3];
tomhudson@google.com93813632011-10-27 20:21:16 +0000351 GrDrawState::DrawFace drawFace[3];
bsalomon@google.com30085192011-08-19 15:42:31 +0000352 bool reverse = false;
353 bool lastPassIsBounds;
354
bsalomon@google.com47059542012-06-06 20:51:20 +0000355 if (kHairLine_GrPathFill == fill) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000356 passCount = 1;
357 if (stencilOnly) {
358 passes[0] = &gDirectToStencil;
359 } else {
360 passes[0] = NULL;
361 }
362 lastPassIsBounds = false;
tomhudson@google.com93813632011-10-27 20:21:16 +0000363 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000364 } else {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000365 if (single_pass_path(path, fill)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000366 passCount = 1;
367 if (stencilOnly) {
368 passes[0] = &gDirectToStencil;
369 } else {
370 passes[0] = NULL;
371 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000372 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000373 lastPassIsBounds = false;
374 } else {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000375 switch (fill) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000376 case kInverseEvenOdd_GrPathFill:
bsalomon@google.com30085192011-08-19 15:42:31 +0000377 reverse = true;
378 // fallthrough
bsalomon@google.com47059542012-06-06 20:51:20 +0000379 case kEvenOdd_GrPathFill:
bsalomon@google.com30085192011-08-19 15:42:31 +0000380 passes[0] = &gEOStencilPass;
381 if (stencilOnly) {
382 passCount = 1;
383 lastPassIsBounds = false;
384 } else {
385 passCount = 2;
386 lastPassIsBounds = true;
387 if (reverse) {
388 passes[1] = &gInvEOColorPass;
389 } else {
390 passes[1] = &gEOColorPass;
391 }
392 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000393 drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000394 break;
395
bsalomon@google.com47059542012-06-06 20:51:20 +0000396 case kInverseWinding_GrPathFill:
bsalomon@google.com30085192011-08-19 15:42:31 +0000397 reverse = true;
398 // fallthrough
bsalomon@google.com47059542012-06-06 20:51:20 +0000399 case kWinding_GrPathFill:
bsalomon@google.com30085192011-08-19 15:42:31 +0000400 if (fSeparateStencil) {
401 if (fStencilWrapOps) {
402 passes[0] = &gWindStencilSeparateWithWrap;
403 } else {
404 passes[0] = &gWindStencilSeparateNoWrap;
405 }
406 passCount = 2;
tomhudson@google.com93813632011-10-27 20:21:16 +0000407 drawFace[0] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000408 } else {
409 if (fStencilWrapOps) {
410 passes[0] = &gWindSingleStencilWithWrapInc;
411 passes[1] = &gWindSingleStencilWithWrapDec;
412 } else {
413 passes[0] = &gWindSingleStencilNoWrapInc;
414 passes[1] = &gWindSingleStencilNoWrapDec;
415 }
416 // which is cw and which is ccw is arbitrary.
tomhudson@google.com93813632011-10-27 20:21:16 +0000417 drawFace[0] = GrDrawState::kCW_DrawFace;
418 drawFace[1] = GrDrawState::kCCW_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000419 passCount = 3;
420 }
421 if (stencilOnly) {
422 lastPassIsBounds = false;
423 --passCount;
424 } else {
425 lastPassIsBounds = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000426 drawFace[passCount-1] = GrDrawState::kBoth_DrawFace;
bsalomon@google.com30085192011-08-19 15:42:31 +0000427 if (reverse) {
428 passes[passCount-1] = &gInvWindColorPass;
429 } else {
430 passes[passCount-1] = &gWindColorPass;
431 }
432 }
433 break;
434 default:
435 GrAssert(!"Unknown path fFill!");
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000436 return false;
bsalomon@google.com30085192011-08-19 15:42:31 +0000437 }
438 }
439 }
440
441 {
bsalomon@google.com30085192011-08-19 15:42:31 +0000442 for (int p = 0; p < passCount; ++p) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000443 drawState->setDrawFace(drawFace[p]);
bsalomon@google.com30085192011-08-19 15:42:31 +0000444 if (NULL != passes[p]) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000445 *drawState->stencil() = *passes[p];
bsalomon@google.com30085192011-08-19 15:42:31 +0000446 }
447
448 if (lastPassIsBounds && (p == passCount-1)) {
449 if (!colorWritesWereDisabled) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000450 drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000451 }
452 GrRect bounds;
bsalomon@google.com288d9542012-10-17 12:53:54 +0000453 GrDrawState::AutoDeviceCoordDraw adcd;
bsalomon@google.com30085192011-08-19 15:42:31 +0000454 if (reverse) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000455 GrAssert(NULL != drawState->getRenderTarget());
bsalomon@google.com30085192011-08-19 15:42:31 +0000456 // draw over the whole world.
457 bounds.setLTRB(0, 0,
bsalomon@google.com81712882012-11-01 17:12:34 +0000458 SkIntToScalar(drawState->getRenderTarget()->width()),
459 SkIntToScalar(drawState->getRenderTarget()->height()));
bsalomon@google.com30085192011-08-19 15:42:31 +0000460 GrMatrix vmi;
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000461 // mapRect through persp matrix may not be correct
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000462 if (!drawState->getViewMatrix().hasPerspective() &&
463 drawState->getViewInverse(&vmi)) {
bsalomon@google.com30085192011-08-19 15:42:31 +0000464 vmi.mapRect(&bounds);
bsalomon@google.com8c2fe992011-09-13 15:27:18 +0000465 } else {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000466 adcd.set(drawState);
bsalomon@google.com30085192011-08-19 15:42:31 +0000467 }
468 } else {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000469 bounds = path.getBounds();
bsalomon@google.com30085192011-08-19 15:42:31 +0000470 }
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000471 GrDrawTarget::AutoGeometryPush agp(target);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000472 target->drawSimpleRect(bounds, NULL);
bsalomon@google.com30085192011-08-19 15:42:31 +0000473 } else {
474 if (passCount > 1) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000475 drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
bsalomon@google.com30085192011-08-19 15:42:31 +0000476 }
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000477 if (indexCnt) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000478 target->drawIndexed(primType, 0, 0,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000479 vertexCnt, indexCnt);
bsalomon@google.com30085192011-08-19 15:42:31 +0000480 } else {
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000481 target->drawNonIndexed(primType, 0, vertexCnt);
bsalomon@google.com30085192011-08-19 15:42:31 +0000482 }
483 }
484 }
485 }
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000486 return true;
bsalomon@google.com30085192011-08-19 15:42:31 +0000487}
488
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000489bool GrDefaultPathRenderer::canDrawPath(const SkPath& path,
490 GrPathFill fill,
491 const GrDrawTarget* target,
492 bool antiAlias) const {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000493 // this class can draw any path with any fill but doesn't do any
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000494 // anti-aliasing.
495 return !antiAlias;
bsalomon@google.com30085192011-08-19 15:42:31 +0000496}
497
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000498bool GrDefaultPathRenderer::onDrawPath(const SkPath& path,
499 GrPathFill fill,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000500 GrDrawTarget* target,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000501 bool antiAlias) {
502 return this->internalDrawPath(path,
503 fill,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000504 target,
bsalomon@google.comc2099d22012-03-02 21:26:50 +0000505 false);
506}
507
508void GrDefaultPathRenderer::drawPathToStencil(const SkPath& path,
509 GrPathFill fill,
510 GrDrawTarget* target) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000511 GrAssert(kInverseEvenOdd_GrPathFill != fill);
512 GrAssert(kInverseWinding_GrPathFill != fill);
bsalomon@google.com0f11e1a2012-10-08 14:48:36 +0000513 this->internalDrawPath(path, fill, target, true);
bsalomon@google.com30085192011-08-19 15:42:31 +0000514}