OLD | NEW |
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 #include "GrAtlasTextContext.h" | 7 #include "GrAtlasTextContext.h" |
8 | 8 |
9 #include "GrBatch.h" | 9 #include "GrBatch.h" |
10 #include "GrBatchFontCache.h" | 10 #include "GrBatchFontCache.h" |
(...skipping 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 | 1437 |
1438 // V3 | 1438 // V3 |
1439 position = reinterpret_cast<SkPoint*>(vertex); | 1439 position = reinterpret_cast<SkPoint*>(vertex); |
1440 position->set(positions.fRight, positions.fTop); | 1440 position->set(positions.fRight, positions.fTop); |
1441 } | 1441 } |
1442 | 1442 |
1443 subRun->fGlyphEndIndex++; | 1443 subRun->fGlyphEndIndex++; |
1444 subRun->fVertexEndIndex += vertexStride * kVerticesPerGlyph; | 1444 subRun->fVertexEndIndex += vertexStride * kVerticesPerGlyph; |
1445 } | 1445 } |
1446 | 1446 |
1447 class BitmapTextBatch : public GrBatch { | 1447 class TextBatch : public GrBatch { |
1448 public: | 1448 public: |
1449 typedef GrAtlasTextContext::DistanceAdjustTable DistanceAdjustTable; | 1449 typedef GrAtlasTextContext::DistanceAdjustTable DistanceAdjustTable; |
1450 typedef GrAtlasTextBlob Blob; | 1450 typedef GrAtlasTextBlob Blob; |
1451 typedef Blob::Run Run; | 1451 typedef Blob::Run Run; |
1452 typedef Run::SubRunInfo TextInfo; | 1452 typedef Run::SubRunInfo TextInfo; |
1453 struct Geometry { | 1453 struct Geometry { |
1454 Blob* fBlob; | 1454 Blob* fBlob; |
1455 int fRun; | 1455 int fRun; |
1456 int fSubRun; | 1456 int fSubRun; |
1457 GrColor fColor; | 1457 GrColor fColor; |
1458 SkScalar fTransX; | 1458 SkScalar fTransX; |
1459 SkScalar fTransY; | 1459 SkScalar fTransY; |
1460 }; | 1460 }; |
1461 | 1461 |
1462 static BitmapTextBatch* Create(GrMaskFormat maskFormat, int glyphCount, | 1462 static TextBatch* CreateBitmap(GrMaskFormat maskFormat, int glyphCount, |
1463 GrBatchFontCache* fontCache) { | 1463 GrBatchFontCache* fontCache) { |
1464 return SkNEW_ARGS(BitmapTextBatch, (maskFormat, glyphCount, fontCache)); | 1464 TextBatch* batch = SkNEW(TextBatch); |
| 1465 |
| 1466 batch->initClassID<TextBatch>(); |
| 1467 batch->fFontCache = fontCache; |
| 1468 switch (maskFormat) { |
| 1469 case kA8_GrMaskFormat: |
| 1470 batch->fMaskType = kGrayscaleCoverageMask_MaskType; |
| 1471 break; |
| 1472 case kA565_GrMaskFormat: |
| 1473 batch->fMaskType = kLCDCoverageMask_MaskType; |
| 1474 break; |
| 1475 case kARGB_GrMaskFormat: |
| 1476 batch->fMaskType = kColorBitmapMask_MaskType; |
| 1477 break; |
| 1478 } |
| 1479 batch->fBatch.fNumGlyphs = glyphCount; |
| 1480 batch->fInstanceCount = 1; |
| 1481 batch->fAllocatedCount = kMinAllocated; |
| 1482 batch->fFilteredColor = 0; |
| 1483 batch->fFontCache = fontCache; |
| 1484 batch->fUseBGR = false; |
| 1485 return batch; |
1465 } | 1486 } |
1466 | 1487 |
1467 static BitmapTextBatch* Create(GrMaskFormat maskFormat, int glyphCount, | 1488 static TextBatch* CreateDistanceField(int glyphCount, GrBatchFontCache* font
Cache, |
1468 GrBatchFontCache* fontCache, | 1489 DistanceAdjustTable* distanceAdjustTab
le, |
1469 DistanceAdjustTable* distanceAdjustTable, | 1490 SkColor filteredColor, bool isLCD, |
1470 SkColor filteredColor, bool useLCDText, | 1491 bool useBGR) { |
1471 bool useBGR) { | 1492 TextBatch* batch = SkNEW(TextBatch); |
1472 return SkNEW_ARGS(BitmapTextBatch, (maskFormat, glyphCount, fontCache, d
istanceAdjustTable, | 1493 batch->initClassID<TextBatch>(); |
1473 filteredColor, useLCDText, useBGR)); | 1494 batch->fFontCache = fontCache; |
| 1495 batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistan
ceField_MaskType; |
| 1496 batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable)); |
| 1497 batch->fFilteredColor = filteredColor; |
| 1498 batch->fUseBGR = useBGR; |
| 1499 batch->fBatch.fNumGlyphs = glyphCount; |
| 1500 batch->fInstanceCount = 1; |
| 1501 batch->fAllocatedCount = kMinAllocated; |
| 1502 return batch; |
1474 } | 1503 } |
1475 | 1504 |
1476 const char* name() const override { return "BitmapTextBatch"; } | 1505 const char* name() const override { return "TextBatch"; } |
1477 | 1506 |
1478 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 1507 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
1479 if (kARGB_GrMaskFormat == fMaskFormat) { | 1508 if (kColorBitmapMask_MaskType == fMaskType) { |
1480 out->setUnknownFourComponents(); | 1509 out->setUnknownFourComponents(); |
1481 } else { | 1510 } else { |
1482 out->setKnownFourComponents(fBatch.fColor); | 1511 out->setKnownFourComponents(fBatch.fColor); |
1483 } | 1512 } |
1484 } | 1513 } |
1485 | 1514 |
1486 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { | 1515 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override { |
1487 if (!fUseDistanceFields) { | 1516 switch (fMaskType) { |
1488 // Bitmap Text | 1517 case kGrayscaleDistanceField_MaskType: |
1489 if (kARGB_GrMaskFormat != fMaskFormat) { | 1518 case kGrayscaleCoverageMask_MaskType: |
1490 if (GrPixelConfigIsAlphaOnly(fPixelConfig)) { | 1519 out->setUnknownSingleComponent(); |
1491 out->setUnknownSingleComponent(); | 1520 break; |
1492 } else if (GrPixelConfigIsOpaque(fPixelConfig)) { | 1521 case kLCDCoverageMask_MaskType: |
1493 out->setUnknownOpaqueFourComponents(); | 1522 case kLCDDistanceField_MaskType: |
1494 out->setUsingLCDCoverage(); | 1523 out->setUnknownOpaqueFourComponents(); |
1495 } else { | 1524 out->setUsingLCDCoverage(); |
1496 out->setUnknownFourComponents(); | 1525 break; |
1497 out->setUsingLCDCoverage(); | 1526 case kColorBitmapMask_MaskType: |
1498 } | |
1499 } else { | |
1500 out->setKnownSingleComponent(0xff); | 1527 out->setKnownSingleComponent(0xff); |
1501 } | |
1502 } else { | |
1503 // Distance fields | |
1504 if (!fUseLCDText) { | |
1505 out->setUnknownSingleComponent(); | |
1506 } else { | |
1507 out->setUnknownFourComponents(); | |
1508 out->setUsingLCDCoverage(); | |
1509 } | |
1510 } | 1528 } |
1511 } | 1529 } |
1512 | 1530 |
1513 void initBatchTracker(const GrPipelineInfo& init) override { | 1531 void initBatchTracker(const GrPipelineInfo& init) override { |
1514 // Handle any color overrides | 1532 // Handle any color overrides |
1515 if (!init.readsColor()) { | 1533 if (!init.readsColor()) { |
1516 fGeoData[0].fColor = GrColor_ILLEGAL; | 1534 fGeoData[0].fColor = GrColor_ILLEGAL; |
1517 } | 1535 } |
1518 init.getOverrideColorIfSet(&fGeoData[0].fColor); | 1536 init.getOverrideColorIfSet(&fGeoData[0].fColor); |
1519 | 1537 |
(...skipping 13 matching lines...) Expand all Loading... |
1533 | 1551 |
1534 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { | 1552 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { |
1535 // if we have RGB, then we won't have any SkShaders so no need to use a
localmatrix. | 1553 // if we have RGB, then we won't have any SkShaders so no need to use a
localmatrix. |
1536 // TODO actually only invert if we don't have RGBA | 1554 // TODO actually only invert if we don't have RGBA |
1537 SkMatrix localMatrix; | 1555 SkMatrix localMatrix; |
1538 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix))
{ | 1556 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix))
{ |
1539 SkDebugf("Cannot invert viewmatrix\n"); | 1557 SkDebugf("Cannot invert viewmatrix\n"); |
1540 return; | 1558 return; |
1541 } | 1559 } |
1542 | 1560 |
1543 GrTexture* texture = fFontCache->getTexture(fMaskFormat); | 1561 GrTexture* texture = fFontCache->getTexture(this->maskFormat()); |
1544 if (!texture) { | 1562 if (!texture) { |
1545 SkDebugf("Could not allocate backing texture for atlas\n"); | 1563 SkDebugf("Could not allocate backing texture for atlas\n"); |
1546 return; | 1564 return; |
1547 } | 1565 } |
1548 | 1566 |
| 1567 bool usesDistanceFields = this->usesDistanceFields(); |
| 1568 GrMaskFormat maskFormat = this->maskFormat(); |
| 1569 bool isLCD = this->isLCD(); |
| 1570 |
1549 SkAutoTUnref<const GrGeometryProcessor> gp; | 1571 SkAutoTUnref<const GrGeometryProcessor> gp; |
1550 if (fUseDistanceFields) { | 1572 if (usesDistanceFields) { |
1551 gp.reset(this->setupDfProcessor(this->viewMatrix(), fFilteredColor,
this->color(), | 1573 gp.reset(this->setupDfProcessor(this->viewMatrix(), fFilteredColor,
this->color(), |
1552 texture)); | 1574 texture)); |
1553 } else { | 1575 } else { |
1554 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k
None_FilterMode); | 1576 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k
None_FilterMode); |
1555 gp.reset(GrBitmapTextGeoProc::Create(this->color(), | 1577 gp.reset(GrBitmapTextGeoProc::Create(this->color(), |
1556 texture, | 1578 texture, |
1557 params, | 1579 params, |
1558 fMaskFormat, | 1580 maskFormat, |
1559 localMatrix, | 1581 localMatrix, |
1560 this->usesLocalCoords())); | 1582 this->usesLocalCoords())); |
1561 } | 1583 } |
1562 | 1584 |
1563 FlushInfo flushInfo; | 1585 FlushInfo flushInfo; |
1564 flushInfo.fGlyphsToFlush = 0; | 1586 flushInfo.fGlyphsToFlush = 0; |
1565 size_t vertexStride = gp->getVertexStride(); | 1587 size_t vertexStride = gp->getVertexStride(); |
1566 SkASSERT(vertexStride == (fUseDistanceFields ? | 1588 SkASSERT(vertexStride == (usesDistanceFields ? |
1567 get_vertex_stride_df(fMaskFormat, fUseLCDText)
: | 1589 get_vertex_stride_df(maskFormat, isLCD) : |
1568 get_vertex_stride(fMaskFormat))); | 1590 get_vertex_stride(maskFormat))); |
1569 | 1591 |
1570 batchTarget->initDraw(gp, pipeline); | 1592 batchTarget->initDraw(gp, pipeline); |
1571 | 1593 |
1572 int glyphCount = this->numGlyphs(); | 1594 int glyphCount = this->numGlyphs(); |
1573 int instanceCount = fInstanceCount; | 1595 int instanceCount = fInstanceCount; |
1574 const GrVertexBuffer* vertexBuffer; | 1596 const GrVertexBuffer* vertexBuffer; |
1575 | 1597 |
1576 void* vertices = batchTarget->makeVertSpace(vertexStride, | 1598 void* vertices = batchTarget->makeVertSpace(vertexStride, |
1577 glyphCount * kVerticesPerGly
ph, | 1599 glyphCount * kVerticesPerGly
ph, |
1578 &vertexBuffer, | 1600 &vertexBuffer, |
(...skipping 13 matching lines...) Expand all Loading... |
1592 SkGlyphCache* cache = NULL; | 1614 SkGlyphCache* cache = NULL; |
1593 GrFontScaler* scaler = NULL; | 1615 GrFontScaler* scaler = NULL; |
1594 SkTypeface* typeface = NULL; | 1616 SkTypeface* typeface = NULL; |
1595 | 1617 |
1596 for (int i = 0; i < instanceCount; i++) { | 1618 for (int i = 0; i < instanceCount; i++) { |
1597 Geometry& args = fGeoData[i]; | 1619 Geometry& args = fGeoData[i]; |
1598 Blob* blob = args.fBlob; | 1620 Blob* blob = args.fBlob; |
1599 Run& run = blob->fRuns[args.fRun]; | 1621 Run& run = blob->fRuns[args.fRun]; |
1600 TextInfo& info = run.fSubRunInfo[args.fSubRun]; | 1622 TextInfo& info = run.fSubRunInfo[args.fSubRun]; |
1601 | 1623 |
1602 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); | 1624 uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat); |
1603 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas
Gen || | 1625 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas
Gen || |
1604 run.fStrike->isAbandoned(); | 1626 run.fStrike->isAbandoned(); |
1605 bool regenerateColors; | 1627 bool regenerateColors; |
1606 if (fUseDistanceFields) { | 1628 if (usesDistanceFields) { |
1607 regenerateColors = !fUseLCDText && run.fColor != args.fColor; | 1629 regenerateColors = !isLCD && run.fColor != args.fColor; |
1608 } else { | 1630 } else { |
1609 regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColor
!= args.fColor; | 1631 regenerateColors = kA8_GrMaskFormat == maskFormat && run.fColor
!= args.fColor; |
1610 } | 1632 } |
1611 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.
f; | 1633 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.
f; |
1612 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; | 1634 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; |
1613 | 1635 |
1614 // We regenerate both texture coords and colors in the blob itself,
and update the | 1636 // We regenerate both texture coords and colors in the blob itself,
and update the |
1615 // atlas generation. If we don't end up purging any unused plots, w
e can avoid | 1637 // atlas generation. If we don't end up purging any unused plots, w
e can avoid |
1616 // regenerating the coords. We could take a finer grained approach
to updating texture | 1638 // regenerating the coords. We could take a finer grained approach
to updating texture |
1617 // coords but its not clear if the extra bookkeeping would offset an
y gains. | 1639 // coords but its not clear if the extra bookkeeping would offset an
y gains. |
1618 // To avoid looping over the glyphs twice, we do one loop and condit
ionally update color | 1640 // To avoid looping over the glyphs twice, we do one loop and condit
ionally update color |
1619 // or coords as needed. One final note, if we have to break a run f
or an atlas eviction | 1641 // or coords as needed. One final note, if we have to break a run f
or an atlas eviction |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 GrGlyph* glyph; | 1689 GrGlyph* glyph; |
1668 if (regenerateGlyphs) { | 1690 if (regenerateGlyphs) { |
1669 // Get the id from the old glyph, and use the new st
rike to lookup | 1691 // Get the id from the old glyph, and use the new st
rike to lookup |
1670 // the glyph. | 1692 // the glyph. |
1671 glyph = blob->fGlyphs[glyphOffset]; | 1693 glyph = blob->fGlyphs[glyphOffset]; |
1672 blob->fGlyphs[glyphOffset] = strike->getGlyph(glyph-
>fPackedID, | 1694 blob->fGlyphs[glyphOffset] = strike->getGlyph(glyph-
>fPackedID, |
1673 scaler
); | 1695 scaler
); |
1674 } | 1696 } |
1675 glyph = blob->fGlyphs[glyphOffset]; | 1697 glyph = blob->fGlyphs[glyphOffset]; |
1676 SkASSERT(glyph); | 1698 SkASSERT(glyph); |
1677 SkASSERT(glyph->fMaskFormat == fMaskFormat); | 1699 SkASSERT(glyph->fMaskFormat == this->maskFormat()); |
1678 | 1700 |
1679 if (!fFontCache->hasGlyph(glyph) && | 1701 if (!fFontCache->hasGlyph(glyph) && |
1680 !strike->addGlyphToAtlas(batchTarget, glyph, scaler)
) { | 1702 !strike->addGlyphToAtlas(batchTarget, glyph, scaler)
) { |
1681 this->flush(batchTarget, &flushInfo); | 1703 this->flush(batchTarget, &flushInfo); |
1682 batchTarget->initDraw(gp, pipeline); | 1704 batchTarget->initDraw(gp, pipeline); |
1683 brokenRun = glyphIdx > 0; | 1705 brokenRun = glyphIdx > 0; |
1684 | 1706 |
1685 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(
batchTarget, | 1707 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(
batchTarget, |
1686
glyph, | 1708
glyph, |
1687
scaler); | 1709
scaler); |
(...skipping 30 matching lines...) Expand all Loading... |
1718 flushInfo.fGlyphsToFlush++; | 1740 flushInfo.fGlyphsToFlush++; |
1719 } | 1741 } |
1720 | 1742 |
1721 // We my have changed the color so update it here | 1743 // We my have changed the color so update it here |
1722 run.fColor = args.fColor; | 1744 run.fColor = args.fColor; |
1723 if (regenerateTextureCoords) { | 1745 if (regenerateTextureCoords) { |
1724 if (regenerateGlyphs) { | 1746 if (regenerateGlyphs) { |
1725 run.fStrike.reset(SkRef(strike)); | 1747 run.fStrike.reset(SkRef(strike)); |
1726 } | 1748 } |
1727 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt
lasGeneration : | 1749 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt
lasGeneration : |
1728 fFontCache->atlasGenerat
ion(fMaskFormat); | 1750 fFontCache->atlasGenerat
ion(maskFormat); |
1729 } | 1751 } |
1730 } else { | 1752 } else { |
1731 flushInfo.fGlyphsToFlush += glyphCount; | 1753 flushInfo.fGlyphsToFlush += glyphCount; |
1732 | 1754 |
1733 // set use tokens for all of the glyphs in our subrun. This is
only valid if we | 1755 // set use tokens for all of the glyphs in our subrun. This is
only valid if we |
1734 // have a valid atlas generation | 1756 // have a valid atlas generation |
1735 fFontCache->setUseTokenBulk(info.fBulkUseToken, | 1757 fFontCache->setUseTokenBulk(info.fBulkUseToken, |
1736 batchTarget->currentToken(), | 1758 batchTarget->currentToken(), |
1737 fMaskFormat); | 1759 maskFormat); |
1738 } | 1760 } |
1739 | 1761 |
1740 // now copy all vertices | 1762 // now copy all vertices |
1741 size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex; | 1763 size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex; |
1742 memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCou
nt); | 1764 memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCou
nt); |
1743 | 1765 |
1744 currVertex += byteCount; | 1766 currVertex += byteCount; |
1745 } | 1767 } |
1746 // Make sure to attach the last cache if applicable | 1768 // Make sure to attach the last cache if applicable |
1747 if (cache) { | 1769 if (cache) { |
(...skipping 24 matching lines...) Expand all Loading... |
1772 if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) { | 1794 if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) { |
1773 SkRect bounds = run.fVertexBounds; | 1795 SkRect bounds = run.fVertexBounds; |
1774 fBatch.fViewMatrix.mapRect(&bounds); | 1796 fBatch.fViewMatrix.mapRect(&bounds); |
1775 this->setBounds(bounds); | 1797 this->setBounds(bounds); |
1776 } else { | 1798 } else { |
1777 this->setBounds(run.fVertexBounds); | 1799 this->setBounds(run.fVertexBounds); |
1778 } | 1800 } |
1779 } | 1801 } |
1780 | 1802 |
1781 private: | 1803 private: |
1782 BitmapTextBatch(GrMaskFormat maskFormat, int glyphCount, GrBatchFontCache* f
ontCache) | 1804 TextBatch() {} // initialized in factory functions. |
1783 : fMaskFormat(maskFormat) | |
1784 , fPixelConfig(fontCache->getPixelConfig(maskFormat)) | |
1785 , fFontCache(fontCache) | |
1786 , fUseDistanceFields(false) { | |
1787 this->initClassID<BitmapTextBatch>(); | |
1788 fBatch.fNumGlyphs = glyphCount; | |
1789 fInstanceCount = 1; | |
1790 fAllocatedCount = kMinAllocated; | |
1791 } | |
1792 | 1805 |
1793 BitmapTextBatch(GrMaskFormat maskFormat, int glyphCount, GrBatchFontCache* f
ontCache, | 1806 ~TextBatch() { |
1794 DistanceAdjustTable* distanceAdjustTable, SkColor filteredCo
lor, | |
1795 bool useLCDText, bool useBGR) | |
1796 : fMaskFormat(maskFormat) | |
1797 , fPixelConfig(fontCache->getPixelConfig(maskFormat)) | |
1798 , fFontCache(fontCache) | |
1799 , fDistanceAdjustTable(SkRef(distanceAdjustTable)) | |
1800 , fFilteredColor(filteredColor) | |
1801 , fUseDistanceFields(true) | |
1802 , fUseLCDText(useLCDText) | |
1803 , fUseBGR(useBGR) { | |
1804 this->initClassID<BitmapTextBatch>(); | |
1805 fBatch.fNumGlyphs = glyphCount; | |
1806 fInstanceCount = 1; | |
1807 fAllocatedCount = kMinAllocated; | |
1808 SkASSERT(fMaskFormat == kA8_GrMaskFormat); | |
1809 } | |
1810 | |
1811 ~BitmapTextBatch() { | |
1812 for (int i = 0; i < fInstanceCount; i++) { | 1807 for (int i = 0; i < fInstanceCount; i++) { |
1813 fGeoData[i].fBlob->unref(); | 1808 fGeoData[i].fBlob->unref(); |
1814 } | 1809 } |
1815 } | 1810 } |
1816 | 1811 |
| 1812 GrMaskFormat maskFormat() const { |
| 1813 switch (fMaskType) { |
| 1814 case kLCDCoverageMask_MaskType: |
| 1815 return kA565_GrMaskFormat; |
| 1816 case kColorBitmapMask_MaskType: |
| 1817 return kARGB_GrMaskFormat; |
| 1818 case kGrayscaleCoverageMask_MaskType: |
| 1819 case kGrayscaleDistanceField_MaskType: |
| 1820 case kLCDDistanceField_MaskType: |
| 1821 return kA8_GrMaskFormat; |
| 1822 } |
| 1823 return kA8_GrMaskFormat; // suppress warning |
| 1824 } |
| 1825 |
| 1826 bool usesDistanceFields() const { |
| 1827 return kGrayscaleDistanceField_MaskType == fMaskType || |
| 1828 kLCDDistanceField_MaskType == fMaskType; |
| 1829 } |
| 1830 |
| 1831 bool isLCD() const { |
| 1832 return kLCDCoverageMask_MaskType == fMaskType || |
| 1833 kLCDDistanceField_MaskType == fMaskType; |
| 1834 } |
| 1835 |
1817 void regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex, size_t vertexS
tride) { | 1836 void regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex, size_t vertexS
tride) { |
1818 int width = glyph->fBounds.width(); | 1837 int width = glyph->fBounds.width(); |
1819 int height = glyph->fBounds.height(); | 1838 int height = glyph->fBounds.height(); |
1820 | 1839 |
1821 int u0, v0, u1, v1; | 1840 int u0, v0, u1, v1; |
1822 if (fUseDistanceFields) { | 1841 if (this->usesDistanceFields()) { |
1823 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset; | 1842 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset; |
1824 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset; | 1843 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset; |
1825 u1 = u0 + width - 2 * SK_DistanceFieldInset; | 1844 u1 = u0 + width - 2 * SK_DistanceFieldInset; |
1826 v1 = v0 + height - 2 * SK_DistanceFieldInset; | 1845 v1 = v0 + height - 2 * SK_DistanceFieldInset; |
1827 } else { | 1846 } else { |
1828 u0 = glyph->fAtlasLocation.fX; | 1847 u0 = glyph->fAtlasLocation.fX; |
1829 v0 = glyph->fAtlasLocation.fY; | 1848 v0 = glyph->fAtlasLocation.fY; |
1830 u1 = u0 + width; | 1849 u1 = u0 + width; |
1831 v1 = v0 + height; | 1850 v1 = v0 + height; |
1832 } | 1851 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1885 GrColor color() const { return fBatch.fColor; } | 1904 GrColor color() const { return fBatch.fColor; } |
1886 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } | 1905 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; } |
1887 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } | 1906 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; } |
1888 int numGlyphs() const { return fBatch.fNumGlyphs; } | 1907 int numGlyphs() const { return fBatch.fNumGlyphs; } |
1889 | 1908 |
1890 bool onCombineIfPossible(GrBatch* t) override { | 1909 bool onCombineIfPossible(GrBatch* t) override { |
1891 if (!this->pipeline()->isEqual(*t->pipeline())) { | 1910 if (!this->pipeline()->isEqual(*t->pipeline())) { |
1892 return false; | 1911 return false; |
1893 } | 1912 } |
1894 | 1913 |
1895 BitmapTextBatch* that = t->cast<BitmapTextBatch>(); | 1914 TextBatch* that = t->cast<TextBatch>(); |
1896 | 1915 |
1897 if (fUseDistanceFields != that->fUseDistanceFields) { | 1916 if (fMaskType != that->fMaskType) { |
1898 return false; | 1917 return false; |
1899 } | 1918 } |
1900 | 1919 |
1901 if (!fUseDistanceFields) { | 1920 if (!this->usesDistanceFields()) { |
1902 // Bitmap Text | 1921 // TODO we can often batch across LCD text if we have dual source bl
ending and don't |
1903 if (fMaskFormat != that->fMaskFormat) { | 1922 // have to use the blend constant |
| 1923 if (kGrayscaleCoverageMask_MaskType != fMaskType && this->color() !=
that->color()) { |
1904 return false; | 1924 return false; |
1905 } | 1925 } |
1906 | |
1907 // TODO we can often batch across LCD text if we have dual source bl
ending and don't | |
1908 // have to use the blend constant | |
1909 if (fMaskFormat != kA8_GrMaskFormat && this->color() != that->color(
)) { | |
1910 return false; | |
1911 } | |
1912 | |
1913 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that
->viewMatrix())) { | 1926 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that
->viewMatrix())) { |
1914 return false; | 1927 return false; |
1915 } | 1928 } |
1916 } else { | 1929 } else { |
1917 // Distance Fields | |
1918 SkASSERT(this->fMaskFormat == that->fMaskFormat && | |
1919 this->fMaskFormat == kA8_GrMaskFormat); | |
1920 | |
1921 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { | 1930 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) { |
1922 return false; | 1931 return false; |
1923 } | 1932 } |
1924 | 1933 |
1925 if (fFilteredColor != that->fFilteredColor) { | 1934 if (fFilteredColor != that->fFilteredColor) { |
1926 return false; | 1935 return false; |
1927 } | 1936 } |
1928 | 1937 |
1929 if (fUseLCDText != that->fUseLCDText) { | |
1930 return false; | |
1931 } | |
1932 | |
1933 if (fUseBGR != that->fUseBGR) { | 1938 if (fUseBGR != that->fUseBGR) { |
1934 return false; | 1939 return false; |
1935 } | 1940 } |
1936 | 1941 |
1937 // TODO see note above | 1942 // TODO see note above |
1938 if (fUseLCDText && this->color() != that->color()) { | 1943 if (kLCDDistanceField_MaskType == fMaskType && this->color() != that
->color()) { |
1939 return false; | |
1940 } | 1944 } |
1941 } | 1945 } |
1942 | 1946 |
1943 fBatch.fNumGlyphs += that->numGlyphs(); | 1947 fBatch.fNumGlyphs += that->numGlyphs(); |
1944 | 1948 |
1945 // copy that->geoData(). We do this manually for performance reasons | 1949 // copy that->geoData(). We do this manually for performance reasons |
1946 SkAutoSTMalloc<kMinAllocated, Geometry>* otherGeoData = that->geoData(); | 1950 SkAutoSTMalloc<kMinAllocated, Geometry>* otherGeoData = that->geoData(); |
1947 int otherInstanceCount = that->instanceCount(); | 1951 int otherInstanceCount = that->instanceCount(); |
1948 int allocSize = otherInstanceCount + fInstanceCount; | 1952 int allocSize = otherInstanceCount + fInstanceCount; |
1949 if (allocSize > fAllocatedCount) { | 1953 if (allocSize > fAllocatedCount) { |
(...skipping 13 matching lines...) Expand all Loading... |
1963 | 1967 |
1964 this->joinBounds(that->bounds()); | 1968 this->joinBounds(that->bounds()); |
1965 return true; | 1969 return true; |
1966 } | 1970 } |
1967 | 1971 |
1968 // TODO just use class params | 1972 // TODO just use class params |
1969 // TODO trying to figure out why lcd is so whack | 1973 // TODO trying to figure out why lcd is so whack |
1970 GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor fi
lteredColor, | 1974 GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor fi
lteredColor, |
1971 GrColor color, GrTexture* texture) { | 1975 GrColor color, GrTexture* texture) { |
1972 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile
rp_FilterMode); | 1976 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile
rp_FilterMode); |
1973 | 1977 bool isLCD = this->isLCD(); |
1974 // set up any flags | 1978 // set up any flags |
1975 uint32_t flags = 0; | 1979 uint32_t flags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEf
fectFlag : 0; |
1976 flags |= viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag
: 0; | |
1977 flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0; | |
1978 flags |= fUseLCDText && viewMatrix.rectStaysRect() ? | |
1979 kRectToRect_DistanceFieldEffectFlag : 0; | |
1980 flags |= fUseLCDText && fUseBGR ? kBGR_DistanceFieldEffectFlag : 0; | |
1981 | 1980 |
1982 // see if we need to create a new effect | 1981 // see if we need to create a new effect |
1983 if (fUseLCDText) { | 1982 if (isLCD) { |
| 1983 flags |= kUseLCD_DistanceFieldEffectFlag; |
| 1984 flags |= viewMatrix.rectStaysRect() ? kRectToRect_DistanceFieldEffec
tFlag : 0; |
| 1985 flags |= fUseBGR ? kBGR_DistanceFieldEffectFlag : 0; |
| 1986 |
1984 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol
or); | 1987 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol
or); |
1985 | 1988 |
1986 float redCorrection = | 1989 float redCorrection = |
1987 (*fDistanceAdjustTable)[GrColorUnpackR(colorNoPreMul) >> kDistan
ceAdjustLumShift]; | 1990 (*fDistanceAdjustTable)[GrColorUnpackR(colorNoPreMul) >> kDistan
ceAdjustLumShift]; |
1988 float greenCorrection = | 1991 float greenCorrection = |
1989 (*fDistanceAdjustTable)[GrColorUnpackG(colorNoPreMul) >> kDistan
ceAdjustLumShift]; | 1992 (*fDistanceAdjustTable)[GrColorUnpackG(colorNoPreMul) >> kDistan
ceAdjustLumShift]; |
1990 float blueCorrection = | 1993 float blueCorrection = |
1991 (*fDistanceAdjustTable)[GrColorUnpackB(colorNoPreMul) >> kDistan
ceAdjustLumShift]; | 1994 (*fDistanceAdjustTable)[GrColorUnpackB(colorNoPreMul) >> kDistan
ceAdjustLumShift]; |
1992 GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust = | 1995 GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust = |
1993 GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrectio
n, | 1996 GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrectio
n, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2031 bool fUsesLocalCoords; | 2034 bool fUsesLocalCoords; |
2032 bool fColorIgnored; | 2035 bool fColorIgnored; |
2033 bool fCoverageIgnored; | 2036 bool fCoverageIgnored; |
2034 int fNumGlyphs; | 2037 int fNumGlyphs; |
2035 }; | 2038 }; |
2036 | 2039 |
2037 BatchTracker fBatch; | 2040 BatchTracker fBatch; |
2038 SkAutoSTMalloc<kMinAllocated, Geometry> fGeoData; | 2041 SkAutoSTMalloc<kMinAllocated, Geometry> fGeoData; |
2039 int fInstanceCount; | 2042 int fInstanceCount; |
2040 int fAllocatedCount; | 2043 int fAllocatedCount; |
2041 GrMaskFormat fMaskFormat; | 2044 |
2042 GrPixelConfig fPixelConfig; | 2045 enum MaskType { |
| 2046 kGrayscaleCoverageMask_MaskType, |
| 2047 kLCDCoverageMask_MaskType, |
| 2048 kColorBitmapMask_MaskType, |
| 2049 kGrayscaleDistanceField_MaskType, |
| 2050 kLCDDistanceField_MaskType, |
| 2051 } fMaskType; |
| 2052 bool fUseBGR; // fold this into the enum? |
| 2053 |
2043 GrBatchFontCache* fFontCache; | 2054 GrBatchFontCache* fFontCache; |
2044 | 2055 |
2045 // Distance field properties | 2056 // Distance field properties |
2046 SkAutoTUnref<const DistanceAdjustTable> fDistanceAdjustTable; | 2057 SkAutoTUnref<const DistanceAdjustTable> fDistanceAdjustTable; |
2047 SkColor fFilteredColor; | 2058 SkColor fFilteredColor; |
2048 bool fUseDistanceFields; | |
2049 bool fUseLCDText; | |
2050 bool fUseBGR; | |
2051 }; | 2059 }; |
2052 | 2060 |
2053 void GrAtlasTextContext::flushRunAsPaths(GrRenderTarget* rt, const SkTextBlob::R
unIterator& it, | 2061 void GrAtlasTextContext::flushRunAsPaths(GrRenderTarget* rt, const SkTextBlob::R
unIterator& it, |
2054 const GrClip& clip, const SkPaint& skPa
int, | 2062 const GrClip& clip, const SkPaint& skPa
int, |
2055 SkDrawFilter* drawFilter, const SkMatri
x& viewMatrix, | 2063 SkDrawFilter* drawFilter, const SkMatri
x& viewMatrix, |
2056 const SkIRect& clipBounds, SkScalar x,
SkScalar y) { | 2064 const SkIRect& clipBounds, SkScalar x,
SkScalar y) { |
2057 SkPaint runPaint = skPaint; | 2065 SkPaint runPaint = skPaint; |
2058 | 2066 |
2059 size_t textLen = it.glyphCount() * sizeof(uint16_t); | 2067 size_t textLen = it.glyphCount() * sizeof(uint16_t); |
2060 const SkPoint& offset = it.offset(); | 2068 const SkPoint& offset = it.offset(); |
(...skipping 19 matching lines...) Expand all Loading... |
2080 clipBounds); | 2088 clipBounds); |
2081 break; | 2089 break; |
2082 case SkTextBlob::kFull_Positioning: | 2090 case SkTextBlob::kFull_Positioning: |
2083 this->drawPosTextAsPath(rt, clip, runPaint, viewMatrix, | 2091 this->drawPosTextAsPath(rt, clip, runPaint, viewMatrix, |
2084 (const char*)it.glyphs(), | 2092 (const char*)it.glyphs(), |
2085 textLen, it.pos(), 2, SkPoint::Make(x, y), c
lipBounds); | 2093 textLen, it.pos(), 2, SkPoint::Make(x, y), c
lipBounds); |
2086 break; | 2094 break; |
2087 } | 2095 } |
2088 } | 2096 } |
2089 | 2097 |
2090 | 2098 inline GrBatch* |
2091 inline BitmapTextBatch* | |
2092 GrAtlasTextContext::createBatch(GrAtlasTextBlob* cacheBlob, const PerSubRunInfo&
info, | 2099 GrAtlasTextContext::createBatch(GrAtlasTextBlob* cacheBlob, const PerSubRunInfo&
info, |
2093 int glyphCount, int run, int subRun, | 2100 int glyphCount, int run, int subRun, |
2094 GrColor color, SkScalar transX, SkScalar transY, | 2101 GrColor color, SkScalar transX, SkScalar transY, |
2095 const SkPaint& skPaint) { | 2102 const SkPaint& skPaint) { |
2096 GrMaskFormat format = info.fMaskFormat; | 2103 GrMaskFormat format = info.fMaskFormat; |
2097 GrColor subRunColor; | 2104 GrColor subRunColor; |
2098 if (kARGB_GrMaskFormat == format) { | 2105 if (kARGB_GrMaskFormat == format) { |
2099 uint8_t paintAlpha = skPaint.getAlpha(); | 2106 uint8_t paintAlpha = skPaint.getAlpha(); |
2100 subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAl
pha); | 2107 subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAl
pha); |
2101 } else { | 2108 } else { |
2102 subRunColor = color; | 2109 subRunColor = color; |
2103 } | 2110 } |
2104 | 2111 |
2105 BitmapTextBatch* batch; | 2112 TextBatch* batch; |
2106 if (info.fDrawAsDistanceFields) { | 2113 if (info.fDrawAsDistanceFields) { |
2107 SkColor filteredColor; | 2114 SkColor filteredColor; |
2108 SkColorFilter* colorFilter = skPaint.getColorFilter(); | 2115 SkColorFilter* colorFilter = skPaint.getColorFilter(); |
2109 if (colorFilter) { | 2116 if (colorFilter) { |
2110 filteredColor = colorFilter->filterColor(skPaint.getColor()); | 2117 filteredColor = colorFilter->filterColor(skPaint.getColor()); |
2111 } else { | 2118 } else { |
2112 filteredColor = skPaint.getColor(); | 2119 filteredColor = skPaint.getColor(); |
2113 } | 2120 } |
2114 bool useBGR = SkPixelGeometryIsBGR(fSurfaceProps.pixelGeometry()); | 2121 bool useBGR = SkPixelGeometryIsBGR(fSurfaceProps.pixelGeometry()); |
2115 batch = BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFo
ntCache(), | 2122 batch = TextBatch::CreateDistanceField(glyphCount, fContext->getBatchFon
tCache(), |
2116 fDistanceAdjustTable, filteredColor, | 2123 fDistanceAdjustTable, filteredCol
or, |
2117 info.fUseLCDText, useBGR); | 2124 info.fUseLCDText, useBGR); |
2118 } else { | 2125 } else { |
2119 batch = BitmapTextBatch::Create(format, glyphCount, fContext->getBatchFo
ntCache()); | 2126 batch = TextBatch::CreateBitmap(format, glyphCount, fContext->getBatchFo
ntCache()); |
2120 } | 2127 } |
2121 BitmapTextBatch::Geometry& geometry = batch->geometry(); | 2128 TextBatch::Geometry& geometry = batch->geometry(); |
2122 geometry.fBlob = SkRef(cacheBlob); | 2129 geometry.fBlob = SkRef(cacheBlob); |
2123 geometry.fRun = run; | 2130 geometry.fRun = run; |
2124 geometry.fSubRun = subRun; | 2131 geometry.fSubRun = subRun; |
2125 geometry.fColor = subRunColor; | 2132 geometry.fColor = subRunColor; |
2126 geometry.fTransX = transX; | 2133 geometry.fTransX = transX; |
2127 geometry.fTransY = transY; | 2134 geometry.fTransY = transY; |
2128 batch->init(); | 2135 batch->init(); |
2129 | 2136 |
2130 return batch; | 2137 return batch; |
2131 } | 2138 } |
2132 | 2139 |
2133 inline void GrAtlasTextContext::flushRun(GrPipelineBuilder* pipelineBuilder, | 2140 inline void GrAtlasTextContext::flushRun(GrPipelineBuilder* pipelineBuilder, |
2134 GrAtlasTextBlob* cacheBlob, int run, Gr
Color color, | 2141 GrAtlasTextBlob* cacheBlob, int run, Gr
Color color, |
2135 SkScalar transX, SkScalar transY, | 2142 SkScalar transX, SkScalar transY, |
2136 const SkPaint& skPaint) { | 2143 const SkPaint& skPaint) { |
2137 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub
Run++) { | 2144 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub
Run++) { |
2138 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; | 2145 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; |
2139 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; | 2146 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; |
2140 if (0 == glyphCount) { | 2147 if (0 == glyphCount) { |
2141 continue; | 2148 continue; |
2142 } | 2149 } |
2143 | 2150 |
2144 SkAutoTUnref<BitmapTextBatch> batch(this->createBatch(cacheBlob, info, g
lyphCount, run, | 2151 SkAutoTUnref<GrBatch> batch(this->createBatch(cacheBlob, info, glyphCoun
t, run, |
2145 subRun, color, tra
nsX, transY, | 2152 subRun, color, transX, tra
nsY, |
2146 skPaint)); | 2153 skPaint)); |
2147 fDrawContext->drawBatch(pipelineBuilder, batch); | 2154 fDrawContext->drawBatch(pipelineBuilder, batch); |
2148 } | 2155 } |
2149 } | 2156 } |
2150 | 2157 |
2151 inline void GrAtlasTextContext::flushBigGlyphs(GrAtlasTextBlob* cacheBlob, GrRen
derTarget* rt, | 2158 inline void GrAtlasTextContext::flushBigGlyphs(GrAtlasTextBlob* cacheBlob, GrRen
derTarget* rt, |
2152 const GrClip& clip, const SkPaint
& skPaint, | 2159 const GrClip& clip, const SkPaint
& skPaint, |
2153 SkScalar transX, SkScalar transY, | 2160 SkScalar transX, SkScalar transY, |
2154 const SkIRect& clipBounds) { | 2161 const SkIRect& clipBounds) { |
2155 if (!cacheBlob->fBigGlyphs.count()) { | 2162 if (!cacheBlob->fBigGlyphs.count()) { |
2156 return; | 2163 return; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2284 gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMat
rix, text, | 2291 gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMat
rix, text, |
2285 static_cast<size_t>(textLen), 0, 0,
noClip)); | 2292 static_cast<size_t>(textLen), 0, 0,
noClip)); |
2286 | 2293 |
2287 SkScalar transX = static_cast<SkScalar>(random->nextU()); | 2294 SkScalar transX = static_cast<SkScalar>(random->nextU()); |
2288 SkScalar transY = static_cast<SkScalar>(random->nextU()); | 2295 SkScalar transY = static_cast<SkScalar>(random->nextU()); |
2289 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; | 2296 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; |
2290 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t
ransY, skPaint); | 2297 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t
ransY, skPaint); |
2291 } | 2298 } |
2292 | 2299 |
2293 #endif | 2300 #endif |
OLD | NEW |