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

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: Integrated cache invalidation based on SkPath GenID change 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 bool cacheMatch(GrVertexBuffer* vertexBuffer, const SkMatrix& newMatrix) {
1339 if (!vertexBuffer) {
1340 return false;
1341 }
1342 const SkData* data = vertexBuffer->getCustomData();
1343 if (!data || !data->data()) { // path is linear; matches any scale
1344 return true;
1345 }
1346 const SkSize* cachedScale = static_cast<const SkSize*>(data->data());
bsalomon 2015/07/28 14:55:48 Rather than use the data on the VB, can we canonic
Stephen White 2015/07/28 15:10:28 I could do that, but then a single path with an an
bsalomon 2015/07/28 21:23:30 That makes sense. I wonder if there is an efficien
Stephen White 2015/07/28 22:11:23 I've done the latter (I think..)
1347 SkASSERT(cachedScale);
1348 SkSize newScale;
1349 if (!newMatrix.decomposeScale(&newScale)) {
1350 return false;
1351 }
1352 if (newScale.width() > 0.01f * cachedScale->width() && newScale.width() < 3. 0f * cachedScale->width()
1353 && newScale.height() > 0.01f * cachedScale->height() && newScale.height() < 3.0f * cachedScale->height()) {
1354 return true;
1355 }
1356 return false;
1357 }
1358
1332 }; 1359 };
1333 1360
1334 GrTessellatingPathRenderer::GrTessellatingPathRenderer() { 1361 GrTessellatingPathRenderer::GrTessellatingPathRenderer(GrContext* context) : fCo ntext(context) {
1335 } 1362 }
1336 1363
1337 GrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport( 1364 GrPathRenderer::StencilSupport GrTessellatingPathRenderer::onGetStencilSupport(
1338 const GrDrawTarget*, 1365 const GrDrawTarget*,
1339 const GrPipelineBuil der*, 1366 const GrPipelineBuil der*,
1340 const SkPath&, 1367 const SkPath&,
1341 const GrStrokeInfo&) const { 1368 const GrStrokeInfo&) const {
1342 return GrPathRenderer::kNoSupport_StencilSupport; 1369 return GrPathRenderer::kNoSupport_StencilSupport;
1343 } 1370 }
1344 1371
1372 namespace {
1373
1374 // When the SkPathRef genID changes, invalidate a corresponding GrResource descr ibed by key.
1375 class PathInvalidator : public SkPathRef::GenIDChangeListener {
1376 public:
1377 explicit PathInvalidator(const GrUniqueKey& key) : fMsg(key) {}
1378 private:
1379 GrUniqueKeyInvalidatedMessage fMsg;
1380
1381 void onChange() override {
1382 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(fMsg);
1383 }
1384 };
1385
1386 } // namespace
1387
1388
1345 bool GrTessellatingPathRenderer::canDrawPath(const GrDrawTarget* target, 1389 bool GrTessellatingPathRenderer::canDrawPath(const GrDrawTarget* target,
1346 const GrPipelineBuilder* pipelineBu ilder, 1390 const GrPipelineBuilder* pipelineBu ilder,
1347 const SkMatrix& viewMatrix, 1391 const SkMatrix& viewMatrix,
1348 const SkPath& path, 1392 const SkPath& path,
1349 const GrStrokeInfo& stroke, 1393 const GrStrokeInfo& stroke,
1350 bool antiAlias) const { 1394 bool antiAlias) const {
1351 // This path renderer can draw all fill styles, but does not do antialiasing . It can do convex 1395 // This path renderer can draw all fill styles, but does not do antialiasing . It can do convex
1352 // and concave paths, but we'll leave the convex ones to simpler algorithms. 1396 // and concave paths, but we'll leave the convex ones to simpler algorithms.
1353 return stroke.isFillStyle() && !antiAlias && !path.isConvex(); 1397 return stroke.isFillStyle() && !antiAlias && !path.isConvex();
1354 } 1398 }
1355 1399
1356 class TessellatingPathBatch : public GrBatch { 1400 class TessellatingPathBatch : public GrBatch {
1357 public: 1401 public:
1358 1402
1359 static GrBatch* Create(const GrColor& color, 1403 static GrBatch* Create(const GrColor& color,
1360 const SkPath& path, 1404 const SkPath& path,
1361 const SkMatrix& viewMatrix, 1405 const SkMatrix& viewMatrix,
1362 SkRect clipBounds) { 1406 SkRect clipBounds,
1363 return SkNEW_ARGS(TessellatingPathBatch, (color, path, viewMatrix, clipB ounds)); 1407 GrContext* context) {
1408 return SkNEW_ARGS(TessellatingPathBatch, (color, path, viewMatrix, clipB ounds, context));
1364 } 1409 }
1365 1410
1366 const char* name() const override { return "TessellatingPathBatch"; } 1411 const char* name() const override { return "TessellatingPathBatch"; }
1367 1412
1368 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 1413 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
1369 out->setKnownFourComponents(fColor); 1414 out->setKnownFourComponents(fColor);
1370 } 1415 }
1371 1416
1372 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { 1417 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
1373 out->setUnknownSingleComponent(); 1418 out->setUnknownSingleComponent();
1374 } 1419 }
1375 1420
1376 void initBatchTracker(const GrPipelineInfo& init) override { 1421 void initBatchTracker(const GrPipelineInfo& init) override {
1377 // Handle any color overrides 1422 // Handle any color overrides
1378 if (!init.readsColor()) { 1423 if (!init.readsColor()) {
1379 fColor = GrColor_ILLEGAL; 1424 fColor = GrColor_ILLEGAL;
1380 } 1425 }
1381 init.getOverrideColorIfSet(&fColor); 1426 init.getOverrideColorIfSet(&fColor);
1382 fPipelineInfo = init; 1427 fPipelineInfo = init;
1383 } 1428 }
1384 1429
1385 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override { 1430 int tessellate(const GrUniqueKey& key, SkAutoTUnref<GrVertexBuffer>& vertexB uffer) {
1386 SkRect pathBounds = fPath.getBounds(); 1431 SkRect pathBounds = fPath.getBounds();
1387 Comparator c; 1432 Comparator c;
1388 if (pathBounds.width() > pathBounds.height()) { 1433 if (pathBounds.width() > pathBounds.height()) {
1389 c.sweep_lt = sweep_lt_horiz; 1434 c.sweep_lt = sweep_lt_horiz;
1390 c.sweep_gt = sweep_gt_horiz; 1435 c.sweep_gt = sweep_gt_horiz;
1391 } else { 1436 } else {
1392 c.sweep_lt = sweep_lt_vert; 1437 c.sweep_lt = sweep_lt_vert;
1393 c.sweep_gt = sweep_gt_vert; 1438 c.sweep_gt = sweep_gt_vert;
1394 } 1439 }
1395 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance; 1440 SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
1396 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix, pathBounds); 1441 SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, fViewMat rix, pathBounds);
1397 int contourCnt; 1442 int contourCnt;
1398 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); 1443 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol);
1399 if (maxPts <= 0) { 1444 if (maxPts <= 0) {
1400 return; 1445 return 0;
1401 } 1446 }
1402 if (maxPts > ((int)SK_MaxU16 + 1)) { 1447 if (maxPts > ((int)SK_MaxU16 + 1)) {
1403 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); 1448 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts);
1404 return; 1449 return 0;
1405 } 1450 }
1406 SkPath::FillType fillType = fPath.getFillType(); 1451 SkPath::FillType fillType = fPath.getFillType();
1407 if (SkPath::IsInverseFillType(fillType)) { 1452 if (SkPath::IsInverseFillType(fillType)) {
1408 contourCnt++; 1453 contourCnt++;
1409 } 1454 }
1410 1455
1411 LOG("got %d pts, %d contours\n", maxPts, contourCnt); 1456 LOG("got %d pts, %d contours\n", maxPts, contourCnt);
1412 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1413 SkAutoTUnref<const GrGeometryProcessor> gp(
1414 GrDefaultGeoProcFactory::Create(flags, fColor, fPipelineInfo.readsLo calCoords(),
1415 !fPipelineInfo.readsCoverage(), fVie wMatrix,
1416 SkMatrix::I()));
1417 batchTarget->initDraw(gp, pipeline);
1418
1419 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); 1457 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt));
1420 1458
1421 // For the initial size of the chunk allocator, estimate based on the po int count: 1459 // For the initial size of the chunk allocator, estimate based on the po int count:
1422 // one vertex per point for the initial passes, plus two for the vertice s in the 1460 // one vertex per point for the initial passes, plus two for the vertice s in the
1423 // resulting Polys, since the same point may end up in two Polys. Assum e minimal 1461 // resulting Polys, since the same point may end up in two Polys. Assum e minimal
1424 // connectivity of one Edge per Vertex (will grow for intersections). 1462 // connectivity of one Edge per Vertex (will grow for intersections).
1425 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); 1463 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
1426 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc); 1464 bool isLinear;
1465 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc, &isLine ar);
1427 Poly* polys; 1466 Poly* polys;
1428 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); 1467 polys = contours_to_polys(contours.get(), contourCnt, c, alloc);
1429 int count = 0; 1468 int count = 0;
1430 for (Poly* poly = polys; poly; poly = poly->fNext) { 1469 for (Poly* poly = polys; poly; poly = poly->fNext) {
1431 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) { 1470 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
1432 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); 1471 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3);
1433 } 1472 }
1434 } 1473 }
1435 if (0 == count) { 1474 if (0 == count) {
1436 return; 1475 return 0;
1437 } 1476 }
1438 1477
1439 size_t stride = gp->getVertexStride(); 1478 vertexBuffer.reset(fContext->getGpu()->createVertexBuffer(count * sizeof (SkPoint), false));
1440 SkASSERT(stride == sizeof(SkPoint)); 1479 if (!vertexBuffer.get()) {
1441 const GrVertexBuffer* vertexBuffer;
1442 int firstVertex;
1443 SkPoint* verts = static_cast<SkPoint*>(
1444 batchTarget->makeVertSpace(stride, count, &vertexBuffer, &firstVerte x));
1445 if (!verts) {
1446 SkDebugf("Could not allocate vertices\n"); 1480 SkDebugf("Could not allocate vertices\n");
1447 return; 1481 return 0;
1448 } 1482 }
1449 1483 SkPoint* verts = static_cast<SkPoint*>(vertexBuffer->map());
1450 LOG("emitting %d verts\n", count); 1484 LOG("emitting %d verts\n", count);
1451 SkPoint* end = polys_to_triangles(polys, fillType, verts); 1485 SkPoint* end = polys_to_triangles(polys, fillType, verts);
1486 vertexBuffer->unmap();
1452 int actualCount = static_cast<int>(end - verts); 1487 int actualCount = static_cast<int>(end - verts);
1453 LOG("actual count: %d\n", actualCount); 1488 LOG("actual count: %d\n", actualCount);
1454 SkASSERT(actualCount <= count); 1489 SkASSERT(actualCount <= count);
1455 1490
1491 if (!fPath.isVolatile()) {
1492 SkSize scale;
1493 if (!isLinear && fViewMatrix.decomposeScale(&scale)) {
1494 vertexBuffer->setCustomData(SkData::NewWithCopy(&scale, sizeof(s cale)));
1495 }
1496 fContext->resourceProvider()->assignUniqueKeyToResource(key, vertexB uffer.get());
1497 fPath.pathRef()->addGenIDChangeListener(SkNEW(PathInvalidator(key))) ;
1498 }
1499 return actualCount;
1500 }
1501
1502 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline ) override {
1503 // construct a cache key from the path's genID and the view matrix
1504 static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain() ;
1505 GrUniqueKey key;
1506 GrUniqueKey::Builder builder(&key, kDomain, 1);
1507 builder[0] = fPath.getGenerationID();
1508 builder.finish();
1509 SkAutoTUnref<GrVertexBuffer> vertexBuffer(fContext->resourceProvider()-> findAndRefTByUniqueKey<GrVertexBuffer>(key));
1510 int actualCount;
1511 if (cacheMatch(vertexBuffer.get(), fViewMatrix)) {
1512 actualCount = vertexBuffer->gpuMemorySize() / sizeof(SkPoint);
1513 } else {
1514 actualCount = tessellate(key, vertexBuffer);
1515 }
1516
1517 if (actualCount == 0) {
1518 return;
1519 }
1520
1521 uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
1522 SkAutoTUnref<const GrGeometryProcessor> gp(
1523 GrDefaultGeoProcFactory::Create(flags, fColor, fPipelineInfo.readsLo calCoords(),
1524 !fPipelineInfo.readsCoverage(), fVie wMatrix,
1525 SkMatrix::I()));
1526 batchTarget->initDraw(gp, pipeline);
1527 SkASSERT(gp->getVertexStride() == sizeof(SkPoint));
1528
1456 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType 1529 GrPrimitiveType primitiveType = WIREFRAME ? kLines_GrPrimitiveType
1457 : kTriangles_GrPrimitiveType; 1530 : kTriangles_GrPrimitiveType;
1458 GrVertices vertices; 1531 GrVertices vertices;
1459 vertices.init(primitiveType, vertexBuffer, firstVertex, actualCount); 1532 vertices.init(primitiveType, vertexBuffer.get(), 0, actualCount);
1460 batchTarget->draw(vertices); 1533 batchTarget->draw(vertices);
1461
1462 batchTarget->putBackVertices((size_t)(count - actualCount), stride);
1463 return;
1464 } 1534 }
1465 1535
1466 bool onCombineIfPossible(GrBatch*) override { 1536 bool onCombineIfPossible(GrBatch*) override {
1467 return false; 1537 return false;
1468 } 1538 }
1469 1539
1470 private: 1540 private:
1471 TessellatingPathBatch(const GrColor& color, 1541 TessellatingPathBatch(const GrColor& color,
1472 const SkPath& path, 1542 const SkPath& path,
1473 const SkMatrix& viewMatrix, 1543 const SkMatrix& viewMatrix,
1474 const SkRect& clipBounds) 1544 const SkRect& clipBounds,
1545 GrContext* context)
1475 : fColor(color) 1546 : fColor(color)
1476 , fPath(path) 1547 , fPath(path)
1477 , fViewMatrix(viewMatrix) 1548 , fViewMatrix(viewMatrix)
1478 , fClipBounds(clipBounds) { 1549 , fClipBounds(clipBounds)
1550 , fContext(context) {
1479 this->initClassID<TessellatingPathBatch>(); 1551 this->initClassID<TessellatingPathBatch>();
1480 1552
1481 fBounds = path.getBounds(); 1553 fBounds = path.getBounds();
1482 viewMatrix.mapRect(&fBounds); 1554 viewMatrix.mapRect(&fBounds);
1483 } 1555 }
1484 1556
1485 GrColor fColor; 1557 GrColor fColor;
1486 SkPath fPath; 1558 SkPath fPath;
1487 SkMatrix fViewMatrix; 1559 SkMatrix fViewMatrix;
1488 SkRect fClipBounds; // in source space 1560 SkRect fClipBounds; // in source space
1561 GrContext* fContext;
1489 GrPipelineInfo fPipelineInfo; 1562 GrPipelineInfo fPipelineInfo;
1490 }; 1563 };
1491 1564
1492 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target, 1565 bool GrTessellatingPathRenderer::onDrawPath(GrDrawTarget* target,
1493 GrPipelineBuilder* pipelineBuilder, 1566 GrPipelineBuilder* pipelineBuilder,
1494 GrColor color, 1567 GrColor color,
1495 const SkMatrix& viewM, 1568 const SkMatrix& viewM,
1496 const SkPath& path, 1569 const SkPath& path,
1497 const GrStrokeInfo&, 1570 const GrStrokeInfo&,
1498 bool antiAlias) { 1571 bool antiAlias) {
1499 SkASSERT(!antiAlias); 1572 SkASSERT(!antiAlias);
1500 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 1573 const GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
1501 if (NULL == rt) { 1574 if (NULL == rt) {
1502 return false; 1575 return false;
1503 } 1576 }
1504 1577
1505 SkIRect clipBoundsI; 1578 SkIRect clipBoundsI;
1506 pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI); 1579 pipelineBuilder->clip().getConservativeBounds(rt, &clipBoundsI);
1507 SkRect clipBounds = SkRect::Make(clipBoundsI); 1580 SkRect clipBounds = SkRect::Make(clipBoundsI);
1508 SkMatrix vmi; 1581 SkMatrix vmi;
1509 if (!viewM.invert(&vmi)) { 1582 if (!viewM.invert(&vmi)) {
1510 return false; 1583 return false;
1511 } 1584 }
1512 vmi.mapRect(&clipBounds); 1585 vmi.mapRect(&clipBounds);
1513 SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM , clipBounds)); 1586 SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM , clipBounds, fContext));
1514 target->drawBatch(*pipelineBuilder, batch); 1587 target->drawBatch(*pipelineBuilder, batch);
1515 1588
1516 return true; 1589 return true;
1517 } 1590 }
1518 1591
1519 //////////////////////////////////////////////////////////////////////////////// /////////////////// 1592 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1520 1593
1521 #ifdef GR_TEST_UTILS 1594 #ifdef GR_TEST_UTILS
1522 1595
1523 BATCH_TEST_DEFINE(TesselatingPathBatch) { 1596 BATCH_TEST_DEFINE(TesselatingPathBatch) {
1524 GrColor color = GrRandomColor(random); 1597 GrColor color = GrRandomColor(random);
1525 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); 1598 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random);
1526 SkPath path = GrTest::TestPath(random); 1599 SkPath path = GrTest::TestPath(random);
1527 SkRect clipBounds = GrTest::TestRect(random); 1600 SkRect clipBounds = GrTest::TestRect(random);
1528 SkMatrix vmi; 1601 SkMatrix vmi;
1529 bool result = viewMatrix.invert(&vmi); 1602 bool result = viewMatrix.invert(&vmi);
1530 if (!result) { 1603 if (!result) {
1531 SkFAIL("Cannot invert matrix\n"); 1604 SkFAIL("Cannot invert matrix\n");
1532 } 1605 }
1533 vmi.mapRect(&clipBounds); 1606 vmi.mapRect(&clipBounds);
1534 return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds); 1607 return TessellatingPathBatch::Create(color, path, viewMatrix, clipBounds, co ntext);
1535 } 1608 }
1536 1609
1537 #endif 1610 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698