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 1445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1456 batch->fMaskType = kGrayscaleCoverageMask_MaskType; | 1456 batch->fMaskType = kGrayscaleCoverageMask_MaskType; |
1457 break; | 1457 break; |
1458 case kA565_GrMaskFormat: | 1458 case kA565_GrMaskFormat: |
1459 batch->fMaskType = kLCDCoverageMask_MaskType; | 1459 batch->fMaskType = kLCDCoverageMask_MaskType; |
1460 break; | 1460 break; |
1461 case kARGB_GrMaskFormat: | 1461 case kARGB_GrMaskFormat: |
1462 batch->fMaskType = kColorBitmapMask_MaskType; | 1462 batch->fMaskType = kColorBitmapMask_MaskType; |
1463 break; | 1463 break; |
1464 } | 1464 } |
1465 batch->fBatch.fNumGlyphs = glyphCount; | 1465 batch->fBatch.fNumGlyphs = glyphCount; |
1466 batch->fInstanceCount = 1; | 1466 batch->fGeoCount = 1; |
1467 batch->fAllocatedCount = kMinAllocated; | |
1468 batch->fFilteredColor = 0; | 1467 batch->fFilteredColor = 0; |
1469 batch->fFontCache = fontCache; | 1468 batch->fFontCache = fontCache; |
1470 batch->fUseBGR = false; | 1469 batch->fUseBGR = false; |
1471 return batch; | 1470 return batch; |
1472 } | 1471 } |
1473 | 1472 |
1474 static TextBatch* CreateDistanceField(int glyphCount, GrBatchFontCache* font
Cache, | 1473 static TextBatch* CreateDistanceField(int glyphCount, GrBatchFontCache* font
Cache, |
1475 DistanceAdjustTable* distanceAdjustTab
le, | 1474 DistanceAdjustTable* distanceAdjustTab
le, |
1476 SkColor filteredColor, bool isLCD, | 1475 SkColor filteredColor, bool isLCD, |
1477 bool useBGR) { | 1476 bool useBGR) { |
1478 TextBatch* batch = SkNEW(TextBatch); | 1477 TextBatch* batch = SkNEW(TextBatch); |
1479 batch->initClassID<TextBatch>(); | 1478 batch->initClassID<TextBatch>(); |
1480 batch->fFontCache = fontCache; | 1479 batch->fFontCache = fontCache; |
1481 batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistan
ceField_MaskType; | 1480 batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistan
ceField_MaskType; |
1482 batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable)); | 1481 batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable)); |
1483 batch->fFilteredColor = filteredColor; | 1482 batch->fFilteredColor = filteredColor; |
1484 batch->fUseBGR = useBGR; | 1483 batch->fUseBGR = useBGR; |
1485 batch->fBatch.fNumGlyphs = glyphCount; | 1484 batch->fBatch.fNumGlyphs = glyphCount; |
1486 batch->fInstanceCount = 1; | 1485 batch->fGeoCount = 1; |
1487 batch->fAllocatedCount = kMinAllocated; | |
1488 return batch; | 1486 return batch; |
1489 } | 1487 } |
1490 | 1488 |
1491 const char* name() const override { return "TextBatch"; } | 1489 const char* name() const override { return "TextBatch"; } |
1492 | 1490 |
1493 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 1491 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
1494 if (kColorBitmapMask_MaskType == fMaskType) { | 1492 if (kColorBitmapMask_MaskType == fMaskType) { |
1495 out->setUnknownFourComponents(); | 1493 out->setUnknownFourComponents(); |
1496 } else { | 1494 } else { |
1497 out->setKnownFourComponents(fBatch.fColor); | 1495 out->setKnownFourComponents(fBatch.fColor); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1571 FlushInfo flushInfo; | 1569 FlushInfo flushInfo; |
1572 flushInfo.fGlyphsToFlush = 0; | 1570 flushInfo.fGlyphsToFlush = 0; |
1573 size_t vertexStride = gp->getVertexStride(); | 1571 size_t vertexStride = gp->getVertexStride(); |
1574 SkASSERT(vertexStride == (usesDistanceFields ? | 1572 SkASSERT(vertexStride == (usesDistanceFields ? |
1575 get_vertex_stride_df(maskFormat, isLCD) : | 1573 get_vertex_stride_df(maskFormat, isLCD) : |
1576 get_vertex_stride(maskFormat))); | 1574 get_vertex_stride(maskFormat))); |
1577 | 1575 |
1578 batchTarget->initDraw(gp, pipeline); | 1576 batchTarget->initDraw(gp, pipeline); |
1579 | 1577 |
1580 int glyphCount = this->numGlyphs(); | 1578 int glyphCount = this->numGlyphs(); |
1581 int instanceCount = fInstanceCount; | |
1582 const GrVertexBuffer* vertexBuffer; | 1579 const GrVertexBuffer* vertexBuffer; |
1583 | 1580 |
1584 void* vertices = batchTarget->makeVertSpace(vertexStride, | 1581 void* vertices = batchTarget->makeVertSpace(vertexStride, |
1585 glyphCount * kVerticesPerGly
ph, | 1582 glyphCount * kVerticesPerGly
ph, |
1586 &vertexBuffer, | 1583 &vertexBuffer, |
1587 &flushInfo.fVertexOffset); | 1584 &flushInfo.fVertexOffset); |
1588 flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer)); | 1585 flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer)); |
1589 flushInfo.fIndexBuffer.reset(batchTarget->resourceProvider()->refQuadInd
exBuffer()); | 1586 flushInfo.fIndexBuffer.reset(batchTarget->resourceProvider()->refQuadInd
exBuffer()); |
1590 if (!vertices || !flushInfo.fVertexBuffer) { | 1587 if (!vertices || !flushInfo.fVertexBuffer) { |
1591 SkDebugf("Could not allocate vertices\n"); | 1588 SkDebugf("Could not allocate vertices\n"); |
1592 return; | 1589 return; |
1593 } | 1590 } |
1594 | 1591 |
1595 unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices); | 1592 unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices); |
1596 | 1593 |
1597 // We cache some values to avoid going to the glyphcache for the same fo
ntScaler twice | 1594 // We cache some values to avoid going to the glyphcache for the same fo
ntScaler twice |
1598 // in a row | 1595 // in a row |
1599 const SkDescriptor* desc = NULL; | 1596 const SkDescriptor* desc = NULL; |
1600 SkGlyphCache* cache = NULL; | 1597 SkGlyphCache* cache = NULL; |
1601 GrFontScaler* scaler = NULL; | 1598 GrFontScaler* scaler = NULL; |
1602 SkTypeface* typeface = NULL; | 1599 SkTypeface* typeface = NULL; |
1603 | 1600 |
1604 for (int i = 0; i < instanceCount; i++) { | 1601 for (int i = 0; i < fGeoCount; i++) { |
1605 Geometry& args = fGeoData[i]; | 1602 Geometry& args = fGeoData[i]; |
1606 Blob* blob = args.fBlob; | 1603 Blob* blob = args.fBlob; |
1607 Run& run = blob->fRuns[args.fRun]; | 1604 Run& run = blob->fRuns[args.fRun]; |
1608 TextInfo& info = run.fSubRunInfo[args.fSubRun]; | 1605 TextInfo& info = run.fSubRunInfo[args.fSubRun]; |
1609 | 1606 |
1610 uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat); | 1607 uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat); |
1611 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas
Gen || | 1608 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas
Gen || |
1612 run.fStrike->isAbandoned(); | 1609 run.fStrike->isAbandoned(); |
1613 bool regenerateColors; | 1610 bool regenerateColors; |
1614 if (usesDistanceFields) { | 1611 if (usesDistanceFields) { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1754 | 1751 |
1755 currVertex += byteCount; | 1752 currVertex += byteCount; |
1756 } | 1753 } |
1757 // Make sure to attach the last cache if applicable | 1754 // Make sure to attach the last cache if applicable |
1758 if (cache) { | 1755 if (cache) { |
1759 SkGlyphCache::AttachCache(cache); | 1756 SkGlyphCache::AttachCache(cache); |
1760 } | 1757 } |
1761 this->flush(batchTarget, &flushInfo); | 1758 this->flush(batchTarget, &flushInfo); |
1762 } | 1759 } |
1763 | 1760 |
1764 // The minimum number of Geometry we will try to allocate. | |
1765 static const int kMinAllocated = 4; | |
1766 | |
1767 // Total number of Geometry this Batch owns | |
1768 int instanceCount() const { return fInstanceCount; } | |
1769 SkAutoSTMalloc<kMinAllocated, Geometry>* geoData() { return &fGeoData; } | |
1770 | |
1771 // to avoid even the initial copy of the struct, we have a getter for the fi
rst item which | 1761 // to avoid even the initial copy of the struct, we have a getter for the fi
rst item which |
1772 // is used to seed the batch with its initial geometry. After seeding, the
client should call | 1762 // is used to seed the batch with its initial geometry. After seeding, the
client should call |
1773 // init() so the Batch can initialize itself | 1763 // init() so the Batch can initialize itself |
1774 Geometry& geometry() { return fGeoData[0]; } | 1764 Geometry& geometry() { return fGeoData[0]; } |
1775 void init() { | 1765 void init() { |
1776 const Geometry& geo = fGeoData[0]; | 1766 const Geometry& geo = fGeoData[0]; |
1777 fBatch.fColor = geo.fColor; | 1767 fBatch.fColor = geo.fColor; |
1778 fBatch.fViewMatrix = geo.fBlob->fViewMatrix; | 1768 fBatch.fViewMatrix = geo.fBlob->fViewMatrix; |
1779 | 1769 |
1780 // We don't yet position distance field text on the cpu, so we have to m
ap the vertex bounds | 1770 // We don't yet position distance field text on the cpu, so we have to m
ap the vertex bounds |
1781 // into device space | 1771 // into device space |
1782 const Run& run = geo.fBlob->fRuns[geo.fRun]; | 1772 const Run& run = geo.fBlob->fRuns[geo.fRun]; |
1783 if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) { | 1773 if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) { |
1784 SkRect bounds = run.fVertexBounds; | 1774 SkRect bounds = run.fVertexBounds; |
1785 fBatch.fViewMatrix.mapRect(&bounds); | 1775 fBatch.fViewMatrix.mapRect(&bounds); |
1786 this->setBounds(bounds); | 1776 this->setBounds(bounds); |
1787 } else { | 1777 } else { |
1788 this->setBounds(run.fVertexBounds); | 1778 this->setBounds(run.fVertexBounds); |
1789 } | 1779 } |
1790 } | 1780 } |
1791 | 1781 |
1792 private: | 1782 private: |
1793 TextBatch() {} // initialized in factory functions. | 1783 TextBatch() {} // initialized in factory functions. |
1794 | 1784 |
1795 ~TextBatch() { | 1785 ~TextBatch() { |
1796 for (int i = 0; i < fInstanceCount; i++) { | 1786 for (int i = 0; i < fGeoCount; i++) { |
1797 fGeoData[i].fBlob->unref(); | 1787 fGeoData[i].fBlob->unref(); |
1798 } | 1788 } |
1799 } | 1789 } |
1800 | 1790 |
1801 GrMaskFormat maskFormat() const { | 1791 GrMaskFormat maskFormat() const { |
1802 switch (fMaskType) { | 1792 switch (fMaskType) { |
1803 case kLCDCoverageMask_MaskType: | 1793 case kLCDCoverageMask_MaskType: |
1804 return kA565_GrMaskFormat; | 1794 return kA565_GrMaskFormat; |
1805 case kColorBitmapMask_MaskType: | 1795 case kColorBitmapMask_MaskType: |
1806 return kARGB_GrMaskFormat; | 1796 return kARGB_GrMaskFormat; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1928 return false; | 1918 return false; |
1929 } | 1919 } |
1930 | 1920 |
1931 // TODO see note above | 1921 // TODO see note above |
1932 if (kLCDDistanceField_MaskType == fMaskType && this->color() != that
->color()) { | 1922 if (kLCDDistanceField_MaskType == fMaskType && this->color() != that
->color()) { |
1933 } | 1923 } |
1934 } | 1924 } |
1935 | 1925 |
1936 fBatch.fNumGlyphs += that->numGlyphs(); | 1926 fBatch.fNumGlyphs += that->numGlyphs(); |
1937 | 1927 |
1938 // copy that->geoData(). We do this manually for performance reasons | 1928 // Reallocate space for geo data if necessary and then import that's geo
data. |
1939 SkAutoSTMalloc<kMinAllocated, Geometry>* otherGeoData = that->geoData(); | 1929 int newGeoCount = that->fGeoCount + fGeoCount; |
1940 int otherInstanceCount = that->instanceCount(); | 1930 // We assume (and here enforce) that the allocation size is the smallest
power of two that |
1941 int allocSize = otherInstanceCount + fInstanceCount; | 1931 // is greater than or equal to the number of geometries (and at least |
1942 if (allocSize > fAllocatedCount) { | 1932 // kMinGeometryAllocated). |
1943 while (allocSize > fAllocatedCount) { | 1933 int newAllocSize = GrNextPow2(newGeoCount); |
1944 fAllocatedCount = fAllocatedCount << 1; | 1934 int currAllocSize = SkTMax<int>(kMinGeometryAllocated, GrNextPow2(fGeoCo
unt)); |
1945 } | 1935 |
1946 fGeoData.realloc(fAllocatedCount); | 1936 if (newAllocSize > currAllocSize) { |
| 1937 fGeoData.realloc(newAllocSize); |
1947 } | 1938 } |
1948 | 1939 |
1949 memcpy(&fGeoData[fInstanceCount], otherGeoData->get(), | 1940 memcpy(&fGeoData[fGeoCount], that->fGeoData.get(), that->fGeoCount * siz
eof(Geometry)); |
1950 otherInstanceCount * sizeof(Geometry)); | 1941 for (int i = fGeoCount; i < newGeoCount; ++i) { |
1951 int total = fInstanceCount + otherInstanceCount; | |
1952 for (int i = fInstanceCount; i < total; i++) { | |
1953 fGeoData[i].fBlob->ref(); | 1942 fGeoData[i].fBlob->ref(); |
1954 } | 1943 } |
1955 fInstanceCount = total; | 1944 fGeoCount = newGeoCount; |
1956 | 1945 |
1957 this->joinBounds(that->bounds()); | 1946 this->joinBounds(that->bounds()); |
1958 return true; | 1947 return true; |
1959 } | 1948 } |
1960 | 1949 |
1961 // TODO just use class params | 1950 // TODO just use class params |
1962 // TODO trying to figure out why lcd is so whack | 1951 // TODO trying to figure out why lcd is so whack |
1963 GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor fi
lteredColor, | 1952 GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor fi
lteredColor, |
1964 GrColor color, GrTexture* texture) { | 1953 GrColor color, GrTexture* texture) { |
1965 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile
rp_FilterMode); | 1954 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile
rp_FilterMode); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2020 struct BatchTracker { | 2009 struct BatchTracker { |
2021 GrColor fColor; | 2010 GrColor fColor; |
2022 SkMatrix fViewMatrix; | 2011 SkMatrix fViewMatrix; |
2023 bool fUsesLocalCoords; | 2012 bool fUsesLocalCoords; |
2024 bool fColorIgnored; | 2013 bool fColorIgnored; |
2025 bool fCoverageIgnored; | 2014 bool fCoverageIgnored; |
2026 int fNumGlyphs; | 2015 int fNumGlyphs; |
2027 }; | 2016 }; |
2028 | 2017 |
2029 BatchTracker fBatch; | 2018 BatchTracker fBatch; |
2030 SkAutoSTMalloc<kMinAllocated, Geometry> fGeoData; | 2019 // The minimum number of Geometry we will try to allocate. |
2031 int fInstanceCount; | 2020 enum { kMinGeometryAllocated = 4 }; |
2032 int fAllocatedCount; | 2021 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData; |
| 2022 int fGeoCount; |
2033 | 2023 |
2034 enum MaskType { | 2024 enum MaskType { |
2035 kGrayscaleCoverageMask_MaskType, | 2025 kGrayscaleCoverageMask_MaskType, |
2036 kLCDCoverageMask_MaskType, | 2026 kLCDCoverageMask_MaskType, |
2037 kColorBitmapMask_MaskType, | 2027 kColorBitmapMask_MaskType, |
2038 kGrayscaleDistanceField_MaskType, | 2028 kGrayscaleDistanceField_MaskType, |
2039 kLCDDistanceField_MaskType, | 2029 kLCDDistanceField_MaskType, |
2040 } fMaskType; | 2030 } fMaskType; |
2041 bool fUseBGR; // fold this into the enum? | 2031 bool fUseBGR; // fold this into the enum? |
2042 | 2032 |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2280 gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMat
rix, text, | 2270 gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMat
rix, text, |
2281 static_cast<size_t>(textLen), 0, 0,
noClip)); | 2271 static_cast<size_t>(textLen), 0, 0,
noClip)); |
2282 | 2272 |
2283 SkScalar transX = static_cast<SkScalar>(random->nextU()); | 2273 SkScalar transX = static_cast<SkScalar>(random->nextU()); |
2284 SkScalar transY = static_cast<SkScalar>(random->nextU()); | 2274 SkScalar transY = static_cast<SkScalar>(random->nextU()); |
2285 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; | 2275 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0]
; |
2286 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t
ransY, skPaint); | 2276 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t
ransY, skPaint); |
2287 } | 2277 } |
2288 | 2278 |
2289 #endif | 2279 #endif |
OLD | NEW |