OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "GrTessellatingPathRenderer.h" | 8 #include "GrTessellatingPathRenderer.h" |
9 | 9 |
10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
11 #include "GrBatchTarget.h" | 11 #include "GrBatchTarget.h" |
12 #include "GrBatchTest.h" | 12 #include "GrBatchTest.h" |
13 #include "GrDefaultGeoProcFactory.h" | 13 #include "GrDefaultGeoProcFactory.h" |
14 #include "GrPathUtils.h" | 14 #include "GrPathUtils.h" |
15 #include "GrVertices.h" | 15 #include "GrVertices.h" |
| 16 #include "GrResourceCache.h" |
| 17 #include "GrResourceProvider.h" |
16 #include "SkChunkAlloc.h" | 18 #include "SkChunkAlloc.h" |
17 #include "SkGeometry.h" | 19 #include "SkGeometry.h" |
18 | 20 |
19 #include <stdio.h> | 21 #include <stdio.h> |
20 | 22 |
21 /* | 23 /* |
22 * This path renderer tessellates the path into triangles, uploads the triangles
to a | 24 * This path renderer tessellates the path into triangles, uploads the triangles
to a |
23 * vertex buffer, and renders them with a single draw call. It does not currentl
y do | 25 * vertex buffer, and renders them with a single draw call. It does not currentl
y do |
24 * antialiasing, so it must be used in conjunction with multisampling. | 26 * antialiasing, so it must be used in conjunction with multisampling. |
25 * | 27 * |
(...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1]
.fY) }; | 533 const SkPoint s = { SkScalarAve(r[0].fX, r[1].fX), SkScalarAve(r[0].fY, r[1]
.fY) }; |
532 pointsLeft >>= 1; | 534 pointsLeft >>= 1; |
533 prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLe
ft, alloc); | 535 prev = generate_cubic_points(p0, q[0], r[0], s, tolSqd, prev, head, pointsLe
ft, alloc); |
534 prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLe
ft, alloc); | 536 prev = generate_cubic_points(s, r[1], q[2], p3, tolSqd, prev, head, pointsLe
ft, alloc); |
535 return prev; | 537 return prev; |
536 } | 538 } |
537 | 539 |
538 // Stage 1: convert the input path to a set of linear contours (linked list of V
ertices). | 540 // Stage 1: convert the input path to a set of linear contours (linked list of V
ertices). |
539 | 541 |
540 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
Bounds, | 542 void path_to_contours(const SkPath& path, SkScalar tolerance, const SkRect& clip
Bounds, |
541 Vertex** contours, SkChunkAlloc& alloc) { | 543 Vertex** contours, SkChunkAlloc& alloc, bool *isLinear) { |
542 | 544 |
543 SkScalar toleranceSqd = tolerance * tolerance; | 545 SkScalar toleranceSqd = tolerance * tolerance; |
544 | 546 |
545 SkPoint pts[4]; | 547 SkPoint pts[4]; |
546 bool done = false; | 548 bool done = false; |
| 549 *isLinear = true; |
547 SkPath::Iter iter(path, false); | 550 SkPath::Iter iter(path, false); |
548 Vertex* prev = NULL; | 551 Vertex* prev = NULL; |
549 Vertex* head = NULL; | 552 Vertex* head = NULL; |
550 if (path.isInverseFillType()) { | 553 if (path.isInverseFillType()) { |
551 SkPoint quad[4]; | 554 SkPoint quad[4]; |
552 clipBounds.toQuad(quad); | 555 clipBounds.toQuad(quad); |
553 for (int i = 3; i >= 0; i--) { | 556 for (int i = 3; i >= 0; i--) { |
554 prev = append_point_to_contour(quad[i], prev, &head, alloc); | 557 prev = append_point_to_contour(quad[i], prev, &head, alloc); |
555 } | 558 } |
556 head->fPrev = prev; | 559 head->fPrev = prev; |
557 prev->fNext = head; | 560 prev->fNext = head; |
558 *contours++ = head; | 561 *contours++ = head; |
559 head = prev = NULL; | 562 head = prev = NULL; |
560 } | 563 } |
561 SkAutoConicToQuads converter; | 564 SkAutoConicToQuads converter; |
562 while (!done) { | 565 while (!done) { |
563 SkPath::Verb verb = iter.next(pts); | 566 SkPath::Verb verb = iter.next(pts); |
564 switch (verb) { | 567 switch (verb) { |
565 case SkPath::kConic_Verb: { | 568 case SkPath::kConic_Verb: { |
566 SkScalar weight = iter.conicWeight(); | 569 SkScalar weight = iter.conicWeight(); |
567 const SkPoint* quadPts = converter.computeQuads(pts, weight, tol
eranceSqd); | 570 const SkPoint* quadPts = converter.computeQuads(pts, weight, tol
eranceSqd); |
568 for (int i = 0; i < converter.countQuads(); ++i) { | 571 for (int i = 0; i < converter.countQuads(); ++i) { |
569 int pointsLeft = GrPathUtils::quadraticPointCount(quadPts, t
olerance); | 572 int pointsLeft = GrPathUtils::quadraticPointCount(quadPts, t
olerance); |
570 prev = generate_quadratic_points(quadPts[0], quadPts[1], qua
dPts[2], | 573 prev = generate_quadratic_points(quadPts[0], quadPts[1], qua
dPts[2], |
571 toleranceSqd, prev, &head,
pointsLeft, alloc); | 574 toleranceSqd, prev, &head,
pointsLeft, alloc); |
572 quadPts += 2; | 575 quadPts += 2; |
573 } | 576 } |
| 577 *isLinear = false; |
574 break; | 578 break; |
575 } | 579 } |
576 case SkPath::kMove_Verb: | 580 case SkPath::kMove_Verb: |
577 if (head) { | 581 if (head) { |
578 head->fPrev = prev; | 582 head->fPrev = prev; |
579 prev->fNext = head; | 583 prev->fNext = head; |
580 *contours++ = head; | 584 *contours++ = head; |
581 } | 585 } |
582 head = prev = NULL; | 586 head = prev = NULL; |
583 prev = append_point_to_contour(pts[0], prev, &head, alloc); | 587 prev = append_point_to_contour(pts[0], prev, &head, alloc); |
584 break; | 588 break; |
585 case SkPath::kLine_Verb: { | 589 case SkPath::kLine_Verb: { |
586 prev = append_point_to_contour(pts[1], prev, &head, alloc); | 590 prev = append_point_to_contour(pts[1], prev, &head, alloc); |
587 break; | 591 break; |
588 } | 592 } |
589 case SkPath::kQuad_Verb: { | 593 case SkPath::kQuad_Verb: { |
590 int pointsLeft = GrPathUtils::quadraticPointCount(pts, tolerance
); | 594 int pointsLeft = GrPathUtils::quadraticPointCount(pts, tolerance
); |
591 prev = generate_quadratic_points(pts[0], pts[1], pts[2], toleran
ceSqd, prev, | 595 prev = generate_quadratic_points(pts[0], pts[1], pts[2], toleran
ceSqd, prev, |
592 &head, pointsLeft, alloc); | 596 &head, pointsLeft, alloc); |
| 597 *isLinear = false; |
593 break; | 598 break; |
594 } | 599 } |
595 case SkPath::kCubic_Verb: { | 600 case SkPath::kCubic_Verb: { |
596 int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance); | 601 int pointsLeft = GrPathUtils::cubicPointCount(pts, tolerance); |
597 prev = generate_cubic_points(pts[0], pts[1], pts[2], pts[3], | 602 prev = generate_cubic_points(pts[0], pts[1], pts[2], pts[3], |
598 toleranceSqd, prev, &head, pointsLeft, alloc); | 603 toleranceSqd, prev, &head, pointsLeft, alloc); |
| 604 *isLinear = false; |
599 break; | 605 break; |
600 } | 606 } |
601 case SkPath::kClose_Verb: | 607 case SkPath::kClose_Verb: |
602 if (head) { | 608 if (head) { |
603 head->fPrev = prev; | 609 head->fPrev = prev; |
604 prev->fNext = head; | 610 prev->fNext = head; |
605 *contours++ = head; | 611 *contours++ = head; |
606 } | 612 } |
607 head = prev = NULL; | 613 head = prev = NULL; |
608 break; | 614 break; |
(...skipping 713 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1322 SkPoint* polys_to_triangles(Poly* polys, SkPath::FillType fillType, SkPoint* dat
a) { | 1328 SkPoint* polys_to_triangles(Poly* polys, SkPath::FillType fillType, SkPoint* dat
a) { |
1323 SkPoint* d = data; | 1329 SkPoint* d = data; |
1324 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1330 for (Poly* poly = polys; poly; poly = poly->fNext) { |
1325 if (apply_fill_type(fillType, poly->fWinding)) { | 1331 if (apply_fill_type(fillType, poly->fWinding)) { |
1326 d = poly->emit(d); | 1332 d = poly->emit(d); |
1327 } | 1333 } |
1328 } | 1334 } |
1329 return d; | 1335 return d; |
1330 } | 1336 } |
1331 | 1337 |
| 1338 struct TessInfo { |
| 1339 SkScalar fTolerance; |
| 1340 int fCount; |
| 1341 }; |
| 1342 |
| 1343 bool cache_match(GrVertexBuffer* vertexBuffer, SkScalar tol, int* actualCount) { |
| 1344 if (!vertexBuffer) { |
| 1345 return false; |
| 1346 } |
| 1347 const SkData* data = vertexBuffer->getUniqueKey().getCustomData(); |
| 1348 SkASSERT(data); |
| 1349 const TessInfo* info = static_cast<const TessInfo*>(data->data()); |
| 1350 if (info->fTolerance == 0 || info->fTolerance < 3.0f * tol) { |
| 1351 *actualCount = info->fCount; |
| 1352 return true; |
| 1353 } |
| 1354 return false; |
| 1355 } |
| 1356 |
1332 }; | 1357 }; |
1333 | 1358 |
1334 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { | 1359 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { |
1335 } | 1360 } |
1336 | 1361 |
1337 GrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport( | 1362 GrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport( |
1338 const GrDrawTarget*, | 1363 const GrDrawTarget*, |
1339 const GrPipelineBuil
der*, | 1364 const GrPipelineBuil
der*, |
1340 const SkPath&, | 1365 const SkPath&, |
1341 const GrStrokeInfo&)
const { | 1366 const GrStrokeInfo&)
const { |
1342 return GrPathRenderer::kNoSupport_StencilSupport; | 1367 return GrPathRenderer::kNoSupport_StencilSupport; |
1343 } | 1368 } |
1344 | 1369 |
| 1370 namespace { |
| 1371 |
| 1372 // When the SkPathRef genID changes, invalidate a corresponding GrResource descr
ibed by key. |
| 1373 class PathInvalidator : public SkPathRef::GenIDChangeListener { |
| 1374 public: |
| 1375 explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {} |
| 1376 private: |
| 1377 GrUniqueKeyInvalidatedMessage fMsg; |
| 1378 |
| 1379 void onChange() override { |
| 1380 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg); |
| 1381 } |
| 1382 }; |
| 1383 |
| 1384 } // namespace |
| 1385 |
1345 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons
t { | 1386 bool GrTessellatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) cons
t { |
1346 // This path renderer can draw all fill styles, but does not do antialiasing
. It can do convex | 1387 // This path renderer can draw all fill styles, but does not do antialiasing
. It can do convex |
1347 // and concave paths, but we'll leave the convex ones to simpler algorithms. | 1388 // and concave paths, but we'll leave the convex ones to simpler algorithms. |
1348 return args.fStroke->isFillStyle() && !args.fAntiAlias && !args.fPath->isCon
vex(); | 1389 return args.fStroke->isFillStyle() && !args.fAntiAlias && !args.fPath->isCon
vex(); |
1349 } | 1390 } |
1350 | 1391 |
1351 class TessellatingPathBatch : public GrBatch { | 1392 class TessellatingPathBatch : public GrBatch { |
1352 public: | 1393 public: |
1353 | 1394 |
1354 static GrBatch* Create(const GrColor& color, | 1395 static GrBatch* Create(const GrColor& color, |
(...skipping 15 matching lines...) Expand all Loading... |
1370 | 1411 |
1371 void initBatchTracker(const GrPipelineInfo& init) override { | 1412 void initBatchTracker(const GrPipelineInfo& init) override { |
1372 // Handle any color overrides | 1413 // Handle any color overrides |
1373 if (!init.readsColor()) { | 1414 if (!init.readsColor()) { |
1374 fColor = GrColor_ILLEGAL; | 1415 fColor = GrColor_ILLEGAL; |
1375 } | 1416 } |
1376 init.getOverrideColorIfSet(&fColor); | 1417 init.getOverrideColorIfSet(&fColor); |
1377 fPipelineInfo = init; | 1418 fPipelineInfo = init; |
1378 } | 1419 } |
1379 | 1420 |
1380 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { | 1421 int tessellate(GrUniqueKey* key, |
| 1422 GrResourceProvider* resourceProvider, |
| 1423 SkAutoTUnref<GrVertexBuffer>& vertexBuffer) { |
1381 SkRect pathBounds = fPath.getBounds(); | 1424 SkRect pathBounds = fPath.getBounds(); |
1382 Comparator c; | 1425 Comparator c; |
1383 if (pathBounds.width() > pathBounds.height()) { | 1426 if (pathBounds.width() > pathBounds.height()) { |
1384 c.sweep_lt = sweep_lt_horiz; | 1427 c.sweep_lt = sweep_lt_horiz; |
1385 c.sweep_gt = sweep_gt_horiz; | 1428 c.sweep_gt = sweep_gt_horiz; |
1386 } else { | 1429 } else { |
1387 c.sweep_lt = sweep_lt_vert; | 1430 c.sweep_lt = sweep_lt_vert; |
1388 c.sweep_gt = sweep_gt_vert; | 1431 c.sweep_gt = sweep_gt_vert; |
1389 } | 1432 } |
1390 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; | 1433 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; |
1391 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat
rix, pathBounds); | 1434 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat
rix, pathBounds); |
1392 int contourCnt; | 1435 int contourCnt; |
1393 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); | 1436 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); |
1394 if (maxPts <= 0) { | 1437 if (maxPts <= 0) { |
1395 return; | 1438 return 0; |
1396 } | 1439 } |
1397 if (maxPts > ((int)SK_MaxU16 + 1)) { | 1440 if (maxPts > ((int)SK_MaxU16 + 1)) { |
1398 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); | 1441 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); |
1399 return; | 1442 return 0; |
1400 } | 1443 } |
1401 SkPath::FillType fillType = fPath.getFillType(); | 1444 SkPath::FillType fillType = fPath.getFillType(); |
1402 if (SkPath::IsInverseFillType(fillType)) { | 1445 if (SkPath::IsInverseFillType(fillType)) { |
1403 contourCnt++; | 1446 contourCnt++; |
1404 } | 1447 } |
1405 | 1448 |
1406 LOG("got %d pts, %d contours\n", maxPts, contourCnt); | 1449 LOG("got %d pts, %d contours\n", maxPts, contourCnt); |
1407 SkAutoTUnref<const GrGeometryProcessor> gp; | |
1408 { | |
1409 using namespace GrDefaultGeoProcFactory; | |
1410 | |
1411 Color color(fColor); | |
1412 LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ? | |
1413 LocalCoords::kUsePosition_Type : | |
1414 LocalCoords::kUnused_Type); | |
1415 Coverage::Type coverageType; | |
1416 if (fPipelineInfo.readsCoverage()) { | |
1417 coverageType = Coverage::kSolid_Type; | |
1418 } else { | |
1419 coverageType = Coverage::kNone_Type; | |
1420 } | |
1421 Coverage coverage(coverageType); | |
1422 gp.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoord
s, | |
1423 fViewMatrix)); | |
1424 } | |
1425 batchTarget->initDraw(gp, pipeline); | |
1426 | |
1427 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); | 1450 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); |
1428 | 1451 |
1429 // For the initial size of the chunk allocator, estimate based on the po
int count: | 1452 // For the initial size of the chunk allocator, estimate based on the po
int count: |
1430 // one vertex per point for the initial passes, plus two for the vertice
s in the | 1453 // one vertex per point for the initial passes, plus two for the vertice
s in the |
1431 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal | 1454 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal |
1432 // connectivity of one Edge per Vertex (will grow for intersections). | 1455 // connectivity of one Edge per Vertex (will grow for intersections). |
1433 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); | 1456 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); |
1434 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc); | 1457 bool isLinear; |
| 1458 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc, &isLine
ar); |
1435 Poly* polys; | 1459 Poly* polys; |
1436 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); | 1460 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); |
1437 int count = 0; | 1461 int count = 0; |
1438 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1462 for (Poly* poly = polys; poly; poly = poly->fNext) { |
1439 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3)
{ | 1463 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3)
{ |
1440 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); | 1464 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |
1441 } | 1465 } |
1442 } | 1466 } |
1443 if (0 == count) { | 1467 if (0 == count) { |
1444 return; | 1468 return 0; |
1445 } | 1469 } |
1446 | 1470 |
1447 size_t stride = gp->getVertexStride(); | 1471 size_t size = count * sizeof(SkPoint); |
1448 SkASSERT(stride == sizeof(SkPoint)); | 1472 if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) { |
1449 const GrVertexBuffer* vertexBuffer; | 1473 vertexBuffer.reset(resourceProvider->createVertexBuffer( |
1450 int firstVertex; | 1474 size, GrResourceProvider::kStatic_BufferUsage, 0)); |
1451 SkPoint* verts = static_cast<SkPoint*>( | 1475 } |
1452 batchTarget->makeVertSpace(stride, count, &vertexBuffer, &firstVerte
x)); | 1476 if (!vertexBuffer.get()) { |
1453 if (!verts) { | |
1454 SkDebugf("Could not allocate vertices\n"); | 1477 SkDebugf("Could not allocate vertices\n"); |
1455 return; | 1478 return 0; |
1456 } | 1479 } |
1457 | 1480 SkPoint* verts = static_cast<SkPoint*>(vertexBuffer->map()); |
1458 LOG("emitting %d verts\n", count); | 1481 LOG("emitting %d verts\n", count); |
1459 SkPoint* end = polys_to_triangles(polys, fillType, verts); | 1482 SkPoint* end = polys_to_triangles(polys, fillType, verts); |
| 1483 vertexBuffer->unmap(); |
1460 int actualCount = static_cast<int>(end - verts); | 1484 int actualCount = static_cast<int>(end - verts); |
1461 LOG("actual count: %d\n", actualCount); | 1485 LOG("actual count: %d\n", actualCount); |
1462 SkASSERT(actualCount <= count); | 1486 SkASSERT(actualCount <= count); |
1463 | 1487 |
| 1488 if (!fPath.isVolatile()) { |
| 1489 TessInfo info; |
| 1490 info.fTolerance = isLinear ? 0 : tol; |
| 1491 info.fCount = actualCount; |
| 1492 SkAutoTUnref<SkData> data(SkData::NewWithCopy(&info, sizeof(info))); |
| 1493 key->setCustomData(data.get()); |
| 1494 resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get()
); |
| 1495 SkPathPriv::AddGenIDChangeListener(fPath, SkNEW(PathInvalidator(*key
))); |
| 1496 } |
| 1497 return actualCount; |
| 1498 } |
| 1499 |
| 1500 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { |
| 1501 // construct a cache key from the path's genID and the view matrix |
| 1502 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain()
; |
| 1503 GrUniqueKey key; |
| 1504 int clipBoundsSize32 = |
| 1505 fPath.isInverseFillType() ? sizeof(fClipBounds) / sizeof(uint32_t) :
0; |
| 1506 GrUniqueKey::Builder builder(&key, kDomain, 2 + clipBoundsSize32); |
| 1507 builder[0] = fPath.getGenerationID(); |
| 1508 builder[1] = fPath.getFillType(); |
| 1509 // For inverse fills, the tessellation is dependent on clip bounds. |
| 1510 if (fPath.isInverseFillType()) { |
| 1511 memcpy(&builder[2], &fClipBounds, sizeof(fClipBounds)); |
| 1512 } |
| 1513 builder.finish(); |
| 1514 GrResourceProvider* rp = batchTarget->resourceProvider(); |
| 1515 SkAutoTUnref<GrVertexBuffer> vertexBuffer(rp->findAndRefTByUniqueKey<GrV
ertexBuffer>(key)); |
| 1516 int actualCount; |
| 1517 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; |
| 1518 SkScalar tol = GrPathUtils::scaleToleranceToSrc( |
| 1519 screenSpaceTol, fViewMatrix, fPath.getBounds()); |
| 1520 if (!cache_match(vertexBuffer.get(), tol, &actualCount)) { |
| 1521 actualCount = tessellate(&key, rp, vertexBuffer); |
| 1522 } |
| 1523 |
| 1524 if (actualCount == 0) { |
| 1525 return; |
| 1526 } |
| 1527 |
| 1528 SkAutoTUnref<const GrGeometryProcessor> gp; |
| 1529 { |
| 1530 using namespace GrDefaultGeoProcFactory; |
| 1531 |
| 1532 Color color(fColor); |
| 1533 LocalCoords localCoords(fPipelineInfo.readsLocalCoords() ? |
| 1534 LocalCoords::kUsePosition_Type : |
| 1535 LocalCoords::kUnused_Type); |
| 1536 Coverage::Type coverageType; |
| 1537 if (fPipelineInfo.readsCoverage()) { |
| 1538 coverageType = Coverage::kSolid_Type; |
| 1539 } else { |
| 1540 coverageType = Coverage::kNone_Type; |
| 1541 } |
| 1542 Coverage coverage(coverageType); |
| 1543 gp.reset(GrDefaultGeoProcFactory::Create(color, coverage, localCoord
s, |
| 1544 fViewMatrix)); |
| 1545 } |
| 1546 |
| 1547 batchTarget->initDraw(gp, pipeline); |
| 1548 SkASSERT(gp->getVertexStride() == sizeof(SkPoint)); |
| 1549 |
1464 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType | 1550 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType |
1465 : kTriangles_GrPrimitiveType; | 1551 : kTriangles_GrPrimitiveType; |
1466 GrVertices vertices; | 1552 GrVertices vertices; |
1467 vertices.init(primitiveType, vertexBuffer, firstVertex, actualCount); | 1553 vertices.init(primitiveType, vertexBuffer.get(), 0, actualCount); |
1468 batchTarget->draw(vertices); | 1554 batchTarget->draw(vertices); |
1469 | |
1470 batchTarget->putBackVertices((size_t)(count - actualCount), stride); | |
1471 return; | |
1472 } | 1555 } |
1473 | 1556 |
1474 bool onCombineIfPossible(GrBatch*) override { | 1557 bool onCombineIfPossible(GrBatch*) override { |
1475 return false; | 1558 return false; |
1476 } | 1559 } |
1477 | 1560 |
1478 private: | 1561 private: |
1479 TessellatingPathBatch(const GrColor& color, | 1562 TessellatingPathBatch(const GrColor& color, |
1480 const SkPath& path, | 1563 const SkPath& path, |
1481 const SkMatrix& viewMatrix, | 1564 const SkMatrix& viewMatrix, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1531 SkMatrix vmi; | 1614 SkMatrix vmi; |
1532 bool result = viewMatrix.invert(&vmi); | 1615 bool result = viewMatrix.invert(&vmi); |
1533 if (!result) { | 1616 if (!result) { |
1534 SkFAIL("Cannot invert matrix\n"); | 1617 SkFAIL("Cannot invert matrix\n"); |
1535 } | 1618 } |
1536 vmi.mapRect(&clipBounds); | 1619 vmi.mapRect(&clipBounds); |
1537 return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds); | 1620 return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds); |
1538 } | 1621 } |
1539 | 1622 |
1540 #endif | 1623 #endif |
OLD | NEW |