extract GlyphVector into GrGlyphVector

Extricate GlyphVector to test serialization which will be added to
it in the future.

Change-Id: I2baa01d92394b3f9af6fe4c3e14341ed453d572f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/506885
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2022-02-10 13:39:12 -05:00 committed by SkCQ
parent 39728eb980
commit dd6596250d
4 changed files with 218 additions and 179 deletions

View File

@ -352,6 +352,8 @@ skia_gpu_sources = [
"$_src/gpu/text/GrAtlasManager.h",
"$_src/gpu/text/GrDistanceFieldAdjustTable.cpp",
"$_src/gpu/text/GrDistanceFieldAdjustTable.h",
"$_src/gpu/text/GrGlyphVector.cpp",
"$_src/gpu/text/GrGlyphVector.h",
"$_src/gpu/text/GrSDFMaskFilter.cpp",
"$_src/gpu/text/GrSDFMaskFilter.h",
"$_src/gpu/text/GrSDFTControl.cpp",

View File

@ -0,0 +1,118 @@
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/text/GrGlyphVector.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkStrikeSpec.h"
#include "src/core/SkWriteBuffer.h"
#include "src/gpu/text/GrAtlasManager.h"
GrGlyphVector::GrGlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs)
: fStrike{std::move(strike)}
, fGlyphs{glyphs} {
SkASSERT(fStrike != nullptr);
SkASSERT(fGlyphs.size() > 0);
}
GrGlyphVector GrGlyphVector::Make(
sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc) {
SkASSERT(strike != nullptr);
SkASSERT(glyphs.size() > 0);
Variant* variants = alloc->makePODArray<Variant>(glyphs.size());
for (auto [i, gv] : SkMakeEnumerate(glyphs)) {
variants[i] = gv.glyph()->getPackedID();
}
return GrGlyphVector{std::move(strike), SkMakeSpan(variants, glyphs.size())};
}
SkSpan<const GrGlyph*> GrGlyphVector::glyphs() const {
return SkMakeSpan(reinterpret_cast<const GrGlyph**>(fGlyphs.data()), fGlyphs.size());
}
// packedGlyphIDToGrGlyph must be run in single-threaded mode.
// If fStrike != nullptr then the conversion to GrGlyph* has not happened.
void GrGlyphVector::packedGlyphIDToGrGlyph(GrStrikeCache* cache) {
if (fStrike != nullptr) {
fGrStrike = cache->findOrCreateStrike(fStrike->strikeSpec());
for (auto& variant : fGlyphs) {
variant.grGlyph = fGrStrike->getGlyph(variant.packedGlyphID);
}
// Drop the ref on the strike that was taken in the SkGlyphRunPainter process* methods.
fStrike = nullptr;
}
}
std::tuple<bool, int> GrGlyphVector::regenerateAtlas(int begin, int end,
GrMaskFormat maskFormat,
int srcPadding,
GrMeshDrawTarget* target,
bool bilerpPadding) {
GrAtlasManager* atlasManager = target->atlasManager();
GrDeferredUploadTarget* uploadTarget = target->deferredUploadTarget();
uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
this->packedGlyphIDToGrGlyph(target->strikeCache());
if (fAtlasGeneration != currentAtlasGen) {
// Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
// is set to kInvalidAtlasGeneration) or the atlas has changed in subsequent calls..
fBulkUseToken.reset();
SkBulkGlyphMetricsAndImages metricsAndImages{fGrStrike->strikeSpec()};
// Update the atlas information in the GrStrike.
auto tokenTracker = uploadTarget->tokenTracker();
auto glyphs = fGlyphs.subspan(begin, end - begin);
int glyphsPlacedInAtlas = 0;
bool success = true;
for (const Variant& variant : glyphs) {
GrGlyph* grGlyph = variant.grGlyph;
SkASSERT(grGlyph != nullptr);
if (!atlasManager->hasGlyph(maskFormat, grGlyph)) {
const SkGlyph& skGlyph = *metricsAndImages.glyph(grGlyph->fPackedID);
auto code = atlasManager->addGlyphToAtlas(
skGlyph, grGlyph, srcPadding, target->resourceProvider(),
uploadTarget, bilerpPadding);
if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) {
success = code != GrDrawOpAtlas::ErrorCode::kError;
break;
}
}
atlasManager->addGlyphToBulkAndSetUseToken(
&fBulkUseToken, maskFormat, grGlyph,
tokenTracker->nextDrawToken());
glyphsPlacedInAtlas++;
}
// Update atlas generation if there are no more glyphs to put in the atlas.
if (success && begin + glyphsPlacedInAtlas == SkCount(fGlyphs)) {
// Need to get the freshest value of the atlas' generation because
// updateTextureCoordinates may have changed it.
fAtlasGeneration = atlasManager->atlasGeneration(maskFormat);
}
return {success, glyphsPlacedInAtlas};
} else {
// The atlas hasn't changed, so our texture coordinates are still valid.
if (end == SkCount(fGlyphs)) {
// The atlas hasn't changed and the texture coordinates are all still valid. Update
// all the plots used to the new use token.
atlasManager->setUseTokenBulk(fBulkUseToken,
uploadTarget->tokenTracker()->nextDrawToken(),
maskFormat);
}
return {true, end - begin};
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2022 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrGlyphVector_DEFINED
#define GrGlyphVector_DEFINED
#include "include/core/SkSpan.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkGlyphBuffer.h"
#include "src/gpu/GrGlyph.h"
#include "src/gpu/GrMeshDrawTarget.h"
#include "src/gpu/GrSubRunAllocator.h"
#include "src/gpu/text/GrStrikeCache.h"
// -- GlyphVector ----------------------------------------------------------------------------------
// GlyphVector provides a way to delay the lookup of GrGlyphs until the code is running on the
// GPU in single threaded mode. The GlyphVector is created in a multi-threaded environment, but
// the GrStrikeCache is only single threaded (and must be single threaded because of the atlas).
class GrGlyphVector {
public:
union Variant {
// Initially, filled with packed id, but changed to GrGlyph* in the onPrepare stage.
SkPackedGlyphID packedGlyphID;
GrGlyph* grGlyph;
// Add ctors to help SkArenaAlloc create arrays.
Variant() : grGlyph{nullptr} {}
Variant(SkPackedGlyphID id) : packedGlyphID{id} {}
};
GrGlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs);
static GrGlyphVector Make(
sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc);
SkSpan<const GrGlyph*> glyphs() const;
void packedGlyphIDToGrGlyph(GrStrikeCache* cache);
std::tuple<bool, int> regenerateAtlas(
int begin, int end,
GrMaskFormat maskFormat,
int srcPadding,
GrMeshDrawTarget *,
bool bilerpPadding = false);
static size_t GlyphVectorSize(size_t count) {
return sizeof(Variant) * count;
}
private:
sk_sp<SkStrike> fStrike;
SkSpan<Variant> fGlyphs;
sk_sp<GrTextStrike> fGrStrike{nullptr};
uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
};
#endif // GrGlyphVector_DEFINED

View File

@ -24,6 +24,7 @@
#include "src/gpu/effects/GrDistanceFieldGeoProc.h"
#include "src/gpu/geometry/GrStyledShape.h"
#include "src/gpu/text/GrAtlasManager.h"
#include "src/gpu/text/GrGlyphVector.h"
#include "src/gpu/text/GrStrikeCache.h"
#include "src/gpu/text/GrTextBlob.h"
@ -646,148 +647,6 @@ public:
const GrAtlasSubRun* testingOnly_atlasSubRun() const override { return nullptr; }
};
// -- GlyphVector ----------------------------------------------------------------------------------
// GlyphVector provides a way to delay the lookup of GrGlyphs until the code is running on the
// GPU in single threaded mode. The GlyphVector is created in a multi-threaded environment, but
// the GrStrikeCache is only single threaded (and must be single threaded because of the atlas).
class GlyphVector {
public:
union Variant {
// Initially, filled with packed id, but changed to GrGlyph* in the onPrepare stage.
SkPackedGlyphID packedGlyphID;
GrGlyph* grGlyph;
// Add ctors to help SkArenaAlloc create arrays.
Variant() : grGlyph{nullptr} {}
Variant(SkPackedGlyphID id) : packedGlyphID{id} {}
};
GlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs);
static GlyphVector Make(
sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc);
SkSpan<const GrGlyph*> glyphs() const;
void packedGlyphIDToGrGlyph(GrStrikeCache* cache);
std::tuple<bool, int> regenerateAtlas(
int begin, int end,
GrMaskFormat maskFormat,
int srcPadding,
GrMeshDrawTarget *,
bool bilerpPadding = false);
static size_t GlyphVectorSize(size_t count) {
return sizeof(Variant) * count;
}
private:
sk_sp<SkStrike> fStrike;
SkSpan<Variant> fGlyphs;
sk_sp<GrTextStrike> fGrStrike{nullptr};
uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
};
GlyphVector::GlyphVector(sk_sp<SkStrike>&& strike, SkSpan<Variant> glyphs)
: fStrike{std::move(strike)}
, fGlyphs{glyphs} {
SkASSERT(fStrike != nullptr);
}
GlyphVector GlyphVector::Make(
sk_sp<SkStrike>&& strike, SkSpan<SkGlyphVariant> glyphs, GrSubRunAllocator* alloc) {
Variant* variants = alloc->makePODArray<Variant>(glyphs.size());
for (auto [i, gv] : SkMakeEnumerate(glyphs)) {
variants[i] = gv.glyph()->getPackedID();
}
return GlyphVector{std::move(strike), SkMakeSpan(variants, glyphs.size())};
}
SkSpan<const GrGlyph*> GlyphVector::glyphs() const {
return SkMakeSpan(reinterpret_cast<const GrGlyph**>(fGlyphs.data()), fGlyphs.size());
}
// packedGlyphIDToGrGlyph must be run in single-threaded mode.
// If fStrike != nullptr then the conversion to GrGlyph* has not happened.
void GlyphVector::packedGlyphIDToGrGlyph(GrStrikeCache* cache) {
if (fStrike != nullptr) {
fGrStrike = cache->findOrCreateStrike(fStrike->strikeSpec());
for (auto& variant : fGlyphs) {
variant.grGlyph = fGrStrike->getGlyph(variant.packedGlyphID);
}
// Drop the ref on the strike that was taken in the SkGlyphRunPainter process* methods.
fStrike = nullptr;
}
}
std::tuple<bool, int> GlyphVector::regenerateAtlas(int begin, int end,
GrMaskFormat maskFormat,
int srcPadding,
GrMeshDrawTarget* target,
bool bilerpPadding) {
GrAtlasManager* atlasManager = target->atlasManager();
GrDeferredUploadTarget* uploadTarget = target->deferredUploadTarget();
uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
this->packedGlyphIDToGrGlyph(target->strikeCache());
if (fAtlasGeneration != currentAtlasGen) {
// Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
// is set to kInvalidAtlasGeneration) or the atlas has changed in subsequent calls..
fBulkUseToken.reset();
SkBulkGlyphMetricsAndImages metricsAndImages{fGrStrike->strikeSpec()};
// Update the atlas information in the GrStrike.
auto tokenTracker = uploadTarget->tokenTracker();
auto glyphs = fGlyphs.subspan(begin, end - begin);
int glyphsPlacedInAtlas = 0;
bool success = true;
for (const Variant& variant : glyphs) {
GrGlyph* grGlyph = variant.grGlyph;
SkASSERT(grGlyph != nullptr);
if (!atlasManager->hasGlyph(maskFormat, grGlyph)) {
const SkGlyph& skGlyph = *metricsAndImages.glyph(grGlyph->fPackedID);
auto code = atlasManager->addGlyphToAtlas(
skGlyph, grGlyph, srcPadding, target->resourceProvider(),
uploadTarget, bilerpPadding);
if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) {
success = code != GrDrawOpAtlas::ErrorCode::kError;
break;
}
}
atlasManager->addGlyphToBulkAndSetUseToken(
&fBulkUseToken, maskFormat, grGlyph,
tokenTracker->nextDrawToken());
glyphsPlacedInAtlas++;
}
// Update atlas generation if there are no more glyphs to put in the atlas.
if (success && begin + glyphsPlacedInAtlas == SkCount(fGlyphs)) {
// Need to get the freshest value of the atlas' generation because
// updateTextureCoordinates may have changed it.
fAtlasGeneration = atlasManager->atlasGeneration(maskFormat);
}
return {success, glyphsPlacedInAtlas};
} else {
// The atlas hasn't changed, so our texture coordinates are still valid.
if (end == SkCount(fGlyphs)) {
// The atlas hasn't changed and the texture coordinates are all still valid. Update
// all the plots used to the new use token.
atlasManager->setUseTokenBulk(fBulkUseToken,
uploadTarget->tokenTracker()->nextDrawToken(),
maskFormat);
}
return {true, end - begin};
}
}
// -- DirectMaskSubRun -----------------------------------------------------------------------------
class DirectMaskSubRun final : public GrSubRun, public GrBlobSubRun, public GrAtlasSubRun {
public:
@ -797,7 +656,7 @@ public:
GrTextBlob* blob,
const SkGlyphRect& deviceBounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs,
GrGlyphVector&& glyphs,
bool glyphsOutOfBounds,
bool supportBilerpAtlas);
@ -856,14 +715,14 @@ private:
// The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
// be single threaded.
mutable GlyphVector fGlyphs;
mutable GrGlyphVector fGlyphs;
};
DirectMaskSubRun::DirectMaskSubRun(GrMaskFormat format,
GrTextBlob* blob,
const SkGlyphRect& deviceBounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs,
GrGlyphVector&& glyphs,
bool glyphsOutOfBounds,
bool supportBilerpAtlas)
: fMaskFormat{format}
@ -880,7 +739,7 @@ GrSubRunOwner DirectMaskSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& accep
GrTextBlob* blob,
GrSubRunAllocator* alloc) {
DevicePosition* glyphLeftTop = alloc->makePODArray<DevicePosition>(accepted.size());
GlyphVector::Variant* glyphIDs = alloc->makePODArray<GlyphVector::Variant>(accepted.size());
GrGlyphVector::Variant* glyphIDs = alloc->makePODArray<GrGlyphVector::Variant>(accepted.size());
// Because this is the direct case, the maximum width or height is the size that fits in the
// atlas. This boundary is checked below to ensure that the call to SkGlyphRect below will
@ -916,7 +775,7 @@ GrSubRunOwner DirectMaskSubRun::Make(const SkZip<SkGlyphVariant, SkPoint>& accep
SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
return alloc->makeUnique<DirectMaskSubRun>(
format, blob, runBounds, leftTop,
GlyphVector{std::move(strike), {glyphIDs, goodPosCount}},
GrGlyphVector{std::move(strike), {glyphIDs, goodPosCount}},
glyphsExcluded,
blob->supportBilerpAtlas());
}
@ -1200,7 +1059,7 @@ public:
SkScalar strikeToSourceScale,
const SkRect& bounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs);
GrGlyphVector&& glyphs);
static GrSubRunOwner Make(GrTextReferenceFrame* referenceFrame,
const SkZip<SkGlyphVariant, SkPoint>& accepted,
@ -1257,7 +1116,7 @@ private:
// The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
// be single threaded.
mutable GlyphVector fGlyphs;
mutable GrGlyphVector fGlyphs;
};
TransformedMaskSubRun::TransformedMaskSubRun(GrTextReferenceFrame* referenceFrame,
@ -1265,7 +1124,7 @@ TransformedMaskSubRun::TransformedMaskSubRun(GrTextReferenceFrame* referenceFram
SkScalar strikeToSourceScale,
const SkRect& bounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs)
GrGlyphVector&& glyphs)
: fVertexFiller{format, 0, strikeToSourceScale}
, fReferenceFrame{referenceFrame}
, fVertexBounds{bounds}
@ -1298,7 +1157,7 @@ GrSubRunOwner TransformedMaskSubRun::Make(GrTextReferenceFrame* referenceFrame,
return alloc->makeUnique<TransformedMaskSubRun>(
referenceFrame, format, strikeToSourceScale, bounds, vertexData,
GlyphVector::Make(std::move(strike), accepted.get<0>(), alloc));
GrGlyphVector::Make(std::move(strike), accepted.get<0>(), alloc));
}
void TransformedMaskSubRun::draw(SkCanvas*,
@ -1406,7 +1265,7 @@ public:
SkScalar strikeToSource,
SkRect vertexBounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs,
GrGlyphVector&& glyphs,
bool useLCDText,
bool antiAliased,
const GrSDFTMatrixRange& matrixRange);
@ -1466,7 +1325,7 @@ private:
// The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
// be single threaded.
mutable GlyphVector fGlyphs;
mutable GrGlyphVector fGlyphs;
const bool fUseLCDText;
const bool fAntiAliased;
@ -1477,7 +1336,7 @@ SDFTSubRun::SDFTSubRun(GrTextReferenceFrame* referenceFrame,
SkScalar strikeToSource,
SkRect vertexBounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs,
GrGlyphVector&& glyphs,
bool useLCDText,
bool antiAliased,
const GrSDFTMatrixRange& matrixRange)
@ -1525,7 +1384,7 @@ GrSubRunOwner SDFTSubRun::Make(GrTextReferenceFrame* referenceFrame,
strikeToSourceScale,
bounds,
vertexData,
GlyphVector::Make(std::move(strike), accepted.get<0>(), alloc),
GrGlyphVector::Make(std::move(strike), accepted.get<0>(), alloc),
runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias,
has_some_antialiasing(runFont),
matrixRange);
@ -1845,7 +1704,7 @@ sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
// The neededForSubRun is optimized for DirectMaskSubRun which is by far the most common case.
size_t bytesNeededForSubRun = GrBagOfBytes::PlatformMinimumSizeWithOverhead(
totalGlyphCount * sizeof(DirectMaskSubRun::DevicePosition)
+ GlyphVector::GlyphVectorSize(totalGlyphCount)
+ GrGlyphVector::GlyphVectorSize(totalGlyphCount)
+ glyphRunList.runCount() * (sizeof(DirectMaskSubRun) + vertexDataToSubRunPadding),
alignof(GrTextBlob));
@ -2005,7 +1864,7 @@ public:
bool supportBilerpAtlas,
const SkRect& bounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs);
GrGlyphVector&& glyphs);
static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& accepted,
sk_sp<SkStrike>&& strike,
@ -2050,14 +1909,14 @@ private:
// The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
// be single threaded.
mutable GlyphVector fGlyphs;
mutable GrGlyphVector fGlyphs;
};
DirectMaskSubRunNoCache::DirectMaskSubRunNoCache(GrMaskFormat format,
bool supportBilerpAtlas,
const SkRect& deviceBounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs)
GrGlyphVector&& glyphs)
: fMaskFormat{format}
, fSupportBilerpAtlas{supportBilerpAtlas}
, fGlyphDeviceBounds{deviceBounds}
@ -2071,9 +1930,9 @@ GrAtlasSubRunOwner DirectMaskSubRunNoCache::Make(const SkZip<SkGlyphVariant, SkP
GrSubRunAllocator* alloc) {
DevicePosition* glyphLeftTop = alloc->makePODArray<DevicePosition>(accepted.size());
GlyphVector::Variant* glyphIDs = static_cast<GlyphVector::Variant*>(
alloc->alignedBytes(accepted.size() * sizeof(GlyphVector::Variant),
alignof(GlyphVector::Variant)));
GrGlyphVector::Variant* glyphIDs = static_cast<GrGlyphVector::Variant*>(
alloc->alignedBytes(accepted.size() * sizeof(GrGlyphVector::Variant),
alignof(GrGlyphVector::Variant)));
// Because this is the direct case, the maximum width or height is the size that fits in the
// atlas. This boundary is checked below to ensure that the call to SkGlyphRect below will
@ -2106,7 +1965,7 @@ GrAtlasSubRunOwner DirectMaskSubRunNoCache::Make(const SkZip<SkGlyphVariant, SkP
SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
return alloc->makeUnique<DirectMaskSubRunNoCache>(
format, supportBilerpAtlas, runBounds.rect(), leftTop,
GlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
GrGlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
}
size_t DirectMaskSubRunNoCache::vertexStride(const SkMatrix&) const {
@ -2257,7 +2116,7 @@ public:
SkScalar strikeToSourceScale,
const SkRect& bounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs);
GrGlyphVector&& glyphs);
static GrAtlasSubRunOwner Make(const SkZip<SkGlyphVariant, SkPoint>& accepted,
sk_sp<SkStrike>&& strike,
@ -2301,14 +2160,14 @@ private:
// The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
// be single threaded.
mutable GlyphVector fGlyphs;
mutable GrGlyphVector fGlyphs;
};
TransformedMaskSubRunNoCache::TransformedMaskSubRunNoCache(GrMaskFormat format,
SkScalar strikeToSourceScale,
const SkRect& bounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs)
GrGlyphVector&& glyphs)
: fVertexFiller{format, 0, strikeToSourceScale}
, fVertexBounds{bounds}
, fVertexData{vertexData}
@ -2339,7 +2198,7 @@ GrAtlasSubRunOwner TransformedMaskSubRunNoCache::Make(
return alloc->makeUnique<TransformedMaskSubRunNoCache>(
format, strikeToSourceScale, bounds, vertexData,
GlyphVector::Make(std::move(strike), accepted.get<0>(), alloc));
GrGlyphVector::Make(std::move(strike), accepted.get<0>(), alloc));
}
std::tuple<const GrClip*, GrOp::Owner>
@ -2431,7 +2290,7 @@ public:
SkScalar strikeToSourceScale,
SkRect vertexBounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs,
GrGlyphVector&& glyphs,
bool useLCDText,
bool antiAliased);
@ -2480,7 +2339,7 @@ private:
// The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
// be single threaded.
mutable GlyphVector fGlyphs;
mutable GrGlyphVector fGlyphs;
const bool fUseLCDText;
const bool fAntiAliased;
@ -2490,7 +2349,7 @@ SDFTSubRunNoCache::SDFTSubRunNoCache(GrMaskFormat format,
SkScalar strikeToSourceScale,
SkRect vertexBounds,
SkSpan<const VertexData> vertexData,
GlyphVector&& glyphs,
GrGlyphVector&& glyphs,
bool useLCDText,
bool antiAliased)
: fMaskFormat{format}
@ -2531,7 +2390,7 @@ GrAtlasSubRunOwner SDFTSubRunNoCache::Make(
strikeToSourceScale,
bounds,
vertexData,
GlyphVector::Make(std::move(strike), accepted.get<0>(), alloc),
GrGlyphVector::Make(std::move(strike), accepted.get<0>(), alloc),
runFont.getEdging() == SkFont::Edging::kSubpixelAntiAlias,
has_some_antialiasing(runFont));
}
@ -2800,7 +2659,7 @@ public:
GrMaskFormat format,
SkGlyphRect deviceBounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs);
GrGlyphVector&& glyphs);
static GrSubRunOwner Make(Slug* slug,
const SkZip<SkGlyphVariant, SkPoint>& accepted,
@ -2858,14 +2717,14 @@ private:
// The regenerateAtlas method mutates fGlyphs. It should be called from onPrepare which must
// be single threaded.
mutable GlyphVector fGlyphs;
mutable GrGlyphVector fGlyphs;
};
DirectMaskSubRunSlug::DirectMaskSubRunSlug(Slug* slug,
GrMaskFormat format,
SkGlyphRect deviceBounds,
SkSpan<const DevicePosition> devicePositions,
GlyphVector&& glyphs)
GrGlyphVector&& glyphs)
: fSlug{slug}
, fMaskFormat{format}
, fGlyphDeviceBounds{deviceBounds}
@ -2879,9 +2738,9 @@ GrSubRunOwner DirectMaskSubRunSlug::Make(Slug* slug,
GrSubRunAllocator* alloc) {
DevicePosition* glyphLeftTop = alloc->makePODArray<DevicePosition>(accepted.size());
GlyphVector::Variant* glyphIDs = static_cast<GlyphVector::Variant*>(
alloc->alignedBytes(accepted.size() * sizeof(GlyphVector::Variant),
alignof(GlyphVector::Variant)));
GrGlyphVector::Variant* glyphIDs = static_cast<GrGlyphVector::Variant*>(
alloc->alignedBytes(accepted.size() * sizeof(GrGlyphVector::Variant),
alignof(GrGlyphVector::Variant)));
// Because this is the direct case, the maximum width or height is the size that fits in the
// atlas. This boundary is checked below to ensure that the call to SkGlyphRect below will
@ -2914,7 +2773,7 @@ GrSubRunOwner DirectMaskSubRunSlug::Make(Slug* slug,
SkSpan<const DevicePosition> leftTop{glyphLeftTop, goodPosCount};
return alloc->makeUnique<DirectMaskSubRunSlug>(
slug, format, runBounds, leftTop,
GlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
GrGlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
}
size_t DirectMaskSubRunSlug::vertexStride(const SkMatrix& positionMatrix) const {
@ -3190,7 +3049,7 @@ sk_sp<Slug> Slug::Make(const SkMatrixProvider& viewMatrix,
// common case.
size_t bytesNeededForSubRun = GrBagOfBytes::PlatformMinimumSizeWithOverhead(
totalGlyphCount * sizeof(DirectMaskSubRunSlug::DevicePosition)
+ GlyphVector::GlyphVectorSize(totalGlyphCount)
+ GrGlyphVector::GlyphVectorSize(totalGlyphCount)
+ glyphRunList.runCount() * (sizeof(DirectMaskSubRunSlug) + vertexDataToSubRunPadding),
alignof(Slug));