Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: src/gpu/GrTessellatingPathRenderer.cpp

Issue 1114353004: Implement vertex buffer caching in the tessellated path renderer. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Update to ToT; remove GrContext and use GrResourceProvider directly Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 cacheMatch(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 > 0.01f * tol && info->fToler ance < 3.0f * tol)) {
bsalomon 2015/08/03 18:08:26 nit, col limit
Stephen White 2015/08/03 18:54:41 Fixed (by removing lower bound).
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
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, GrResourceProvider* resourceProvider, SkAut oTUnref<GrVertexBuffer>& vertexBuffer) {
bsalomon 2015/08/03 18:08:27 nit, col limit
Stephen White 2015/08/03 18:54:41 Done.
1381 SkRect pathBounds = fPath.getBounds(); 1422 SkRect pathBounds = fPath.getBounds();
1382 Comparator c; 1423 Comparator c;
1383 if (pathBounds.width() > pathBounds.height()) { 1424 if (pathBounds.width() > pathBounds.height()) {
1384 c.sweep_lt = sweep_lt_horiz; 1425 c.sweep_lt = sweep_lt_horiz;
1385 c.sweep_gt = sweep_gt_horiz; 1426 c.sweep_gt = sweep_gt_horiz;
1386 } else { 1427 } else {
1387 c.sweep_lt = sweep_lt_vert; 1428 c.sweep_lt = sweep_lt_vert;
1388 c.sweep_gt = sweep_gt_vert; 1429 c.sweep_gt = sweep_gt_vert;
1389 } 1430 }
1390 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; 1431 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
1391 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix, pathBounds); 1432 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix, pathBounds);
1392 int contourCnt; 1433 int contourCnt;
1393 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); 1434 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol);
1394 if (maxPts <= 0) { 1435 if (maxPts <= 0) {
1395 return; 1436 return 0;
1396 } 1437 }
1397 if (maxPts > ((int)SK_MaxU16 + 1)) { 1438 if (maxPts > ((int)SK_MaxU16 + 1)) {
1398 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); 1439 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1399 return; 1440 return 0;
1400 } 1441 }
1401 SkPath::FillType fillType = fPath.getFillType(); 1442 SkPath::FillType fillType = fPath.getFillType();
1402 if (SkPath::IsInverseFillType(fillType)) { 1443 if (SkPath::IsInverseFillType(fillType)) {
1403 contourCnt++; 1444 contourCnt++;
1404 } 1445 }
1405 1446
1406 LOG("got %d pts, %d contours\n", maxPts, contourCnt); 1447 LOG("got %d pts, %d contours\n", maxPts, contourCnt);
1407 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1408 SkAutoTUnref<const GrGeometryProcessor> gp(
1409 GrDefaultGeoProcFactory::Create(flags, fColor, fPipelineInfo.readsLo calCoords(),
1410 !fPipelineInfo.readsCoverage(), fVie wMatrix,
1411 SkMatrix::I()));
1412 batchTarget->initDraw(gp, pipeline);
1413
1414 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); 1448 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
1415 1449
1416 // For the initial size of the chunk allocator, estimate based on the po int count: 1450 // For the initial size of the chunk allocator, estimate based on the po int count:
1417 // one vertex per point for the initial passes, plus two for the vertice s in the 1451 // one vertex per point for the initial passes, plus two for the vertice s in the
1418 // resulting Polys, since the same point may end up in two Polys. Assum e minimal 1452 // resulting Polys, since the same point may end up in two Polys. Assum e minimal
1419 // connectivity of one Edge per Vertex (will grow for intersections). 1453 // connectivity of one Edge per Vertex (will grow for intersections).
1420 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); 1454 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
1421 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc); 1455 bool isLinear;
1456 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc, &isLine ar);
1422 Poly* polys; 1457 Poly* polys;
1423 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); 1458 polys = contours_to_polys(contours.get(), contourCnt, c, alloc);
1424 int count = 0; 1459 int count = 0;
1425 for (Poly* poly = polys; poly; poly = poly->fNext) { 1460 for (Poly* poly = polys; poly; poly = poly->fNext) {
1426 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { 1461 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1427 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); 1462 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
1428 } 1463 }
1429 } 1464 }
1430 if (0 == count) { 1465 if (0 == count) {
1431 return; 1466 return 0;
1432 } 1467 }
1433 1468
1434 size_t stride = gp->getVertexStride(); 1469 size_t size = count * sizeof(SkPoint);
1435 SkASSERT(stride == sizeof(SkPoint)); 1470 if (!vertexBuffer.get() || vertexBuffer->gpuMemorySize() < size) {
1436 const GrVertexBuffer* vertexBuffer; 1471 vertexBuffer.reset(resourceProvider->createVertexBuffer(size,
bsalomon 2015/08/03 18:08:27 wrap
Stephen White 2015/08/03 18:54:41 Done.
1437 int firstVertex; 1472 GrResourcePr ovider::kStatic_BufferUsage,
1438 SkPoint* verts = static_cast<SkPoint*>( 1473 0));
1439 batchTarget->makeVertSpace(stride, count, &vertexBuffer, &firstVerte x)); 1474 }
1440 if (!verts) { 1475 if (!vertexBuffer.get()) {
1441 SkDebugf("Could not allocate vertices\n"); 1476 SkDebugf("Could not allocate vertices\n");
1442 return; 1477 return 0;
1443 } 1478 }
1444 1479 SkPoint* verts = static_cast<SkPoint*>(vertexBuffer->map());
1445 LOG("emitting %d verts\n", count); 1480 LOG("emitting %d verts\n", count);
1446 SkPoint* end = polys_to_triangles(polys, fillType, verts); 1481 SkPoint* end = polys_to_triangles(polys, fillType, verts);
1482 vertexBuffer->unmap();
1447 int actualCount = static_cast<int>(end - verts); 1483 int actualCount = static_cast<int>(end - verts);
1448 LOG("actual count: %d\n", actualCount); 1484 LOG("actual count: %d\n", actualCount);
1449 SkASSERT(actualCount <= count); 1485 SkASSERT(actualCount <= count);
1450 1486
1487 if (!fPath.isVolatile()) {
1488 TessInfo info;
1489 info.fTolerance = isLinear ? 0 : tol;
1490 info.fCount = actualCount;
1491 key->setCustomData(SkData::NewWithCopy(&info, sizeof(info)));
1492 resourceProvider->assignUniqueKeyToResource(*key, vertexBuffer.get() );
1493 fPath.pathRef()->addGenIDChangeListener(SkNEW(PathInvalidator(*key)) );
1494 }
1495 return actualCount;
1496 }
1497
1498 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override {
1499 // construct a cache key from the path's genID and the view matrix
1500 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ;
1501 GrUniqueKey key;
1502 GrUniqueKey::Builder builder(&key, kDomain, 2);
1503 builder[0] = fPath.getGenerationID();
1504 builder[1] = fPath.getFillType();
1505 builder.finish();
1506 SkAutoTUnref<GrVertexBuffer> vertexBuffer(batchTarget->resourceProvider( )->findAndRefTByUniqueKey<GrVertexBuffer>(key));
bsalomon 2015/08/03 18:08:27 wrap
Stephen White 2015/08/03 18:54:41 Done.
1507 int actualCount;
1508 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
1509 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix, fPath.getBounds());
bsalomon 2015/08/03 18:08:27 wrap
Stephen White 2015/08/03 18:54:41 Done.
1510 if (!cacheMatch(vertexBuffer.get(), tol, &actualCount)) {
1511 actualCount = tessellate(&key, batchTarget->resourceProvider(), vert exBuffer);
1512 }
1513
1514 if (actualCount == 0) {
1515 return;
1516 }
1517
1518 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1519 SkAutoTUnref<const GrGeometryProcessor> gp(
1520 GrDefaultGeoProcFactory::Create(flags, fColor, fPipelineInfo.readsLo calCoords(),
1521 !fPipelineInfo.readsCoverage(), fVie wMatrix,
1522 SkMatrix::I()));
1523 batchTarget->initDraw(gp, pipeline);
1524 SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
1525
1451 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType 1526 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
1452 : kTriangles_GrPrimitiveType; 1527 : kTriangles_GrPrimitiveType;
1453 GrVertices vertices; 1528 GrVertices vertices;
1454 vertices.init(primitiveType, vertexBuffer, firstVertex, actualCount); 1529 vertices.init(primitiveType, vertexBuffer.get(), 0, actualCount);
1455 batchTarget->draw(vertices); 1530 batchTarget->draw(vertices);
1456
1457 batchTarget->putBackVertices((size_t)(count - actualCount), stride);
1458 return;
1459 } 1531 }
1460 1532
1461 bool onCombineIfPossible(GrBatch*) override { 1533 bool onCombineIfPossible(GrBatch*) override {
1462 return false; 1534 return false;
1463 } 1535 }
1464 1536
1465 private: 1537 private:
1466 TessellatingPathBatch(const GrColor& color, 1538 TessellatingPathBatch(const GrColor& color,
1467 const SkPath& path, 1539 const SkPath& path,
1468 const SkMatrix& viewMatrix, 1540 const SkMatrix& viewMatrix,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1518 SkMatrix vmi; 1590 SkMatrix vmi;
1519 bool result = viewMatrix.invert(&vmi); 1591 bool result = viewMatrix.invert(&vmi);
1520 if (!result) { 1592 if (!result) {
1521 SkFAIL("Cannot invert matrix\n"); 1593 SkFAIL("Cannot invert matrix\n");
1522 } 1594 }
1523 vmi.mapRect(&clipBounds); 1595 vmi.mapRect(&clipBounds);
1524 return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds); 1596 return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds);
1525 } 1597 }
1526 1598
1527 #endif 1599 #endif
OLDNEW
« include/gpu/GrResourceKey.h ('K') | « src/core/SkPathRef.cpp ('k') | tests/PathTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698