OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrDefaultPathRenderer.h" | 8 #include "GrDefaultPathRenderer.h" |
9 | 9 |
10 #include "GrBatch.h" | |
11 #include "GrBatchTarget.h" | |
12 #include "GrBufferAllocPool.h" | |
10 #include "GrContext.h" | 13 #include "GrContext.h" |
11 #include "GrDefaultGeoProcFactory.h" | 14 #include "GrDefaultGeoProcFactory.h" |
12 #include "GrPathUtils.h" | 15 #include "GrPathUtils.h" |
13 #include "GrPipelineBuilder.h" | 16 #include "GrPipelineBuilder.h" |
14 #include "SkGeometry.h" | 17 #include "SkGeometry.h" |
15 #include "SkString.h" | 18 #include "SkString.h" |
16 #include "SkStrokeRec.h" | 19 #include "SkStrokeRec.h" |
17 #include "SkTLazy.h" | 20 #include "SkTLazy.h" |
18 #include "SkTraceEvent.h" | 21 #include "SkTraceEvent.h" |
19 | 22 |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 // drawing triangle fans around fanCenterIdx. | 187 // drawing triangle fans around fanCenterIdx. |
185 if (!hairLine) { | 188 if (!hairLine) { |
186 *((*indices)++) = fanCenterIdx; | 189 *((*indices)++) = fanCenterIdx; |
187 } | 190 } |
188 *((*indices)++) = edgeV0Idx; | 191 *((*indices)++) = edgeV0Idx; |
189 *((*indices)++) = edgeV0Idx + 1; | 192 *((*indices)++) = edgeV0Idx + 1; |
190 } | 193 } |
191 | 194 |
192 static inline void add_quad(SkPoint** vert, const SkPoint* base, const SkPoint p ts[], | 195 static inline void add_quad(SkPoint** vert, const SkPoint* base, const SkPoint p ts[], |
193 SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol, bool indexed, | 196 SkScalar srcSpaceTolSqd, SkScalar srcSpaceTol, bool indexed, |
194 bool isHairline, uint16_t subpathIdxStart, uint16_t* * idx) { | 197 bool isHairline, uint16_t subpathIdxStart, int offse t, uint16_t** idx) { |
195 // first pt of quad is the pt we ended on in previous step | 198 // first pt of quad is the pt we ended on in previous step |
196 uint16_t firstQPtIdx = (uint16_t)(*vert - base) - 1; | 199 uint16_t firstQPtIdx = (uint16_t)(*vert - base) - 1 + offset; |
197 uint16_t numPts = (uint16_t) | 200 uint16_t numPts = (uint16_t) |
198 GrPathUtils::generateQuadraticPoints( | 201 GrPathUtils::generateQuadraticPoints( |
199 pts[0], pts[1], pts[2], | 202 pts[0], pts[1], pts[2], |
200 srcSpaceTolSqd, vert, | 203 srcSpaceTolSqd, vert, |
201 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); | 204 GrPathUtils::quadraticPointCount(pts, srcSpaceTol)); |
202 if (indexed) { | 205 if (indexed) { |
203 for (uint16_t i = 0; i < numPts; ++i) { | 206 for (uint16_t i = 0; i < numPts; ++i) { |
204 append_countour_edge_indices(isHairline, subpathIdxStart, | 207 append_countour_edge_indices(isHairline, subpathIdxStart, |
205 firstQPtIdx + i, idx); | 208 firstQPtIdx + i, idx); |
206 } | 209 } |
207 } | 210 } |
208 } | 211 } |
209 | 212 |
210 bool GrDefaultPathRenderer::createGeom(GrDrawTarget* target, | 213 class DefaultPathBatch : public GrBatch { |
211 GrPipelineBuilder* pipelineBuilder, | 214 public: |
212 GrPrimitiveType* primType, | 215 struct Geometry { |
213 int* vertexCnt, | 216 GrColor fColor; |
214 int* indexCnt, | 217 SkPath fPath; |
215 GrDrawTarget::AutoReleaseGeometry* arg, | 218 SkScalar fTolerance; |
216 const SkPath& path, | 219 SkDEBUGCODE(SkRect fDevBounds;) |
217 const SkStrokeRec& stroke, | 220 }; |
218 SkScalar srcSpaceTol) { | 221 |
219 { | 222 static GrBatch* Create(const Geometry& geometry, uint8_t coverage, const SkM atrix& viewMatrix, |
220 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol); | 223 bool isHairline) { |
221 int contourCnt; | 224 return SkNEW_ARGS(DefaultPathBatch, (geometry, coverage, viewMatrix, isH airline)); |
222 int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, | 225 } |
223 srcSpaceTol); | 226 |
224 | 227 const char* name() const SK_OVERRIDE { return "DefaultPathBatch"; } |
225 if (maxPts <= 0) { | 228 |
226 return false; | 229 void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE { |
227 } | 230 // When this is called on a batch, there is only one geometry bundle |
228 if (maxPts > ((int)SK_MaxU16 + 1)) { | 231 out->setKnownFourComponents(fGeoData[0].fColor); |
229 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); | 232 } |
230 return false; | 233 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRID E { |
231 } | 234 out->setUnknownSingleComponent(); |
232 | 235 } |
233 bool indexed = contourCnt > 1; | 236 |
234 | 237 void initBatchTracker(const GrPipelineInfo& init) SK_OVERRIDE { |
235 const bool isHairline = stroke.isHairlineStyle(); | 238 // Handle any color overrides |
236 | 239 if (init.fColorIgnored) { |
237 int maxIdxs = 0; | 240 fGeoData[0].fColor = GrColor_ILLEGAL; |
238 if (isHairline) { | 241 } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
239 if (indexed) { | 242 fGeoData[0].fColor = init.fOverrideColor; |
240 maxIdxs = 2 * maxPts; | 243 } |
241 *primType = kLines_GrPrimitiveType; | 244 |
245 // setup batch properties | |
246 fBatch.fColorIgnored = init.fColorIgnored; | |
247 fBatch.fColor = fGeoData[0].fColor; | |
248 fBatch.fUsesLocalCoords = init.fUsesLocalCoords; | |
249 fBatch.fCoverageIgnored = init.fCoverageIgnored; | |
250 } | |
251 | |
252 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) SK_OVERRIDE { | |
253 SkAutoTUnref<const GrGeometryProcessor> gp( | |
254 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPositi on_GPType, | |
255 this->color(), | |
256 this->viewMatrix(), | |
257 SkMatrix::I(), | |
258 false, | |
259 this->coverage())); | |
260 | |
261 size_t vertexStride = gp->getVertexStride(); | |
262 SkASSERT(vertexStride == sizeof(SkPoint)); | |
263 | |
264 batchTarget->initDraw(gp, pipeline); | |
265 | |
266 // TODO this is hacky, but the only way we have to initialize the GP is to use the | |
267 // GrPipelineInfo struct so we can generate the correct shader. Once we have GrBatch | |
268 // everywhere we can remove this nastiness | |
269 GrPipelineInfo init; | |
270 init.fColorIgnored = fBatch.fColorIgnored; | |
271 init.fOverrideColor = GrColor_ILLEGAL; | |
272 init.fCoverageIgnored = fBatch.fCoverageIgnored; | |
273 init.fUsesLocalCoords = this->usesLocalCoords(); | |
274 gp->initBatchTracker(batchTarget->currentBatchTracker(), init); | |
275 | |
276 int instanceCount = fGeoData.count(); | |
277 | |
278 // compute number of vertices | |
279 int maxVertices = 0; | |
280 | |
281 // We will use index buffers if we have multiple paths or one path with multiple contours | |
282 bool isIndexed = instanceCount > 1; | |
283 for (int i = 0; i < instanceCount; i++) { | |
284 Geometry& args = fGeoData[i]; | |
285 | |
286 int contourCount; | |
287 maxVertices += GrPathUtils::worstCasePointCount(args.fPath, &contour Count, | |
288 args.fTolerance); | |
289 | |
290 isIndexed = isIndexed || contourCount > 1; | |
291 } | |
292 | |
293 // determine primitiveType | |
294 int maxIndices = 0; | |
295 GrPrimitiveType primitiveType; | |
296 if (this->isHairline()) { | |
297 if (isIndexed) { | |
298 maxIndices = 2 * maxVertices; | |
299 primitiveType = kLines_GrPrimitiveType; | |
300 } else { | |
301 primitiveType = kLineStrip_GrPrimitiveType; | |
302 } | |
242 } else { | 303 } else { |
243 *primType = kLineStrip_GrPrimitiveType; | 304 if (isIndexed) { |
244 } | 305 maxIndices = 3 * maxVertices; |
245 } else { | 306 primitiveType = kTriangles_GrPrimitiveType; |
246 if (indexed) { | 307 } else { |
247 maxIdxs = 3 * maxPts; | 308 primitiveType = kTriangleFan_GrPrimitiveType; |
248 *primType = kTriangles_GrPrimitiveType; | 309 } |
310 } | |
311 | |
312 // allocate vertex / index buffers | |
313 const GrVertexBuffer* vertexBuffer; | |
314 int firstVertex; | |
315 | |
316 void* vertices = batchTarget->vertexPool()->makeSpace(vertexStride, | |
317 maxVertices, | |
318 &vertexBuffer, | |
319 &firstVertex); | |
320 | |
321 const GrIndexBuffer* indexBuffer; | |
322 int firstIndex; | |
323 | |
324 void* indices = NULL; | |
325 if (isIndexed) { | |
326 indices = batchTarget->indexPool()->makeSpace(maxIndices, | |
327 &indexBuffer, | |
328 &firstIndex); | |
329 } | |
330 | |
331 // fill buffers | |
332 int vertexOffset = 0; | |
333 int indexOffset = 0; | |
334 for (int i = 0; i < instanceCount; i++) { | |
335 Geometry& args = fGeoData[i]; | |
336 | |
337 int vertexCnt = 0; | |
338 int indexCnt = 0; | |
339 if (!this->createGeom(vertices, | |
340 vertexOffset, | |
341 indices, | |
342 indexOffset, | |
343 &vertexCnt, | |
344 &indexCnt, | |
345 args.fPath, | |
346 args.fTolerance, | |
347 isIndexed)) { | |
348 return; | |
349 } | |
350 | |
351 vertexOffset += vertexCnt; | |
352 indexOffset += indexCnt; | |
353 } | |
354 SkASSERT(vertexOffset <= maxVertices && indexOffset <= maxIndices); | |
355 | |
356 GrDrawTarget::DrawInfo drawInfo; | |
357 drawInfo.setPrimitiveType(primitiveType); | |
358 drawInfo.setVertexBuffer(vertexBuffer); | |
359 drawInfo.setStartVertex(firstVertex); | |
360 drawInfo.setVertexCount(vertexOffset); | |
361 if (isIndexed) { | |
362 drawInfo.setIndexBuffer(indexBuffer); | |
363 drawInfo.setStartIndex(firstIndex); | |
364 drawInfo.setIndexCount(indexOffset); | |
249 } else { | 365 } else { |
250 *primType = kTriangleFan_GrPrimitiveType; | 366 drawInfo.setStartIndex(0); |
251 } | 367 drawInfo.setIndexCount(0); |
252 } | 368 } |
253 | 369 batchTarget->draw(drawInfo); |
254 if (!arg->set(target, maxPts, GrDefaultGeoProcFactory::DefaultVertexStride() , maxIdxs)) { | 370 } |
255 return false; | 371 |
256 } | 372 SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; } |
257 SkASSERT(GrDefaultGeoProcFactory::DefaultVertexStride() == sizeof(SkPoint)); | 373 |
258 | 374 private: |
259 uint16_t* idxBase = reinterpret_cast<uint16_t*>(arg->indices()); | 375 DefaultPathBatch(const Geometry& geometry, uint8_t coverage, const SkMatrix& viewMatrix, |
260 uint16_t* idx = idxBase; | 376 bool isHairline) { |
261 uint16_t subpathIdxStart = 0; | 377 this->initClassID<DefaultPathBatch>(); |
262 | 378 fBatch.fCoverage = coverage; |
263 SkPoint* base = reinterpret_cast<SkPoint*>(arg->vertices()); | 379 fBatch.fIsHairline = isHairline; |
264 SkASSERT(base); | 380 fBatch.fViewMatrix = viewMatrix; |
265 SkPoint* vert = base; | 381 fGeoData.push_back(geometry); |
266 | 382 } |
267 SkPoint pts[4]; | 383 |
268 | 384 bool onCombineIfPossible(GrBatch* t) SK_OVERRIDE { |
269 bool first = true; | 385 DefaultPathBatch* that = t->cast<DefaultPathBatch>(); |
270 int subpath = 0; | 386 |
271 | 387 if (this->color() != that->color()) { |
272 SkPath::Iter iter(path, false); | 388 return false; |
273 | 389 } |
274 for (;;) { | 390 |
275 SkPath::Verb verb = iter.next(pts); | 391 if (this->coverage() != that->coverage()) { |
276 switch (verb) { | 392 return false; |
277 case SkPath::kMove_Verb: | 393 } |
278 if (!first) { | 394 |
279 uint16_t currIdx = (uint16_t) (vert - base); | 395 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
280 subpathIdxStart = currIdx; | 396 return false; |
281 ++subpath; | 397 } |
398 | |
399 if (this->isHairline() != that->isHairline()) { | |
400 return false; | |
401 } | |
402 | |
403 fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin()) ; | |
404 return true; | |
405 } | |
406 | |
407 bool createGeom(void* vertices, | |
408 size_t vertexOffset, | |
409 void* indices, | |
410 size_t indexOffset, | |
411 int* vertexCnt, | |
412 int* indexCnt, | |
413 const SkPath& path, | |
414 SkScalar srcSpaceTol, | |
415 bool isIndexed) { | |
416 { | |
417 SkScalar srcSpaceTolSqd = SkScalarMul(srcSpaceTol, srcSpaceTol); | |
418 | |
419 uint16_t* idxBase = reinterpret_cast<uint16_t*>(indices) + indexOffs et; | |
420 uint16_t* idx = idxBase; | |
421 uint16_t subpathIdxStart = vertexOffset; | |
422 | |
423 SkPoint* base = reinterpret_cast<SkPoint*>(vertices) + vertexOffset; | |
424 SkPoint* vert = base; | |
425 | |
426 SkPoint pts[4]; | |
427 | |
428 bool first = true; | |
429 int subpath = 0; | |
430 | |
431 SkPath::Iter iter(path, false); | |
432 | |
433 bool done = false; | |
434 while (!done) { | |
435 SkPath::Verb verb = iter.next(pts); | |
436 switch (verb) { | |
437 case SkPath::kMove_Verb: | |
438 if (!first) { | |
439 uint16_t currIdx = (uint16_t) (vert - base) + vertex Offset; | |
440 subpathIdxStart = currIdx; | |
441 ++subpath; | |
442 } | |
443 *vert = pts[0]; | |
444 vert++; | |
445 break; | |
446 case SkPath::kLine_Verb: | |
447 if (isIndexed) { | |
448 uint16_t prevIdx = (uint16_t)(vert - base) - 1 + ver texOffset; | |
449 append_countour_edge_indices(this->isHairline(), sub pathIdxStart, | |
450 prevIdx, &idx); | |
451 } | |
452 *(vert++) = pts[1]; | |
453 break; | |
454 case SkPath::kConic_Verb: { | |
455 SkScalar weight = iter.conicWeight(); | |
456 SkAutoConicToQuads converter; | |
457 // Converting in src-space, hance the finer tolerance (0 .25) | |
458 // TODO: find a way to do this in dev-space so the toler ance means something | |
459 const SkPoint* quadPts = converter.computeQuads(pts, wei ght, 0.25f); | |
460 for (int i = 0; i < converter.countQuads(); ++i) { | |
461 add_quad(&vert, base, quadPts + i*2, srcSpaceTolSqd, srcSpaceTol, | |
462 isIndexed, this->isHairline(), subpathIdxSt art, vertexOffset, &idx); | |
egdaniel
2015/02/18 15:16:57
100 chars
| |
463 } | |
464 break; | |
465 } | |
466 case SkPath::kQuad_Verb: | |
467 add_quad(&vert, base, pts, srcSpaceTolSqd, srcSpaceTol, isIndexed, | |
468 this->isHairline(), subpathIdxStart, vertexOffs et, &idx); | |
469 break; | |
470 case SkPath::kCubic_Verb: { | |
471 // first pt of cubic is the pt we ended on in previous s tep | |
472 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1 + ver texOffset; | |
473 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicP oints( | |
474 pts[0], pts[1], pts[2], pts[3], | |
475 srcSpaceTolSqd, &vert, | |
476 GrPathUtils::cubicPointCount(pts, srcSpa ceTol)); | |
477 if (isIndexed) { | |
478 for (uint16_t i = 0; i < numPts; ++i) { | |
479 append_countour_edge_indices(this->isHairline(), subpathIdxStart, | |
480 firstCPtIdx + i, &i dx); | |
481 } | |
482 } | |
483 break; | |
484 } | |
485 case SkPath::kClose_Verb: | |
486 break; | |
487 case SkPath::kDone_Verb: | |
488 // uint16_t currIdx = (uint16_t) (vert - base); | |
egdaniel
2015/02/18 15:16:57
is the commented line needed for any reason
| |
489 done = true; | |
282 } | 490 } |
283 *vert = pts[0]; | 491 first = false; |
284 vert++; | |
285 break; | |
286 case SkPath::kLine_Verb: | |
287 if (indexed) { | |
288 uint16_t prevIdx = (uint16_t)(vert - base) - 1; | |
289 append_countour_edge_indices(isHairline, subpathIdxStart, | |
290 prevIdx, &idx); | |
291 } | |
292 *(vert++) = pts[1]; | |
293 break; | |
294 case SkPath::kConic_Verb: { | |
295 SkScalar weight = iter.conicWeight(); | |
296 SkAutoConicToQuads converter; | |
297 // Converting in src-space, hance the finer tolerance (0.25) | |
298 // TODO: find a way to do this in dev-space so the tolerance mea ns something | |
299 const SkPoint* quadPts = converter.computeQuads(pts, weight, 0.2 5f); | |
300 for (int i = 0; i < converter.countQuads(); ++i) { | |
301 add_quad(&vert, base, quadPts + i*2, srcSpaceTolSqd, srcSpac eTol, indexed, | |
302 isHairline, subpathIdxStart, &idx); | |
303 } | |
304 break; | |
305 } | 492 } |
306 case SkPath::kQuad_Verb: | 493 |
egdaniel
2015/02/18 15:16:57
was there a reason to remove the asserts in that w
joshualitt
2015/02/20 14:31:46
I put an assert at the end of the whole thing(line
| |
307 add_quad(&vert, base, pts, srcSpaceTolSqd, srcSpaceTol, indexed, | 494 *vertexCnt = static_cast<int>(vert - base); |
308 isHairline, subpathIdxStart, &idx); | 495 *indexCnt = static_cast<int>(idx - idxBase); |
309 break; | 496 |
310 case SkPath::kCubic_Verb: { | 497 } |
311 // first pt of cubic is the pt we ended on in previous step | 498 return true; |
312 uint16_t firstCPtIdx = (uint16_t)(vert - base) - 1; | 499 } |
313 uint16_t numPts = (uint16_t) GrPathUtils::generateCubicPoints( | 500 |
314 pts[0], pts[1], pts[2], pts[3], | 501 GrColor color() const { return fBatch.fColor; } |
315 srcSpaceTolSqd, &vert, | 502 uint8_t coverage() const { return fBatch.fCoverage; } |
316 GrPathUtils::cubicPointCount(pts, srcSpaceTol)); | 503 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
317 if (indexed) { | 504 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
318 for (uint16_t i = 0; i < numPts; ++i) { | 505 bool isHairline() const { return fBatch.fIsHairline; } |
319 append_countour_edge_indices(isHairline, subpathIdxStart , | 506 |
320 firstCPtIdx + i, &idx); | 507 struct BatchTracker { |
321 } | 508 GrColor fColor; |
322 } | 509 uint8_t fCoverage; |
323 break; | 510 SkMatrix fViewMatrix; |
324 } | 511 bool fUsesLocalCoords; |
325 case SkPath::kClose_Verb: | 512 bool fColorIgnored; |
326 break; | 513 bool fCoverageIgnored; |
327 case SkPath::kDone_Verb: | 514 bool fIsHairline; |
328 // uint16_t currIdx = (uint16_t) (vert - base); | 515 }; |
329 goto FINISHED; | 516 |
330 } | 517 BatchTracker fBatch; |
331 first = false; | 518 SkSTArray<1, Geometry, true> fGeoData; |
332 } | 519 }; |
333 FINISHED: | |
334 SkASSERT((vert - base) <= maxPts); | |
335 SkASSERT((idx - idxBase) <= maxIdxs); | |
336 | |
337 *vertexCnt = static_cast<int>(vert - base); | |
338 *indexCnt = static_cast<int>(idx - idxBase); | |
339 | |
340 } | |
341 return true; | |
342 } | |
343 | 520 |
344 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, | 521 bool GrDefaultPathRenderer::internalDrawPath(GrDrawTarget* target, |
345 GrPipelineBuilder* pipelineBuilder, | 522 GrPipelineBuilder* pipelineBuilder, |
346 GrColor color, | 523 GrColor color, |
347 const SkMatrix& viewMatrix, | 524 const SkMatrix& viewMatrix, |
348 const SkPath& path, | 525 const SkPath& path, |
349 const SkStrokeRec& origStroke, | 526 const SkStrokeRec& origStroke, |
350 bool stencilOnly) { | 527 bool stencilOnly) { |
351 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); | 528 SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); |
352 | 529 |
353 SkScalar hairlineCoverage; | 530 SkScalar hairlineCoverage; |
354 uint8_t newCoverage = 0xff; | 531 uint8_t newCoverage = 0xff; |
355 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { | 532 if (IsStrokeHairlineOrEquivalent(*stroke, viewMatrix, &hairlineCoverage)) { |
356 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); | 533 newCoverage = SkScalarRoundToInt(hairlineCoverage * 0xff); |
357 | 534 |
358 if (!stroke->isHairlineStyle()) { | 535 if (!stroke->isHairlineStyle()) { |
359 stroke.writable()->setHairlineStyle(); | 536 stroke.writable()->setHairlineStyle(); |
360 } | 537 } |
361 } | 538 } |
362 | 539 |
363 SkScalar tol = SK_Scalar1; | 540 const bool isHairline = stroke->isHairlineStyle(); |
364 tol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, path.getBounds()); | |
365 | 541 |
366 int vertexCnt; | |
367 int indexCnt; | |
368 GrPrimitiveType primType; | |
369 GrDrawTarget::AutoReleaseGeometry arg; | |
370 if (!this->createGeom(target, | |
371 pipelineBuilder, | |
372 &primType, | |
373 &vertexCnt, | |
374 &indexCnt, | |
375 &arg, | |
376 path, | |
377 *stroke, | |
378 tol)) { | |
379 return false; | |
380 } | |
381 // Save the current xp on the draw state so we can reset it if needed | 542 // Save the current xp on the draw state so we can reset it if needed |
382 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXP Factory())); | 543 SkAutoTUnref<const GrXPFactory> backupXPFactory(SkRef(pipelineBuilder->getXP Factory())); |
383 // face culling doesn't make sense here | 544 // face culling doesn't make sense here |
384 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace() ); | 545 SkASSERT(GrPipelineBuilder::kBoth_DrawFace == pipelineBuilder->getDrawFace() ); |
385 | 546 |
386 int passCount = 0; | 547 int passCount = 0; |
387 const GrStencilSettings* passes[3]; | 548 const GrStencilSettings* passes[3]; |
388 GrPipelineBuilder::DrawFace drawFace[3]; | 549 GrPipelineBuilder::DrawFace drawFace[3]; |
389 bool reverse = false; | 550 bool reverse = false; |
390 bool lastPassIsBounds; | 551 bool lastPassIsBounds; |
391 | 552 |
392 if (stroke->isHairlineStyle()) { | 553 if (isHairline) { |
393 passCount = 1; | 554 passCount = 1; |
394 if (stencilOnly) { | 555 if (stencilOnly) { |
395 passes[0] = &gDirectToStencil; | 556 passes[0] = &gDirectToStencil; |
396 } else { | 557 } else { |
397 passes[0] = NULL; | 558 passes[0] = NULL; |
398 } | 559 } |
399 lastPassIsBounds = false; | 560 lastPassIsBounds = false; |
400 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; | 561 drawFace[0] = GrPipelineBuilder::kBoth_DrawFace; |
401 } else { | 562 } else { |
402 if (single_pass_path(path, *stroke)) { | 563 if (single_pass_path(path, *stroke)) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 } | 629 } |
469 } | 630 } |
470 break; | 631 break; |
471 default: | 632 default: |
472 SkDEBUGFAIL("Unknown path fFill!"); | 633 SkDEBUGFAIL("Unknown path fFill!"); |
473 return false; | 634 return false; |
474 } | 635 } |
475 } | 636 } |
476 } | 637 } |
477 | 638 |
639 SkScalar tol = SK_Scalar1; | |
640 SkScalar srcSpaceTol = GrPathUtils::scaleToleranceToSrc(tol, viewMatrix, pat h.getBounds()); | |
641 | |
478 SkRect devBounds; | 642 SkRect devBounds; |
479 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB ounds); | 643 GetPathDevBounds(path, pipelineBuilder->getRenderTarget(), viewMatrix, &devB ounds); |
480 | 644 |
481 for (int p = 0; p < passCount; ++p) { | 645 for (int p = 0; p < passCount; ++p) { |
482 pipelineBuilder->setDrawFace(drawFace[p]); | 646 pipelineBuilder->setDrawFace(drawFace[p]); |
483 if (passes[p]) { | 647 if (passes[p]) { |
484 *pipelineBuilder->stencil() = *passes[p]; | 648 *pipelineBuilder->stencil() = *passes[p]; |
485 } | 649 } |
486 | 650 |
487 if (lastPassIsBounds && (p == passCount-1)) { | 651 if (lastPassIsBounds && (p == passCount-1)) { |
(...skipping 18 matching lines...) Expand all Loading... | |
506 bounds = path.getBounds(); | 670 bounds = path.getBounds(); |
507 } | 671 } |
508 GrDrawTarget::AutoGeometryPush agp(target); | 672 GrDrawTarget::AutoGeometryPush agp(target); |
509 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S kMatrix::I() : | 673 const SkMatrix& viewM = (reverse && viewMatrix.hasPerspective()) ? S kMatrix::I() : |
510 v iewMatrix; | 674 v iewMatrix; |
511 target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &local Matrix); | 675 target->drawRect(pipelineBuilder, color, viewM, bounds, NULL, &local Matrix); |
512 } else { | 676 } else { |
513 if (passCount > 1) { | 677 if (passCount > 1) { |
514 pipelineBuilder->setDisableColorXPFactory(); | 678 pipelineBuilder->setDisableColorXPFactory(); |
515 } | 679 } |
516 GrPipelineBuilder::AutoRestoreEffects are(pipelineBuilder); | 680 |
517 SkAutoTUnref<const GrGeometryProcessor> gp( | 681 DefaultPathBatch::Geometry geometry; |
518 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPo sition_GPType, | 682 geometry.fColor = color; |
519 color, | 683 geometry.fPath = path; |
520 viewMatrix, | 684 geometry.fTolerance = srcSpaceTol; |
521 SkMatrix::I(), | 685 SkDEBUGCODE(geometry.fDevBounds = devBounds;) |
522 false, | 686 |
523 newCoverage)); | 687 SkAutoTUnref<GrBatch> batch(DefaultPathBatch::Create(geometry, newCo verage, viewMatrix, |
524 if (indexCnt) { | 688 isHairline)); |
525 target->drawIndexed(pipelineBuilder, | 689 |
526 gp, | 690 target->drawBatch(pipelineBuilder, batch, &devBounds); |
527 primType, | |
528 0, | |
529 0, | |
530 vertexCnt, | |
531 indexCnt, | |
532 &devBounds); | |
533 } else { | |
534 target->drawNonIndexed(pipelineBuilder, gp, primType, 0, vertexC nt, &devBounds); | |
535 } | |
536 } | 691 } |
537 } | 692 } |
538 return true; | 693 return true; |
539 } | 694 } |
540 | 695 |
541 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, | 696 bool GrDefaultPathRenderer::canDrawPath(const GrDrawTarget* target, |
542 const GrPipelineBuilder* pipelineBuilder , | 697 const GrPipelineBuilder* pipelineBuilder , |
543 const SkMatrix& viewMatrix, | 698 const SkMatrix& viewMatrix, |
544 const SkPath& path, | 699 const SkPath& path, |
545 const SkStrokeRec& stroke, | 700 const SkStrokeRec& stroke, |
(...skipping 22 matching lines...) Expand all Loading... | |
568 | 723 |
569 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, | 724 void GrDefaultPathRenderer::onStencilPath(GrDrawTarget* target, |
570 GrPipelineBuilder* pipelineBuilder, | 725 GrPipelineBuilder* pipelineBuilder, |
571 const SkMatrix& viewMatrix, | 726 const SkMatrix& viewMatrix, |
572 const SkPath& path, | 727 const SkPath& path, |
573 const SkStrokeRec& stroke) { | 728 const SkStrokeRec& stroke) { |
574 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); | 729 SkASSERT(SkPath::kInverseEvenOdd_FillType != path.getFillType()); |
575 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); | 730 SkASSERT(SkPath::kInverseWinding_FillType != path.getFillType()); |
576 this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, p ath, stroke, true); | 731 this->internalDrawPath(target, pipelineBuilder, GrColor_WHITE, viewMatrix, p ath, stroke, true); |
577 } | 732 } |
OLD | NEW |