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 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 // ____________ | 1355 // ____________ |
1356 // |_|________|_| | 1356 // |_|________|_| |
1357 // | |\ ____ /| | | 1357 // | |\ ____ /| | |
1358 // | | | | | | | 1358 // | | | | | | |
1359 // | | |____| | | | 1359 // | | |____| | | |
1360 // |_|/______\|_| | 1360 // |_|/______\|_| |
1361 // |_|________|_| | 1361 // |_|________|_| |
1362 // | 1362 // |
1363 // We don't draw the center quad from the fill rect in this case. | 1363 // We don't draw the center quad from the fill rect in this case. |
1364 | 1364 |
1365 static const uint16_t gRRectOverstrokeIndices[] = { | 1365 static const uint16_t gOverstrokeRRectIndices[] = { |
1366 // overstroke quads | 1366 // overstroke quads |
1367 // we place this at the beginning so that we can skip these indices when ren
dering normally | 1367 // we place this at the beginning so that we can skip these indices when ren
dering normally |
1368 16, 17, 19, 16, 19, 18, | 1368 16, 17, 19, 16, 19, 18, |
1369 19, 17, 23, 19, 23, 21, | 1369 19, 17, 23, 19, 23, 21, |
1370 21, 23, 22, 21, 22, 20, | 1370 21, 23, 22, 21, 22, 20, |
1371 22, 16, 18, 22, 18, 20, | 1371 22, 16, 18, 22, 18, 20, |
1372 | 1372 |
1373 // corners | 1373 // corners |
1374 0, 1, 5, 0, 5, 4, | 1374 0, 1, 5, 0, 5, 4, |
1375 2, 3, 7, 2, 7, 6, | 1375 2, 3, 7, 2, 7, 6, |
1376 8, 9, 13, 8, 13, 12, | 1376 8, 9, 13, 8, 13, 12, |
1377 10, 11, 15, 10, 15, 14, | 1377 10, 11, 15, 10, 15, 14, |
1378 | 1378 |
1379 // edges | 1379 // edges |
1380 1, 2, 6, 1, 6, 5, | 1380 1, 2, 6, 1, 6, 5, |
1381 4, 5, 9, 4, 9, 8, | 1381 4, 5, 9, 4, 9, 8, |
1382 6, 7, 11, 6, 11, 10, | 1382 6, 7, 11, 6, 11, 10, |
1383 9, 10, 14, 9, 14, 13, | 1383 9, 10, 14, 9, 14, 13, |
1384 | 1384 |
1385 // center | 1385 // center |
1386 // we place this at the end so that we can ignore these indices when not ren
dering as filled | 1386 // we place this at the end so that we can ignore these indices when not ren
dering as filled |
1387 5, 6, 10, 5, 10, 9, | 1387 5, 6, 10, 5, 10, 9, |
1388 }; | 1388 }; |
| 1389 // fill and standard stroke indices skip the overstroke "ring" |
| 1390 static const uint16_t* gStandardRRectIndices = gOverstrokeRRectIndices + 6*4; |
1389 | 1391 |
1390 static const uint16_t* gRRectIndices = gRRectOverstrokeIndices + 6*4; | 1392 // overstroke count is arraysize minus the center indices |
1391 | 1393 static const int kIndicesPerOverstrokeRRect = SK_ARRAY_COUNT(gOverstrokeRRectInd
ices) - 6; |
1392 // overstroke count is arraysize | 1394 // fill count skips overstroke indices and includes center |
1393 static const int kIndicesPerOverstrokeRRect = SK_ARRAY_COUNT(gRRectOverstrokeInd
ices) - 6; | |
1394 static const int kIndicesPerFillRRect = kIndicesPerOverstrokeRRect - 6*4 + 6; | 1395 static const int kIndicesPerFillRRect = kIndicesPerOverstrokeRRect - 6*4 + 6; |
| 1396 // stroke count is fill count minus center indices |
1395 static const int kIndicesPerStrokeRRect = kIndicesPerFillRRect - 6; | 1397 static const int kIndicesPerStrokeRRect = kIndicesPerFillRRect - 6; |
1396 static const int kVertsPerStandardRRect = 16; | 1398 static const int kVertsPerStandardRRect = 16; |
1397 static const int kVertsPerOverstrokeRRect = 24; | 1399 static const int kVertsPerOverstrokeRRect = 24; |
1398 static const int kNumRRectsInIndexBuffer = 256; | |
1399 | 1400 |
1400 enum RRectType { | 1401 enum RRectType { |
1401 kFill_RRectType, | 1402 kFill_RRectType, |
1402 kStroke_RRectType, | 1403 kStroke_RRectType, |
1403 kOverstroke_RRectType | 1404 kOverstroke_RRectType, |
1404 }; | 1405 }; |
1405 | 1406 |
1406 GR_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); | 1407 static int rrect_type_to_vert_count(RRectType type) { |
1407 GR_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); | 1408 static const int kTypeToVertCount[] = { |
1408 GR_DECLARE_STATIC_UNIQUE_KEY(gOverstrokeRRectOnlyIndexBufferKey); | 1409 kVertsPerStandardRRect, |
1409 static const GrBuffer* ref_rrect_index_buffer(RRectType type, | 1410 kVertsPerStandardRRect, |
1410 GrResourceProvider* resourceProvid
er) { | 1411 kVertsPerOverstrokeRRect, |
1411 GR_DEFINE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); | |
1412 GR_DEFINE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); | |
1413 GR_DEFINE_STATIC_UNIQUE_KEY(gOverstrokeRRectOnlyIndexBufferKey); | |
1414 switch (type) { | |
1415 case kFill_RRectType: | |
1416 default: | |
1417 return resourceProvider->findOrCreateInstancedIndexBuffer( | |
1418 gRRectIndices, kIndicesPerFillRRect, kNumRRectsInIndexBuffer, | |
1419 kVertsPerStandardRRect, gRRectOnlyIndexBufferKey); | |
1420 case kStroke_RRectType: | |
1421 return resourceProvider->findOrCreateInstancedIndexBuffer( | |
1422 gRRectIndices, kIndicesPerStrokeRRect, kNumRRectsInIndexBuffer, | |
1423 kVertsPerStandardRRect, gStrokeRRectOnlyIndexBufferKey); | |
1424 case kOverstroke_RRectType: | |
1425 return resourceProvider->findOrCreateInstancedIndexBuffer( | |
1426 gRRectOverstrokeIndices, kIndicesPerOverstrokeRRect, kNumRRectsI
nIndexBuffer, | |
1427 kVertsPerOverstrokeRRect, gOverstrokeRRectOnlyIndexBufferKey); | |
1428 }; | 1412 }; |
| 1413 |
| 1414 return kTypeToVertCount[type]; |
| 1415 } |
| 1416 |
| 1417 static int rrect_type_to_index_count(RRectType type) { |
| 1418 static const int kTypeToIndexCount[] = { |
| 1419 kIndicesPerFillRRect, |
| 1420 kIndicesPerStrokeRRect, |
| 1421 kIndicesPerOverstrokeRRect, |
| 1422 }; |
| 1423 |
| 1424 return kTypeToIndexCount[type]; |
| 1425 } |
| 1426 |
| 1427 static const uint16_t* rrect_type_to_indices(RRectType type) { |
| 1428 static const uint16_t* kTypeToIndices[] = { |
| 1429 gStandardRRectIndices, |
| 1430 gStandardRRectIndices, |
| 1431 gOverstrokeRRectIndices, |
| 1432 }; |
| 1433 |
| 1434 return kTypeToIndices[type]; |
1429 } | 1435 } |
1430 | 1436 |
1431 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 1437 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
1432 | 1438 |
1433 class RRectCircleRendererBatch : public GrVertexBatch { | 1439 class RRectCircleRendererBatch : public GrVertexBatch { |
1434 public: | 1440 public: |
1435 DEFINE_BATCH_CLASS_ID | 1441 DEFINE_BATCH_CLASS_ID |
1436 | 1442 |
1437 // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then s
trokeOnly indicates | 1443 // A devStrokeWidth <= 0 indicates a fill only. If devStrokeWidth > 0 then s
trokeOnly indicates |
1438 // whether the rrect is only stroked or stroked and filled. | 1444 // whether the rrect is only stroked or stroked and filled. |
1439 RRectCircleRendererBatch(GrColor color, const SkMatrix& viewMatrix, const Sk
Rect& devRect, | 1445 RRectCircleRendererBatch(GrColor color, const SkMatrix& viewMatrix, const Sk
Rect& devRect, |
1440 float devRadius, float devStrokeWidth, bool strokeO
nly) | 1446 float devRadius, float devStrokeWidth, bool strokeO
nly) |
1441 : INHERITED(ClassID()) | 1447 : INHERITED(ClassID()) |
1442 , fViewMatrixIfUsingLocalCoords(viewMatrix) { | 1448 , fViewMatrixIfUsingLocalCoords(viewMatrix) { |
1443 SkRect bounds = devRect; | 1449 SkRect bounds = devRect; |
1444 SkASSERT(!(devStrokeWidth <= 0 && strokeOnly)); | 1450 SkASSERT(!(devStrokeWidth <= 0 && strokeOnly)); |
1445 SkScalar innerRadius = 0.0f; | 1451 SkScalar innerRadius = 0.0f; |
1446 SkScalar outerRadius = devRadius; | 1452 SkScalar outerRadius = devRadius; |
1447 SkScalar halfWidth = 0; | 1453 SkScalar halfWidth = 0; |
1448 fType = kFill_RRectType; | 1454 RRectType type = kFill_RRectType; |
1449 if (devStrokeWidth > 0) { | 1455 if (devStrokeWidth > 0) { |
1450 if (SkScalarNearlyZero(devStrokeWidth)) { | 1456 if (SkScalarNearlyZero(devStrokeWidth)) { |
1451 halfWidth = SK_ScalarHalf; | 1457 halfWidth = SK_ScalarHalf; |
1452 } else { | 1458 } else { |
1453 halfWidth = SkScalarHalf(devStrokeWidth); | 1459 halfWidth = SkScalarHalf(devStrokeWidth); |
1454 } | 1460 } |
1455 | 1461 |
1456 if (strokeOnly) { | 1462 if (strokeOnly) { |
1457 // Outset stroke by 1/4 pixel | 1463 // Outset stroke by 1/4 pixel |
1458 devStrokeWidth += 0.25f; | 1464 devStrokeWidth += 0.25f; |
1459 // If stroke is greater than width or height, this is still a fi
ll | 1465 // If stroke is greater than width or height, this is still a fi
ll |
1460 // Otherwise we compute stroke params | 1466 // Otherwise we compute stroke params |
1461 if (devStrokeWidth <= devRect.width() && | 1467 if (devStrokeWidth <= devRect.width() && |
1462 devStrokeWidth <= devRect.height()) { | 1468 devStrokeWidth <= devRect.height()) { |
1463 innerRadius = devRadius - halfWidth; | 1469 innerRadius = devRadius - halfWidth; |
1464 fType = (innerRadius >= 0) ? kStroke_RRectType : kOverstroke
_RRectType; | 1470 type = (innerRadius >= 0) ? kStroke_RRectType : kOverstroke_
RRectType; |
1465 } | 1471 } |
1466 } | 1472 } |
1467 outerRadius += halfWidth; | 1473 outerRadius += halfWidth; |
1468 bounds.outset(halfWidth, halfWidth); | 1474 bounds.outset(halfWidth, halfWidth); |
1469 } | 1475 } |
1470 | 1476 |
1471 // The radii are outset for two reasons. First, it allows the shader to
simply perform | 1477 // The radii are outset for two reasons. First, it allows the shader to
simply perform |
1472 // simpler computation because the computed alpha is zero, rather than 5
0%, at the radius. | 1478 // simpler computation because the computed alpha is zero, rather than 5
0%, at the radius. |
1473 // Second, the outer radius is used to compute the verts of the bounding
box that is | 1479 // Second, the outer radius is used to compute the verts of the bounding
box that is |
1474 // rendered and the outset ensures the box will cover all partially cove
red by the rrect | 1480 // rendered and the outset ensures the box will cover all partially cove
red by the rrect |
1475 // corners. | 1481 // corners. |
1476 outerRadius += SK_ScalarHalf; | 1482 outerRadius += SK_ScalarHalf; |
1477 innerRadius -= SK_ScalarHalf; | 1483 innerRadius -= SK_ScalarHalf; |
1478 | 1484 |
1479 this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo); | 1485 this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo); |
1480 | 1486 |
1481 // Expand the rect for aa to generate correct vertices. | 1487 // Expand the rect for aa to generate correct vertices. |
1482 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1488 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
1483 | 1489 |
1484 fGeoData.emplace_back(Geometry { color, innerRadius, outerRadius, bounds
}); | 1490 fGeoData.emplace_back(Geometry{ color, innerRadius, outerRadius, bounds,
type }); |
| 1491 fVertCount = rrect_type_to_vert_count(type); |
| 1492 fIndexCount = rrect_type_to_index_count(type); |
| 1493 fAllFill = (kFill_RRectType == type); |
1485 } | 1494 } |
1486 | 1495 |
1487 const char* name() const override { return "RRectCircleBatch"; } | 1496 const char* name() const override { return "RRectCircleBatch"; } |
1488 | 1497 |
1489 SkString dumpInfo() const override { | 1498 SkString dumpInfo() const override { |
1490 SkString string; | 1499 SkString string; |
1491 for (int i = 0; i < fGeoData.count(); ++i) { | 1500 for (int i = 0; i < fGeoData.count(); ++i) { |
1492 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.
2f]," | 1501 string.appendf("Color: 0x%08x Rect [L: %.2f, T: %.2f, R: %.2f, B: %.
2f]," |
1493 "InnerRad: %.2f, OuterRad: %.2f\n", | 1502 "InnerRad: %.2f, OuterRad: %.2f\n", |
1494 fGeoData[i].fColor, | 1503 fGeoData[i].fColor, |
(...skipping 24 matching lines...) Expand all Loading... |
1519 } | 1528 } |
1520 | 1529 |
1521 void onPrepareDraws(Target* target) const override { | 1530 void onPrepareDraws(Target* target) const override { |
1522 // Invert the view matrix as a local matrix (if any other processors req
uire coords). | 1531 // Invert the view matrix as a local matrix (if any other processors req
uire coords). |
1523 SkMatrix localMatrix; | 1532 SkMatrix localMatrix; |
1524 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { | 1533 if (!fViewMatrixIfUsingLocalCoords.invert(&localMatrix)) { |
1525 return; | 1534 return; |
1526 } | 1535 } |
1527 | 1536 |
1528 // Setup geometry processor | 1537 // Setup geometry processor |
1529 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(kFill_R
RectType != fType, | 1538 SkAutoTUnref<GrGeometryProcessor> gp(new CircleGeometryProcessor(fAllFil
l, |
1530 false,
false, | 1539 false,
false, |
1531 false,
localMatrix)); | 1540 false,
localMatrix)); |
1532 | |
1533 struct CircleVertex { | 1541 struct CircleVertex { |
1534 SkPoint fPos; | 1542 SkPoint fPos; |
1535 GrColor fColor; | 1543 GrColor fColor; |
1536 SkPoint fOffset; | 1544 SkPoint fOffset; |
1537 SkScalar fOuterRadius; | 1545 SkScalar fOuterRadius; |
1538 SkScalar fInnerRadius; | 1546 SkScalar fInnerRadius; |
1539 // No half plane, we don't use it here. | 1547 // No half plane, we don't use it here. |
1540 }; | 1548 }; |
1541 | 1549 |
1542 int instanceCount = fGeoData.count(); | 1550 int instanceCount = fGeoData.count(); |
1543 size_t vertexStride = gp->getVertexStride(); | 1551 size_t vertexStride = gp->getVertexStride(); |
1544 SkASSERT(vertexStride == sizeof(CircleVertex)); | 1552 SkASSERT(sizeof(CircleVertex) == vertexStride); |
1545 | 1553 |
1546 // drop out the middle quad if we're stroked | 1554 const GrBuffer* vertexBuffer; |
1547 int indicesPerInstance = kIndicesPerFillRRect; | 1555 int firstVertex; |
1548 if (kStroke_RRectType == fType) { | |
1549 indicesPerInstance = kIndicesPerStrokeRRect; | |
1550 } else if (kOverstroke_RRectType == fType) { | |
1551 indicesPerInstance = kIndicesPerOverstrokeRRect; | |
1552 } | |
1553 SkAutoTUnref<const GrBuffer> indexBuffer( | |
1554 ref_rrect_index_buffer(fType, target->resourceProvider())); | |
1555 | 1556 |
1556 InstancedHelper helper; | 1557 CircleVertex* verts = (CircleVertex*) target->makeVertexSpace(vertexStri
de, fVertCount, |
1557 int vertexCount = (kOverstroke_RRectType == fType) ? kVertsPerOverstroke
RRect | 1558 &vertexBuf
fer, &firstVertex); |
1558 : kVertsPerStandardRR
ect; | 1559 if (!verts) { |
1559 CircleVertex* verts = reinterpret_cast<CircleVertex*>(helper.init(target
, | |
1560 kTriangles_GrPrimitiveType, vertexStride, indexBuffer, vertexCount, | |
1561 indicesPerInstance, instanceCount)); | |
1562 if (!verts || !indexBuffer) { | |
1563 SkDebugf("Could not allocate vertices\n"); | 1560 SkDebugf("Could not allocate vertices\n"); |
1564 return; | 1561 return; |
1565 } | 1562 } |
1566 | 1563 |
| 1564 const GrBuffer* indexBuffer = nullptr; |
| 1565 int firstIndex = 0; |
| 1566 uint16_t* indices = target->makeIndexSpace(fIndexCount, &indexBuffer, &f
irstIndex); |
| 1567 if (!indices) { |
| 1568 SkDebugf("Could not allocate indices\n"); |
| 1569 return; |
| 1570 } |
| 1571 |
| 1572 int currStartVertex = 0; |
1567 for (int i = 0; i < instanceCount; i++) { | 1573 for (int i = 0; i < instanceCount; i++) { |
1568 const Geometry& args = fGeoData[i]; | 1574 const Geometry& args = fGeoData[i]; |
1569 | 1575 |
1570 GrColor color = args.fColor; | 1576 GrColor color = args.fColor; |
1571 SkScalar outerRadius = args.fOuterRadius; | 1577 SkScalar outerRadius = args.fOuterRadius; |
1572 | 1578 |
1573 const SkRect& bounds = args.fDevBounds; | 1579 const SkRect& bounds = args.fDevBounds; |
1574 | 1580 |
1575 SkScalar yCoords[4] = { | 1581 SkScalar yCoords[4] = { |
1576 bounds.fTop, | 1582 bounds.fTop, |
1577 bounds.fTop + outerRadius, | 1583 bounds.fTop + outerRadius, |
1578 bounds.fBottom - outerRadius, | 1584 bounds.fBottom - outerRadius, |
1579 bounds.fBottom | 1585 bounds.fBottom |
1580 }; | 1586 }; |
1581 | 1587 |
1582 SkScalar yOuterRadii[4] = {-1, 0, 0, 1 }; | 1588 SkScalar yOuterRadii[4] = {-1, 0, 0, 1 }; |
1583 // The inner radius in the vertex data must be specified in normaliz
ed space. | 1589 // The inner radius in the vertex data must be specified in normaliz
ed space. |
1584 SkScalar innerRadius = args.fInnerRadius / args.fOuterRadius; | 1590 // For fills, specifying -1/outerRadius guarantees an alpha of 1.0 a
t the inner radius. |
| 1591 SkScalar innerRadius = args.fType != kFill_RRectType |
| 1592 ? args.fInnerRadius / args.fOuterRadius |
| 1593 : -1.0f / args.fOuterRadius; |
1585 for (int i = 0; i < 4; ++i) { | 1594 for (int i = 0; i < 4; ++i) { |
1586 verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); | 1595 verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); |
1587 verts->fColor = color; | 1596 verts->fColor = color; |
1588 verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]); | 1597 verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]); |
1589 verts->fOuterRadius = outerRadius; | 1598 verts->fOuterRadius = outerRadius; |
1590 verts->fInnerRadius = innerRadius; | 1599 verts->fInnerRadius = innerRadius; |
1591 verts++; | 1600 verts++; |
1592 | 1601 |
1593 verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[
i]); | 1602 verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[
i]); |
1594 verts->fColor = color; | 1603 verts->fColor = color; |
(...skipping 17 matching lines...) Expand all Loading... |
1612 verts++; | 1621 verts++; |
1613 } | 1622 } |
1614 // Add the additional vertices for overstroked rrects. | 1623 // Add the additional vertices for overstroked rrects. |
1615 // Effectively this is an additional stroked rrect, with its | 1624 // Effectively this is an additional stroked rrect, with its |
1616 // outer radius = outerRadius - innerRadius, and inner radius = 0. | 1625 // outer radius = outerRadius - innerRadius, and inner radius = 0. |
1617 // This will give us correct AA in the center and the correct | 1626 // This will give us correct AA in the center and the correct |
1618 // distance to the outer edge. | 1627 // distance to the outer edge. |
1619 // | 1628 // |
1620 // Also, the outer offset is a constant vector pointing to the right
, which | 1629 // Also, the outer offset is a constant vector pointing to the right
, which |
1621 // guarantees that the distance value along the outer rectangle is c
onstant. | 1630 // guarantees that the distance value along the outer rectangle is c
onstant. |
1622 if (kOverstroke_RRectType == fType) { | 1631 if (kOverstroke_RRectType == args.fType) { |
1623 SkScalar overstrokeOuterRadius = outerRadius - args.fInnerRadius
; | 1632 SkScalar overstrokeOuterRadius = outerRadius - args.fInnerRadius
; |
1624 // this is the normalized distance from the outer rectangle of t
his | 1633 // this is the normalized distance from the outer rectangle of t
his |
1625 // geometry to the outer edge | 1634 // geometry to the outer edge |
1626 SkScalar maxOffset = -args.fInnerRadius/overstrokeOuterRadius; | 1635 SkScalar maxOffset = -args.fInnerRadius / overstrokeOuterRadius; |
1627 | 1636 |
1628 verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[
1]); | 1637 verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[
1]); |
1629 verts->fColor = color; | 1638 verts->fColor = color; |
1630 verts->fOffset = SkPoint::Make(maxOffset, 0); | 1639 verts->fOffset = SkPoint::Make(maxOffset, 0); |
1631 verts->fOuterRadius = overstrokeOuterRadius; | 1640 verts->fOuterRadius = overstrokeOuterRadius; |
1632 verts->fInnerRadius = 0; | 1641 verts->fInnerRadius = 0; |
1633 verts++; | 1642 verts++; |
1634 | 1643 |
1635 verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords
[1]); | 1644 verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords
[1]); |
1636 verts->fColor = color; | 1645 verts->fColor = color; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1678 verts->fInnerRadius = 0; | 1687 verts->fInnerRadius = 0; |
1679 verts++; | 1688 verts++; |
1680 | 1689 |
1681 verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords
[2]); | 1690 verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords
[2]); |
1682 verts->fColor = color; | 1691 verts->fColor = color; |
1683 verts->fOffset = SkPoint::Make(maxOffset, 0); | 1692 verts->fOffset = SkPoint::Make(maxOffset, 0); |
1684 verts->fOuterRadius = overstrokeOuterRadius; | 1693 verts->fOuterRadius = overstrokeOuterRadius; |
1685 verts->fInnerRadius = 0; | 1694 verts->fInnerRadius = 0; |
1686 verts++; | 1695 verts++; |
1687 } | 1696 } |
| 1697 |
| 1698 const uint16_t* primIndices = rrect_type_to_indices(args.fType); |
| 1699 const int primIndexCount = rrect_type_to_index_count(args.fType); |
| 1700 for (int i = 0; i < primIndexCount; ++i) { |
| 1701 *indices++ = primIndices[i] + currStartVertex; |
| 1702 } |
| 1703 |
| 1704 currStartVertex += rrect_type_to_vert_count(args.fType); |
1688 } | 1705 } |
1689 | 1706 |
1690 helper.recordDraw(target, gp); | 1707 GrMesh mesh; |
| 1708 mesh.initIndexed(kTriangles_GrPrimitiveType, vertexBuffer, indexBuffer,
firstVertex, |
| 1709 firstIndex, fVertCount, fIndexCount); |
| 1710 target->draw(gp.get(), mesh); |
1691 } | 1711 } |
1692 | 1712 |
1693 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { | 1713 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override { |
1694 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>(); | 1714 RRectCircleRendererBatch* that = t->cast<RRectCircleRendererBatch>(); |
1695 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), | 1715 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi
peline(), |
1696 that->bounds(), caps)) { | 1716 that->bounds(), caps)) { |
1697 return false; | 1717 return false; |
1698 } | 1718 } |
1699 | 1719 |
1700 if (fType != that->fType) { | |
1701 return false; | |
1702 } | |
1703 | |
1704 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing
LocalCoords)) { | 1720 if (!fViewMatrixIfUsingLocalCoords.cheapEqualTo(that->fViewMatrixIfUsing
LocalCoords)) { |
1705 return false; | 1721 return false; |
1706 } | 1722 } |
1707 | 1723 |
1708 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); | 1724 fGeoData.push_back_n(that->fGeoData.count(), that->fGeoData.begin()); |
1709 this->joinBounds(*that); | 1725 this->joinBounds(*that); |
| 1726 fVertCount += that->fVertCount; |
| 1727 fIndexCount += that->fIndexCount; |
| 1728 fAllFill = fAllFill && that->fAllFill; |
1710 return true; | 1729 return true; |
1711 } | 1730 } |
1712 | 1731 |
1713 struct Geometry { | 1732 struct Geometry { |
1714 GrColor fColor; | 1733 GrColor fColor; |
1715 SkScalar fInnerRadius; | 1734 SkScalar fInnerRadius; |
1716 SkScalar fOuterRadius; | 1735 SkScalar fOuterRadius; |
1717 SkRect fDevBounds; | 1736 SkRect fDevBounds; |
| 1737 RRectType fType; |
1718 }; | 1738 }; |
1719 | 1739 |
1720 RRectType fType; | 1740 SkSTArray<1, Geometry, true> fGeoData; |
1721 SkMatrix fViewMatrixIfUsingLocalCoords; | 1741 SkMatrix fViewMatrixIfUsingLocalCoords; |
1722 SkSTArray<1, Geometry, true> fGeoData; | 1742 int fVertCount; |
| 1743 int fIndexCount; |
| 1744 bool fAllFill; |
1723 | 1745 |
1724 typedef GrVertexBatch INHERITED; | 1746 typedef GrVertexBatch INHERITED; |
1725 }; | 1747 }; |
1726 | 1748 |
| 1749 static const int kNumRRectsInIndexBuffer = 256; |
| 1750 |
| 1751 GR_DECLARE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); |
| 1752 GR_DECLARE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); |
| 1753 static const GrBuffer* ref_rrect_index_buffer(RRectType type, |
| 1754 GrResourceProvider* resourceProvid
er) { |
| 1755 GR_DEFINE_STATIC_UNIQUE_KEY(gStrokeRRectOnlyIndexBufferKey); |
| 1756 GR_DEFINE_STATIC_UNIQUE_KEY(gRRectOnlyIndexBufferKey); |
| 1757 switch (type) { |
| 1758 case kFill_RRectType: |
| 1759 return resourceProvider->findOrCreateInstancedIndexBuffer( |
| 1760 gStandardRRectIndices, kIndicesPerFillRRect, kNumRRectsInIndexBu
ffer, |
| 1761 kVertsPerStandardRRect, gRRectOnlyIndexBufferKey); |
| 1762 case kStroke_RRectType: |
| 1763 return resourceProvider->findOrCreateInstancedIndexBuffer( |
| 1764 gStandardRRectIndices, kIndicesPerStrokeRRect, kNumRRectsInIndex
Buffer, |
| 1765 kVertsPerStandardRRect, gStrokeRRectOnlyIndexBufferKey); |
| 1766 default: |
| 1767 SkASSERT(false); |
| 1768 return nullptr; |
| 1769 }; |
| 1770 } |
| 1771 |
1727 class RRectEllipseRendererBatch : public GrVertexBatch { | 1772 class RRectEllipseRendererBatch : public GrVertexBatch { |
1728 public: | 1773 public: |
1729 DEFINE_BATCH_CLASS_ID | 1774 DEFINE_BATCH_CLASS_ID |
1730 | 1775 |
1731 // If devStrokeWidths values are <= 0 indicates then fill only. Otherwise, s
trokeOnly indicates | 1776 // If devStrokeWidths values are <= 0 indicates then fill only. Otherwise, s
trokeOnly indicates |
1732 // whether the rrect is only stroked or stroked and filled. | 1777 // whether the rrect is only stroked or stroked and filled. |
1733 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const
SkRect& devRect, | 1778 static GrDrawBatch* Create(GrColor color, const SkMatrix& viewMatrix, const
SkRect& devRect, |
1734 float devXRadius, float devYRadius, SkVector devS
trokeWidths, | 1779 float devXRadius, float devYRadius, SkVector devS
trokeWidths, |
1735 bool strokeOnly) { | 1780 bool strokeOnly) { |
1736 SkASSERT(devXRadius > 0.5); | 1781 SkASSERT(devXRadius > 0.5); |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2128 } | 2173 } |
2129 | 2174 |
2130 DRAW_BATCH_TEST_DEFINE(RRectBatch) { | 2175 DRAW_BATCH_TEST_DEFINE(RRectBatch) { |
2131 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); | 2176 SkMatrix viewMatrix = GrTest::TestMatrixRectStaysRect(random); |
2132 GrColor color = GrRandomColor(random); | 2177 GrColor color = GrRandomColor(random); |
2133 const SkRRect& rrect = GrTest::TestRRectSimple(random); | 2178 const SkRRect& rrect = GrTest::TestRRectSimple(random); |
2134 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra
ndom)); | 2179 return create_rrect_batch(color, viewMatrix, rrect, GrTest::TestStrokeRec(ra
ndom)); |
2135 } | 2180 } |
2136 | 2181 |
2137 #endif | 2182 #endif |
OLD | NEW |