OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "GrOvalRenderer.h" | 8 #include "GrOvalRenderer.h" |
9 | 9 |
10 #include "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
(...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1328 }; | 1328 }; |
1329 | 1329 |
1330 bool fUsesLocalCoords; | 1330 bool fUsesLocalCoords; |
1331 SkSTArray<1, Geometry, true> fGeoData; | 1331 SkSTArray<1, Geometry, true> fGeoData; |
1332 | 1332 |
1333 typedef GrVertexBatch INHERITED; | 1333 typedef GrVertexBatch INHERITED; |
1334 }; | 1334 }; |
1335 | 1335 |
1336 /////////////////////////////////////////////////////////////////////////////// | 1336 /////////////////////////////////////////////////////////////////////////////// |
1337 | 1337 |
1338 static const uint16_t gRRectIndices[] = { | 1338 // We have three possible cases for geometry for a roundrect. |
1339 // | |
1340 // In the case of a normal fill or a stroke, we draw the roundrect as a 9-patch: | |
1341 // ____________ | |
1342 // |_|________|_| | |
1343 // | | | | | |
1344 // | | | | | |
1345 // | | | | | |
1346 // |_|________|_| | |
1347 // |_|________|_| | |
1348 // | |
1349 // For strokes, we don't draw the center quad. | |
1350 // | |
1351 // For circular roundrects, in the case where the stroke width is greater than t wice | |
1352 // the corner radius (overstroke), we add additional geometry to mark out the re ctangle | |
1353 // in the center: | |
1354 // ____________ | |
1355 // |_|________|_| | |
1356 // | |\ ____ /| | | |
1357 // | | | | | | | |
1358 // | | |____| | | | |
1359 // |_|/______\|_| | |
1360 // |_|________|_| | |
1361 // | |
1362 // We don't draw the center quad from the fill rect in this case. | |
1363 | |
1364 static const uint16_t gRRectOverstrokeIndices[] = { | |
1365 // overstroke quads | |
1366 // we place this at the beginning so that we can skip these indices when ren dering normally | |
1367 5, 6, 17, 5, 17, 16, | |
1368 17, 6, 10, 17, 10, 19, | |
1369 10, 9, 18, 10, 18, 19, | |
1370 18, 9, 5, 18, 5, 16, | |
1371 | |
1339 // corners | 1372 // corners |
1340 0, 1, 5, 0, 5, 4, | 1373 0, 1, 5, 0, 5, 4, |
1341 2, 3, 7, 2, 7, 6, | 1374 2, 3, 7, 2, 7, 6, |
1342 8, 9, 13, 8, 13, 12, | 1375 8, 9, 13, 8, 13, 12, |
1343 10, 11, 15, 10, 15, 14, | 1376 10, 11, 15, 10, 15, 14, |
1344 | 1377 |
1345 // edges | 1378 // edges |
1346 1, 2, 6, 1, 6, 5, | 1379 1, 2, 6, 1, 6, 5, |
1347 4, 5, 9, 4, 9, 8, | 1380 4, 5, 9, 4, 9, 8, |
1348 6, 7, 11, 6, 11, 10, | 1381 6, 7, 11, 6, 11, 10, |
1349 9, 10, 14, 9, 14, 13, | 1382 9, 10, 14, 9, 14, 13, |
1350 | 1383 |
1351 // center | 1384 // center |
1352 // we place this at the end so that we can ignore these indices when renderi ng stroke-only | 1385 // we place this at the end so that we can ignore these indices when not ren dering as filled |
1353 5, 6, 10, 5, 10, 9 | 1386 5, 6, 10, 5, 10, 9, |
1354 }; | 1387 }; |
1355 | 1388 |
1356 static const int kIndicesPerStrokeRRect = SK_ARRAY_COUNT(gRRectIndices) - 6; | 1389 static const uint16_t* gRRectIndices = gRRectOverstrokeIndices + 6*4; |
1357 static const int kIndicesPerRRect = SK_ARRAY_COUNT(gRRectIndices); | 1390 |
1358 static const int kVertsPerRRect = 16; | 1391 // overstroke count is arraysize |
1392 static const int kIndicesPerOverstrokeRRect = SK_ARRAY_COUNT(gRRectOverstrokeInd ices) - 6; | |
1393 static const int kIndicesPerFillRRect = kIndicesPerOverstrokeRRect - 6*4 + 6; | |
1394 static const int kIndicesPerStrokeRRect = kIndicesPerFillRRect - 6; | |
1395 static const int kVertsPerStandardRRect = 16; | |
1396 static const int kVertsPerOverstrokeRRect = 20; | |
1359 static const int kNumRRectsInIndexBuffer = 256; | 1397 static const int kNumRRectsInIndexBuffer = 256; |
1360 | 1398 |
1399 enum RRectType { | |
1400 kFill_RRectType, | |
1401 kStroke_RRectType, | |
1402 kOverstroke_RRectType | |
1403 }; | |
1404 | |
1361 GR_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); | 1405 GR_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); |
1362 GR_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); | 1406 GR_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); |
1363 static const GrBuffer* ref_rrect_index_buffer(bool strokeOnly, | 1407 GR_DECLARE_STATIC_UNIQUE_KEY(gOverstrokeRRectOnlyIndexBufferKey); |
1408 static const GrBuffer* ref_rrect_index_buffer(RRectType type, | |
1364 GrResourceProvider* resourceProvid er) { | 1409 GrResourceProvider* resourceProvid er) { |
1365 GR_DEFINE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); | 1410 GR_DEFINE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); |
1366 GR_DEFINE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); | 1411 GR_DEFINE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); |
1367 if (strokeOnly) { | 1412 GR_DEFINE_STATIC_UNIQUE_KEY(gOverstrokeRRectOnlyIndexBufferKey); |
1368 return resourceProvider->findOrCreateInstancedIndexBuffer( | 1413 switch (type) { |
1369 gRRectIndices, kIndicesPerStrokeRRect, kNumRRectsInIndexBuffer, kVer tsPerRRect, | 1414 case kFill_RRectType: |
1370 gStrokeRRectOnlyIndexBufferKey); | 1415 default: |
1371 } else { | 1416 return resourceProvider->findOrCreateInstancedIndexBuffer( |
1372 return resourceProvider->findOrCreateInstancedIndexBuffer( | 1417 gRRectIndices, kIndicesPerFillRRect, kNumRRectsInIndexBuffer, |
1373 gRRectIndices, kIndicesPerRRect, kNumRRectsInIndexBuffer, kVertsPerR Rect, | 1418 kVertsPerStandardRRect, gRRectOnlyIndexBufferKey); |
1374 gRRectOnlyIndexBufferKey); | 1419 case kStroke_RRectType: |
1375 | 1420 return resourceProvider->findOrCreateInstancedIndexBuffer( |
1376 } | 1421 gRRectIndices, kIndicesPerStrokeRRect, kNumRRectsInIndexBuffer, |
1422 kVertsPerStandardRRect, gStrokeRRectOnlyIndexBufferKey); | |
1423 case kOverstroke_RRectType: | |
1424 return resourceProvider->findOrCreateInstancedIndexBuffer( | |
1425 gRRectOverstrokeIndices, kIndicesPerOverstrokeRRect, kNumRRectsI nIndexBuffer, | |
1426 kVertsPerOverstrokeRRect, gOverstrokeRRectOnlyIndexBufferKey); | |
1427 }; | |
1377 } | 1428 } |
1378 | 1429 |
1379 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 1430 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
1380 | 1431 |
1381 class RRectCircleRendererBatch : public GrVertexBatch { | 1432 class RRectCircleRendererBatch : public GrVertexBatch { |
1382 public: | 1433 public: |
1383 DEFINE_BATCH_CLASS_ID | 1434 DEFINE_BATCH_CLASS_ID |
1384 | 1435 |
1385 // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then s trokeOnly indicates | 1436 // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then s trokeOnly indicates |
1386 // whether the rrect is only stroked or stroked and filled. | 1437 // whether the rrect is only stroked or stroked and filled. |
1387 RRectCircleRendererBatch(GrColor color, const SkMatrix& viewMatrix, const Sk Rect& devRect, | 1438 RRectCircleRendererBatch(GrColor color, const SkMatrix& viewMatrix, const Sk Rect& devRect, |
1388 float devRadius, float devStrokeWidth, bool strokeO nly) | 1439 float devRadius, float devStrokeWidth, bool strokeO nly) |
1389 : INHERITED(ClassID()) | 1440 : INHERITED(ClassID()) |
1390 , fViewMatrixIfUsingLocalCoords(viewMatrix) { | 1441 , fViewMatrixIfUsingLocalCoords(viewMatrix) { |
1391 SkRect bounds = devRect; | 1442 SkRect bounds = devRect; |
1392 SkASSERT(!(devStrokeWidth <= 0 && strokeOnly)); | 1443 SkASSERT(!(devStrokeWidth <= 0 && strokeOnly)); |
1393 SkScalar innerRadius = 0.0f; | 1444 SkScalar innerRadius = 0.0f; |
1394 SkScalar outerRadius = devRadius; | 1445 SkScalar outerRadius = devRadius; |
1395 SkScalar halfWidth = 0; | 1446 SkScalar halfWidth = 0; |
1396 fStroked = false; | 1447 fType = kFill_RRectType; |
1397 if (devStrokeWidth > 0) { | 1448 if (devStrokeWidth > 0) { |
1398 if (SkScalarNearlyZero(devStrokeWidth)) { | 1449 if (SkScalarNearlyZero(devStrokeWidth)) { |
1399 halfWidth = SK_ScalarHalf; | 1450 halfWidth = SK_ScalarHalf; |
1400 } else { | 1451 } else { |
1401 halfWidth = SkScalarHalf(devStrokeWidth); | 1452 halfWidth = SkScalarHalf(devStrokeWidth); |
1402 } | 1453 } |
1403 | 1454 |
1404 if (strokeOnly) { | 1455 if (strokeOnly) { |
1405 innerRadius = devRadius - halfWidth; | 1456 innerRadius = devRadius - halfWidth; |
1406 fStroked = innerRadius >= 0; | 1457 // TODO: if radius is really large this might just be a fill |
robertphillips
2016/08/25 12:55:42
I think, once GrShape is complete, the stroke->fil
jvanverth1
2016/08/25 14:02:52
Fixed until then.
| |
1458 fType = (innerRadius >= 0) ? kStroke_RRectType : kOverstroke_RRe ctType; | |
1407 } | 1459 } |
1408 outerRadius += halfWidth; | 1460 outerRadius += halfWidth; |
1409 bounds.outset(halfWidth, halfWidth); | 1461 bounds.outset(halfWidth, halfWidth); |
1410 } | 1462 } |
1411 | 1463 |
1412 // The radii are outset for two reasons. First, it allows the shader to simply perform | 1464 // The radii are outset for two reasons. First, it allows the shader to simply perform |
1413 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius. | 1465 // simpler computation because the computed alpha is zero, rather than 5 0%, at the radius. |
1414 // Second, the outer radius is used to compute the verts of the bounding box that is | 1466 // Second, the outer radius is used to compute the verts of the bounding box that is |
1415 // rendered and the outset ensures the box will cover all partially cove red by the rrect | 1467 // rendered and the outset ensures the box will cover all partially cove red by the rrect |
1416 // corners. | 1468 // corners. |
1417 outerRadius += SK_ScalarHalf; | 1469 outerRadius += SK_ScalarHalf; |
1418 innerRadius -= SK_ScalarHalf; | 1470 innerRadius -= SK_ScalarHalf; |
1419 | 1471 |
1420 this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo); | 1472 this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo); |
1421 | 1473 |
1422 // Expand the rect for aa to generate correct vertices. | 1474 // Expand the rect for aa to generate correct vertices. |
1423 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1475 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
1424 | 1476 |
1425 fGeoData.emplace_back(Geometry { color, innerRadius, outerRadius, bounds }); | 1477 fGeoData.emplace_back(Geometry { color, innerRadius, outerRadius, bounds }); |
1426 } | 1478 } |
1427 | 1479 |
1428 const char* name() const override { return "RRectCircleBatch"; } | 1480 const char* name() const override { return "RRectCircleBatch"; } |
1429 | 1481 |
1482 SkString dumpInfo() const override { | |
1483 SkString string; | |
1484 for (int i = 0; i < fGeoData.count(); ++i) { | |
1485 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %. 2f]," | |
1486 "InnerRad: %.2f, OuterRad: %.2f\n", | |
1487 fGeoData[i].fColor, | |
1488 fGeoData[i].fDevBounds.fLeft, fGeoData[i].fDevBounds. fTop, | |
1489 fGeoData[i].fDevBounds.fRight, fGeoData[i].fDevBounds .fBottom, | |
1490 fGeoData[i].fInnerRadius, | |
1491 fGeoData[i].fOuterRadius); | |
1492 } | |
1493 string.append(INHERITED::dumpInfo()); | |
1494 return string; | |
1495 } | |
1496 | |
1430 void computePipelineOptimizations(GrInitInvariantOutput* color, | 1497 void computePipelineOptimizations(GrInitInvariantOutput* color, |
1431 GrInitInvariantOutput* coverage, | 1498 GrInitInvariantOutput* coverage, |
1432 GrBatchToXPOverrides* overrides) const ove rride { | 1499 GrBatchToXPOverrides* overrides) const ove rride { |
1433 // When this is called on a batch, there is only one geometry bundle | 1500 // When this is called on a batch, there is only one geometry bundle |
1434 color->setKnownFourComponents(fGeoData[0].fColor); | 1501 color->setKnownFourComponents(fGeoData[0].fColor); |
1435 coverage->setUnknownSingleComponent(); | 1502 coverage->setUnknownSingleComponent(); |
1436 } | 1503 } |
1437 | 1504 |
1438 private: | 1505 private: |
1439 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { | 1506 void initBatchTracker(const GrXPOverridesForBatch& overrides) override { |
1440 // Handle any overrides that affect our GP. | 1507 // Handle any overrides that affect our GP. |
1441 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | 1508 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
1442 if (!overrides.readsLocalCoords()) { | 1509 if (!overrides.readsLocalCoords()) { |
1443 fViewMatrixIfUsingLocalCoords.reset(); | 1510 fViewMatrixIfUsingLocalCoords.reset(); |
1444 } | 1511 } |
1445 } | 1512 } |
1446 | 1513 |
1447 void onPrepareDraws(Target* target) const override { | 1514 void onPrepareDraws(Target* target) const override { |
1448 // Invert the view matrix as a local matrix (if any other processors req uire coords). | 1515 // Invert the view matrix as a local matrix (if any other processors req uire coords). |
1449 SkMatrix localMatrix; | 1516 SkMatrix localMatrix; |
1450 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { | 1517 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { |
1451 return; | 1518 return; |
1452 } | 1519 } |
1453 | 1520 |
1454 // Setup geometry processor | 1521 // Setup geometry processor |
1455 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fStroke d, false, false, | 1522 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(kStroke _RRectType == fType, |
1523 false, false, | |
1456 false, localMatrix)); | 1524 false, localMatrix)); |
1457 | 1525 |
1458 struct CircleVertex { | 1526 struct CircleVertex { |
1459 SkPoint fPos; | 1527 SkPoint fPos; |
1460 GrColor fColor; | 1528 GrColor fColor; |
1461 SkPoint fOffset; | 1529 SkPoint fOffset; |
1462 SkScalar fOuterRadius; | 1530 SkScalar fOuterRadius; |
1463 SkScalar fInnerRadius; | 1531 SkScalar fInnerRadius; |
1464 // No half plane, we don't use it here. | 1532 // No half plane, we don't use it here. |
1465 }; | 1533 }; |
1466 | 1534 |
1467 int instanceCount = fGeoData.count(); | 1535 int instanceCount = fGeoData.count(); |
1468 size_t vertexStride = gp->getVertexStride(); | 1536 size_t vertexStride = gp->getVertexStride(); |
1469 SkASSERT(vertexStride == sizeof(CircleVertex)); | 1537 SkASSERT(vertexStride == sizeof(CircleVertex)); |
1470 | 1538 |
1471 // drop out the middle quad if we're stroked | 1539 // drop out the middle quad if we're stroked |
1472 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer RRect; | 1540 int indicesPerInstance = kIndicesPerFillRRect; |
1541 if (kStroke_RRectType == fType) { | |
1542 indicesPerInstance = kIndicesPerStrokeRRect; | |
1543 } else if (kOverstroke_RRectType == fType) { | |
1544 indicesPerInstance = kIndicesPerOverstrokeRRect; | |
1545 } | |
1473 SkAutoTUnref<const GrBuffer> indexBuffer( | 1546 SkAutoTUnref<const GrBuffer> indexBuffer( |
1474 ref_rrect_index_buffer(fStroked, target->resourceProvider())); | 1547 ref_rrect_index_buffer(fType, target->resourceProvider())); |
1475 | 1548 |
1476 InstancedHelper helper; | 1549 InstancedHelper helper; |
1550 int vertexCount = (kOverstroke_RRectType == fType) ? kVertsPerOverstroke RRect | |
1551 : kVertsPerStandardRR ect; | |
1477 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target , | 1552 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target , |
1478 kTriangles_GrPrimitiveType, vertexStride, indexBuffer, kVertsPerRRec t, | 1553 kTriangles_GrPrimitiveType, vertexStride, indexBuffer, vertexCount, |
1479 indicesPerInstance, instanceCount)); | 1554 indicesPerInstance, instanceCount)); |
1480 if (!verts || !indexBuffer) { | 1555 if (!verts || !indexBuffer) { |
1481 SkDebugf("Could not allocate vertices\n"); | 1556 SkDebugf("Could not allocate vertices\n"); |
1482 return; | 1557 return; |
1483 } | 1558 } |
1484 | 1559 |
1485 for (int i = 0; i < instanceCount; i++) { | 1560 for (int i = 0; i < instanceCount; i++) { |
1486 const Geometry& args = fGeoData[i]; | 1561 const Geometry& args = fGeoData[i]; |
1487 | 1562 |
1488 GrColor color = args.fColor; | 1563 GrColor color = args.fColor; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1522 verts->fInnerRadius = innerRadius; | 1597 verts->fInnerRadius = innerRadius; |
1523 verts++; | 1598 verts++; |
1524 | 1599 |
1525 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); | 1600 verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); |
1526 verts->fColor = color; | 1601 verts->fColor = color; |
1527 verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); | 1602 verts->fOffset = SkPoint::Make(1, yOuterRadii[i]); |
1528 verts->fOuterRadius = outerRadius; | 1603 verts->fOuterRadius = outerRadius; |
1529 verts->fInnerRadius = innerRadius; | 1604 verts->fInnerRadius = innerRadius; |
1530 verts++; | 1605 verts++; |
1531 } | 1606 } |
1607 // Add the additional vertices for overstroked rrects. | |
1608 // | |
1609 // Note that args.fInnerRadius is negative in this case. | |
1610 // Also, the offset is a constant vector pointing to the right, whic h guarantees | |
1611 // that the distance value along the inner rectangle is constant, wh ich | |
1612 // is what we want to get nice anti-aliasing. | |
1613 if (kOverstroke_RRectType == fType) { | |
1614 // outerRadius = originalOuter + 0.5, and innerRadius = original Inner - 0.5. | |
1615 // What we want is originalOuter - originalInner + 0.5, so we su btract 0.5. | |
1616 SkScalar inset = outerRadius - args.fInnerRadius - SK_ScalarHalf ; | |
1617 verts->fPos = SkPoint::Make(bounds.fLeft + inset, | |
1618 bounds.fTop + inset); | |
1619 verts->fColor = color; | |
1620 verts->fOffset = SkPoint::Make(1, 0); | |
1621 verts->fOuterRadius = outerRadius; | |
1622 verts->fInnerRadius = innerRadius; | |
1623 verts++; | |
1624 | |
1625 verts->fPos = SkPoint::Make(bounds.fRight - inset, | |
1626 bounds.fTop + inset); | |
1627 verts->fColor = color; | |
1628 verts->fOffset = SkPoint::Make(1, 0); | |
1629 verts->fOuterRadius = outerRadius; | |
1630 verts->fInnerRadius = innerRadius; | |
1631 verts++; | |
1632 | |
1633 verts->fPos = SkPoint::Make(bounds.fLeft + inset, | |
1634 bounds.fBottom - inset); | |
1635 verts->fColor = color; | |
1636 verts->fOffset = SkPoint::Make(1, 0); | |
1637 verts->fOuterRadius = outerRadius; | |
1638 verts->fInnerRadius = innerRadius; | |
1639 verts++; | |
1640 | |
1641 verts->fPos = SkPoint::Make(bounds.fRight - inset, | |
1642 bounds.fBottom - inset); | |
1643 verts->fColor = color; | |
1644 verts->fOffset = SkPoint::Make(1, 0); | |
1645 verts->fOuterRadius = outerRadius; | |
1646 verts->fInnerRadius = innerRadius; | |
1647 verts++; | |
1648 } | |
1532 } | 1649 } |
1533 | 1650 |
1534 helper.recordDraw(target, gp); | 1651 helper.recordDraw(target, gp); |
1535 } | 1652 } |
1536 | 1653 |
1537 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 1654 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
1538 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>(); | 1655 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>(); |
1539 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), | 1656 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(), |
1540 that->bounds(), caps)) { | 1657 that->bounds(), caps)) { |
1541 return false; | 1658 return false; |
1542 } | 1659 } |
1543 | 1660 |
1544 if (fStroked != that->fStroked) { | 1661 if (fType != that->fType) { |
1545 return false; | 1662 return false; |
1546 } | 1663 } |
1547 | 1664 |
1548 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) { | 1665 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing LocalCoords)) { |
1549 return false; | 1666 return false; |
1550 } | 1667 } |
1551 | 1668 |
1552 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); | 1669 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
1553 this->joinBounds(*that); | 1670 this->joinBounds(*that); |
1554 return true; | 1671 return true; |
1555 } | 1672 } |
1556 | 1673 |
1557 struct Geometry { | 1674 struct Geometry { |
1558 GrColor fColor; | 1675 GrColor fColor; |
1559 SkScalar fInnerRadius; | 1676 SkScalar fInnerRadius; |
1560 SkScalar fOuterRadius; | 1677 SkScalar fOuterRadius; |
1561 SkRect fDevBounds; | 1678 SkRect fDevBounds; |
1562 }; | 1679 }; |
1563 | 1680 |
1564 bool fStroked; | 1681 RRectType fType; |
1565 SkMatrix fViewMatrixIfUsingLocalCoords; | 1682 SkMatrix fViewMatrixIfUsingLocalCoords; |
1566 SkSTArray<1, Geometry, true> fGeoData; | 1683 SkSTArray<1, Geometry, true> fGeoData; |
1567 | 1684 |
1568 typedef GrVertexBatch INHERITED; | 1685 typedef GrVertexBatch INHERITED; |
1569 }; | 1686 }; |
1570 | 1687 |
1571 class RRectEllipseRendererBatch : public GrVertexBatch { | 1688 class RRectEllipseRendererBatch : public GrVertexBatch { |
1572 public: | 1689 public: |
1573 DEFINE_BATCH_CLASS_ID | 1690 DEFINE_BATCH_CLASS_ID |
1574 | 1691 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1659 } | 1776 } |
1660 | 1777 |
1661 // Setup geometry processor | 1778 // Setup geometry processor |
1662 SkAutoTUnref<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStrok ed, localMatrix)); | 1779 SkAutoTUnref<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStrok ed, localMatrix)); |
1663 | 1780 |
1664 int instanceCount = fGeoData.count(); | 1781 int instanceCount = fGeoData.count(); |
1665 size_t vertexStride = gp->getVertexStride(); | 1782 size_t vertexStride = gp->getVertexStride(); |
1666 SkASSERT(vertexStride == sizeof(EllipseVertex)); | 1783 SkASSERT(vertexStride == sizeof(EllipseVertex)); |
1667 | 1784 |
1668 // drop out the middle quad if we're stroked | 1785 // drop out the middle quad if we're stroked |
1669 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer RRect; | 1786 int indicesPerInstance = fStroked ? kIndicesPerStrokeRRect : kIndicesPer FillRRect; |
1670 SkAutoTUnref<const GrBuffer> indexBuffer( | 1787 SkAutoTUnref<const GrBuffer> indexBuffer( |
1671 ref_rrect_index_buffer(fStroked, target->resourceProvider())); | 1788 ref_rrect_index_buffer(fStroked ? kStroke_RRectType : kFill_RRectTyp e, |
1789 target->resourceProvider())); | |
1672 | 1790 |
1673 InstancedHelper helper; | 1791 InstancedHelper helper; |
1674 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( | 1792 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>( |
1675 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexB uffer, | 1793 helper.init(target, kTriangles_GrPrimitiveType, vertexStride, indexB uffer, |
1676 kVertsPerRRect, indicesPerInstance, instanceCount)); | 1794 kVertsPerStandardRRect, indicesPerInstance, instanceCoun t)); |
1677 if (!verts || !indexBuffer) { | 1795 if (!verts || !indexBuffer) { |
1678 SkDebugf("Could not allocate vertices\n"); | 1796 SkDebugf("Could not allocate vertices\n"); |
1679 return; | 1797 return; |
1680 } | 1798 } |
1681 | 1799 |
1682 for (int i = 0; i < instanceCount; i++) { | 1800 for (int i = 0; i < instanceCount; i++) { |
1683 const Geometry& args = fGeoData[i]; | 1801 const Geometry& args = fGeoData[i]; |
1684 | 1802 |
1685 GrColor color = args.fColor; | 1803 GrColor color = args.fColor; |
1686 | 1804 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1802 SkStrokeRec::Style style = stroke.getStyle(); | 1920 SkStrokeRec::Style style = stroke.getStyle(); |
1803 | 1921 |
1804 // Do (potentially) anisotropic mapping of stroke. Use -1s to indicate fill- only draws. | 1922 // Do (potentially) anisotropic mapping of stroke. Use -1s to indicate fill- only draws. |
1805 SkVector scaledStroke = {-1, -1}; | 1923 SkVector scaledStroke = {-1, -1}; |
1806 SkScalar strokeWidth = stroke.getWidth(); | 1924 SkScalar strokeWidth = stroke.getWidth(); |
1807 | 1925 |
1808 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 1926 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
1809 SkStrokeRec::kHairline_Style == style; | 1927 SkStrokeRec::kHairline_Style == style; |
1810 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 1928 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
1811 | 1929 |
1930 bool isCircular = (xRadius == yRadius); | |
1812 if (hasStroke) { | 1931 if (hasStroke) { |
1813 if (SkStrokeRec::kHairline_Style == style) { | 1932 if (SkStrokeRec::kHairline_Style == style) { |
1814 scaledStroke.set(1, 1); | 1933 scaledStroke.set(1, 1); |
1815 } else { | 1934 } else { |
1816 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc aleX] + | 1935 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc aleX] + |
1817 viewMatrix[SkMatrix::kMSk ewY])); | 1936 viewMatrix[SkMatrix::kMSk ewY])); |
1818 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk ewX] + | 1937 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk ewX] + |
1819 viewMatrix[SkMatrix::kMSc aleY])); | 1938 viewMatrix[SkMatrix::kMSc aleY])); |
1820 } | 1939 } |
1821 | 1940 |
1822 // if half of strokewidth is greater than radius, we don't handle that r ight now | 1941 isCircular = isCircular && scaledStroke.fX == scaledStroke.fY; |
1823 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok e.fY > yRadius) { | 1942 // for non-circular rrects, if half of strokewidth is greater than radiu s, |
1943 // we don't handle that right now | |
1944 if (!isCircular && | |
1945 (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStro ke.fY > yRadius)) { | |
1824 return nullptr; | 1946 return nullptr; |
1825 } | 1947 } |
1826 } | 1948 } |
1827 | 1949 |
1828 // The way the effect interpolates the offset-to-ellipse/circle-center attri bute only works on | 1950 // The way the effect interpolates the offset-to-ellipse/circle-center attri bute only works on |
1829 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r ect of the nine- | 1951 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r ect of the nine- |
1830 // patch will have fractional coverage. This only matters when the interior is actually filled. | 1952 // patch will have fractional coverage. This only matters when the interior is actually filled. |
1831 // We could consider falling back to rect rendering here, since a tiny radiu s is | 1953 // We could consider falling back to rect rendering here, since a tiny radiu s is |
1832 // indistinguishable from a square corner. | 1954 // indistinguishable from a square corner. |
1833 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { | 1955 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { |
1834 return nullptr; | 1956 return nullptr; |
1835 } | 1957 } |
1836 | 1958 |
1837 // if the corners are circles, use the circle renderer | 1959 // if the corners are circles, use the circle renderer |
1838 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius ) { | 1960 if (isCircular) { |
1839 return new RRectCircleRendererBatch(color, viewMatrix, bounds, xRadius, scaledStroke.fX, | 1961 return new RRectCircleRendererBatch(color, viewMatrix, bounds, xRadius, scaledStroke.fX, |
1840 isStrokeOnly); | 1962 isStrokeOnly); |
1841 // otherwise we use the ellipse renderer | 1963 // otherwise we use the ellipse renderer |
1842 } else { | 1964 } else { |
1843 return RRectEllipseRendererBatch::Create(color, viewMatrix, bounds, xRad ius, yRadius, | 1965 return RRectEllipseRendererBatch::Create(color, viewMatrix, bounds, xRad ius, yRadius, |
1844 scaledStroke, isStrokeOnly); | 1966 scaledStroke, isStrokeOnly); |
1845 | 1967 |
1846 } | 1968 } |
1847 } | 1969 } |
1848 | 1970 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1962 } | 2084 } |
1963 | 2085 |
1964 DRAW_BATCH_TEST_DEFINE(RRectBatch) { | 2086 DRAW_BATCH_TEST_DEFINE(RRectBatch) { |
1965 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); | 2087 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); |
1966 GrColor color = GrRandomColor(random); | 2088 GrColor color = GrRandomColor(random); |
1967 const SkRRect& rrect = GrTest::TestRRectSimple(random); | 2089 const SkRRect& rrect = GrTest::TestRRectSimple(random); |
1968 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom)); | 2090 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra ndom)); |
1969 } | 2091 } |
1970 | 2092 |
1971 #endif | 2093 #endif |
OLD | NEW |