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

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

Issue 2272703004: Add Ganesh support for circular roundrects with strokes > 2*radii. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Some cleanup Created 4 years, 3 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698