Put SubRuns in an alloc on GrTextBlob
This improves performance when there are multiple runs. Bug: chromium:1029972 Change-Id: If32ddb2baf974ee1af7833710bd10a60e39c0169 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/258736 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
15ee970d79
commit
cb71889318
@ -20,10 +20,6 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
template <size_t N> static size_t sk_align(size_t s) {
|
||||
return ((s + (N-1)) / N) * N;
|
||||
}
|
||||
|
||||
static void calculate_translation(bool applyVM,
|
||||
const SkMatrix& newViewMatrix, SkScalar newX, SkScalar newY,
|
||||
const SkMatrix& currentViewMatrix, SkScalar currentX,
|
||||
@ -82,6 +78,7 @@ GrTextBlob::SubRun::SubRun(SubRunType type, GrTextBlob* textBlob, const SkStrike
|
||||
, fY{textBlob->fInitialOrigin.y()}
|
||||
, fCurrentViewMatrix{textBlob->fInitialViewMatrix} {
|
||||
SkASSERT(type != kTransformedPath);
|
||||
textBlob->insertSubRun(this);
|
||||
}
|
||||
|
||||
GrTextBlob::SubRun::SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec)
|
||||
@ -95,7 +92,9 @@ GrTextBlob::SubRun::SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec)
|
||||
, fStrikeSpec{strikeSpec}
|
||||
, fStrike{nullptr}
|
||||
, fColor{textBlob->fColor}
|
||||
, fPaths{} { }
|
||||
, fPaths{} {
|
||||
textBlob->insertSubRun(this);
|
||||
}
|
||||
|
||||
void GrTextBlob::SubRun::appendGlyphs(const SkZip<SkGlyphVariant, SkPoint>& drawables) {
|
||||
GrTextStrike* grStrike = fStrike.get();
|
||||
@ -223,32 +222,34 @@ sk_sp<GrTextBlob> GrTextBlob::Make(const SkGlyphRunList& glyphRunList,
|
||||
bool forceWForDistanceFields) {
|
||||
|
||||
static_assert(sizeof(ARGB2DVertex) <= sizeof(Mask2DVertex));
|
||||
size_t vertexSize = sizeof(Mask2DVertex);
|
||||
static_assert(alignof(ARGB2DVertex) <= alignof(Mask2DVertex));
|
||||
size_t quadSize = sizeof(Mask2DVertex) * kVerticesPerGlyph;
|
||||
if (viewMatrix.hasPerspective() || forceWForDistanceFields) {
|
||||
static_assert(sizeof(ARGB3DVertex) <= sizeof(SDFT3DVertex));
|
||||
vertexSize = sizeof(SDFT3DVertex);
|
||||
static_assert(alignof(ARGB3DVertex) <= alignof(SDFT3DVertex));
|
||||
quadSize = sizeof(SDFT3DVertex) * kVerticesPerGlyph;
|
||||
}
|
||||
|
||||
size_t quadSize = kVerticesPerGlyph * vertexSize;
|
||||
// We can use the alignment of SDFT3DVertex as a proxy for all Vertex alignments.
|
||||
static_assert(alignof(SDFT3DVertex) >= alignof(Mask2DVertex));
|
||||
|
||||
size_t glyphCount = glyphRunList.totalGlyphCount();
|
||||
// We allocate size for the GrTextBlob itself, plus size for the vertices array,
|
||||
// and size for the glyphIds array.
|
||||
size_t verticesCount = glyphCount * quadSize;
|
||||
size_t subRunsOffset = sizeof(GrTextBlob);
|
||||
size_t subRunsSize = glyphRunList.runCount() * sizeof(SubRun);
|
||||
static_assert(alignof(SubRun) >= alignof(GrGlyph*));
|
||||
size_t glyphsOffset = subRunsOffset + subRunsSize;
|
||||
static_assert(alignof(GrGlyph*) >= alignof(SDFT3DVertex));
|
||||
size_t vertexOffset = glyphsOffset + sizeof(GrGlyph*) * glyphRunList.totalGlyphCount();
|
||||
size_t allocationSize = vertexOffset + quadSize * glyphRunList.totalGlyphCount();
|
||||
|
||||
size_t blobStart = 0;
|
||||
size_t vertex = sk_align<alignof(char)> (blobStart + sizeof(GrTextBlob) * 1);
|
||||
size_t glyphs = sk_align<alignof(GrGlyph*)> (vertex + sizeof(char) * verticesCount);
|
||||
size_t size = (glyphs + sizeof(GrGlyph*) * glyphCount);
|
||||
|
||||
void* allocation = ::operator new (size);
|
||||
void* allocation = ::operator new (allocationSize);
|
||||
|
||||
sk_sp<GrTextBlob> blob{new (allocation) GrTextBlob{
|
||||
size, strikeCache, viewMatrix, glyphRunList.origin(), color, forceWForDistanceFields}};
|
||||
subRunsSize, strikeCache, viewMatrix, glyphRunList.origin(),
|
||||
color, forceWForDistanceFields}};
|
||||
|
||||
// setup offsets for vertices / glyphs
|
||||
blob->fVertices = SkTAddOffset<char>(blob.get(), vertex);
|
||||
blob->fGlyphs = SkTAddOffset<GrGlyph*>(blob.get(), glyphs);
|
||||
blob->fVertices = SkTAddOffset<char>(blob.get(), vertexOffset);
|
||||
blob->fGlyphs = SkTAddOffset<GrGlyph*>(blob.get(), glyphsOffset);
|
||||
|
||||
return blob;
|
||||
}
|
||||
@ -286,7 +287,9 @@ void GrTextBlob::setupKey(const GrTextBlob::Key& key, const SkMaskFilterBase::Bl
|
||||
const GrTextBlob::Key& GrTextBlob::GetKey(const GrTextBlob& blob) { return blob.fKey; }
|
||||
uint32_t GrTextBlob::Hash(const GrTextBlob::Key& key) { return SkOpts::hash(&key, sizeof(Key)); }
|
||||
|
||||
bool GrTextBlob::hasDistanceField() const { return SkToBool(fTextType & kHasDistanceField_TextType); }
|
||||
bool GrTextBlob::hasDistanceField() const {
|
||||
return SkToBool(fTextType & kHasDistanceField_TextType);
|
||||
}
|
||||
bool GrTextBlob::hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); }
|
||||
bool GrTextBlob::hasPerspective() const { return fInitialViewMatrix.hasPerspective(); }
|
||||
|
||||
@ -401,10 +404,10 @@ void GrTextBlob::flush(GrTextTarget* target, const SkSurfaceProps& props,
|
||||
const SkPaint& paint, const SkPMColor4f& filteredColor, const GrClip& clip,
|
||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
|
||||
|
||||
for (auto& subRun : fSubRuns) {
|
||||
if (subRun.drawAsPaths()) {
|
||||
for (SubRun* subRun = fFirstSubRun; subRun != nullptr; subRun = subRun->fNextSubRun) {
|
||||
if (subRun->drawAsPaths()) {
|
||||
SkPaint runPaint{paint};
|
||||
runPaint.setAntiAlias(subRun.isAntiAliased());
|
||||
runPaint.setAntiAlias(subRun->isAntiAliased());
|
||||
// If there are shaders, blurs or styles, the path must be scaled into source
|
||||
// space independently of the CTM. This allows the CTM to be correct for the
|
||||
// different effects.
|
||||
@ -417,9 +420,10 @@ void GrTextBlob::flush(GrTextTarget* target, const SkSurfaceProps& props,
|
||||
// The origin for the blob may have changed, so figure out the delta.
|
||||
SkVector originShift = SkPoint{x, y} - fInitialOrigin;
|
||||
|
||||
for (const auto& pathGlyph : subRun.fPaths) {
|
||||
for (const auto& pathGlyph : subRun->fPaths) {
|
||||
SkMatrix ctm{viewMatrix};
|
||||
SkMatrix pathMatrix = SkMatrix::MakeScale(subRun.fStrikeSpec.strikeToSourceRatio());
|
||||
SkMatrix pathMatrix = SkMatrix::MakeScale(
|
||||
subRun->fStrikeSpec.strikeToSourceRatio());
|
||||
// Shift the original glyph location in source space to the position of the new
|
||||
// blob.
|
||||
pathMatrix.postTranslate(originShift.x() + pathGlyph.fOrigin.x(),
|
||||
@ -447,7 +451,7 @@ void GrTextBlob::flush(GrTextTarget* target, const SkSurfaceProps& props,
|
||||
target->drawShape(clip, runPaint, ctm, shape);
|
||||
}
|
||||
} else {
|
||||
int glyphCount = subRun.glyphCount();
|
||||
int glyphCount = subRun->glyphCount();
|
||||
if (0 == glyphCount) {
|
||||
continue;
|
||||
}
|
||||
@ -460,13 +464,13 @@ void GrTextBlob::flush(GrTextTarget* target, const SkSurfaceProps& props,
|
||||
GrAA aa;
|
||||
// We can clip geometrically if we're not using SDFs or transformed glyphs,
|
||||
// and we have an axis-aligned rectangular non-AA clip
|
||||
if (!subRun.drawAsDistanceFields() && !subRun.needsTransform() &&
|
||||
if (!subRun->drawAsDistanceFields() && !subRun->needsTransform() &&
|
||||
clip.isRRect(rtBounds, &clipRRect, &aa) &&
|
||||
clipRRect.isRect() && GrAA::kNo == aa) {
|
||||
skipClip = true;
|
||||
// We only need to do clipping work if the subrun isn't contained by the clip
|
||||
SkRect subRunBounds;
|
||||
this->computeSubRunBounds(&subRunBounds, subRun, viewMatrix, x, y, false);
|
||||
this->computeSubRunBounds(&subRunBounds, *subRun, viewMatrix, x, y, false);
|
||||
if (!clipRRect.getBounds().contains(subRunBounds)) {
|
||||
// If the subrun is completely outside, don't add an op for it
|
||||
if (!clipRRect.getBounds().intersects(subRunBounds)) {
|
||||
@ -479,7 +483,7 @@ void GrTextBlob::flush(GrTextTarget* target, const SkSurfaceProps& props,
|
||||
}
|
||||
|
||||
if (submitOp) {
|
||||
auto op = this->makeOp(subRun, glyphCount, viewMatrix, x, y,
|
||||
auto op = this->makeOp(*subRun, glyphCount, viewMatrix, x, y,
|
||||
clipRect, paint, filteredColor, props, distanceAdjustTable,
|
||||
target);
|
||||
if (op) {
|
||||
@ -538,9 +542,9 @@ std::unique_ptr<GrDrawOp> GrTextBlob::test_makeOp(
|
||||
SkScalar x, SkScalar y, const SkPaint& paint, const SkPMColor4f& filteredColor,
|
||||
const SkSurfaceProps& props, const GrDistanceFieldAdjustTable* distanceAdjustTable,
|
||||
GrTextTarget* target) {
|
||||
GrTextBlob::SubRun& info = fSubRuns[0];
|
||||
SubRun* info = fFirstSubRun;
|
||||
SkIRect emptyRect = SkIRect::MakeEmpty();
|
||||
return this->makeOp(info, glyphCount, viewMatrix, x, y, emptyRect,
|
||||
return this->makeOp(*info, glyphCount, viewMatrix, x, y, emptyRect,
|
||||
paint, filteredColor, props, distanceAdjustTable, target);
|
||||
}
|
||||
|
||||
@ -573,12 +577,12 @@ GrTextBlob::SubRun* GrTextBlob::makeSubRun(SubRunType type,
|
||||
|
||||
sk_sp<GrTextStrike> grStrike = strikeSpec.findOrCreateGrStrike(fStrikeCache);
|
||||
|
||||
SubRun& subRun = fSubRuns.emplace_back(
|
||||
SubRun* subRun = fAlloc.make<SubRun>(
|
||||
type, this, strikeSpec, format, bufferSpec, std::move(grStrike));
|
||||
|
||||
subRun.appendGlyphs(drawables);
|
||||
subRun->appendGlyphs(drawables);
|
||||
|
||||
return &subRun;
|
||||
return subRun;
|
||||
}
|
||||
|
||||
void GrTextBlob::addSingleMaskFormat(
|
||||
@ -627,21 +631,32 @@ void GrTextBlob::addSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
|
||||
subRun->setAntiAliased(runFont.hasSomeAntiAliasing());
|
||||
}
|
||||
|
||||
GrTextBlob::GrTextBlob(size_t size,
|
||||
GrTextBlob::GrTextBlob(size_t allocSize,
|
||||
GrStrikeCache* strikeCache,
|
||||
const SkMatrix& viewMatrix,
|
||||
SkPoint origin,
|
||||
GrColor color,
|
||||
bool forceWForDistanceFields)
|
||||
: fSize{size}
|
||||
: fSize{allocSize}
|
||||
, fStrikeCache{strikeCache}
|
||||
, fInitialViewMatrix{viewMatrix}
|
||||
, fInitialViewMatrixInverse{make_inverse(viewMatrix)}
|
||||
, fInitialOrigin{origin}
|
||||
, fForceWForDistanceFields{forceWForDistanceFields}
|
||||
, fColor{color} { }
|
||||
, fColor{color}
|
||||
, fAlloc{SkTAddOffset<char>(this, sizeof(GrTextBlob)), allocSize, allocSize/2} { }
|
||||
|
||||
inline std::unique_ptr<GrAtlasTextOp> GrTextBlob::makeOp(
|
||||
void GrTextBlob::insertSubRun(SubRun* subRun) {
|
||||
if (fFirstSubRun == nullptr) {
|
||||
fFirstSubRun = subRun;
|
||||
fLastSubRun = subRun;
|
||||
} else {
|
||||
fLastSubRun->fNextSubRun = subRun;
|
||||
fLastSubRun = subRun;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GrAtlasTextOp> GrTextBlob::makeOp(
|
||||
SubRun& info, int glyphCount,
|
||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
|
||||
const SkPaint& paint, const SkPMColor4f& filteredColor, const SkSurfaceProps& props,
|
||||
@ -682,10 +697,10 @@ void GrTextBlob::processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawab
|
||||
const SkFont& runFont,
|
||||
const SkStrikeSpec& strikeSpec) {
|
||||
this->setHasBitmap();
|
||||
SubRun& subRun = fSubRuns.emplace_back(this, strikeSpec);
|
||||
subRun.setAntiAliased(runFont.hasSomeAntiAliasing());
|
||||
SubRun* subRun = fAlloc.make<SubRun>(this, strikeSpec);
|
||||
subRun->setAntiAliased(runFont.hasSomeAntiAliasing());
|
||||
for (auto [variant, pos] : drawables) {
|
||||
subRun.fPaths.emplace_back(*variant.path(), pos);
|
||||
subRun->fPaths.emplace_back(*variant.path(), pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,6 +138,7 @@ public:
|
||||
|
||||
const SkStrikeSpec& strikeSpec() const;
|
||||
|
||||
SubRun* fNextSubRun{nullptr};
|
||||
const SubRunType fType;
|
||||
GrTextBlob* const fBlob;
|
||||
const GrMaskFormat fMaskFormat;
|
||||
@ -292,13 +293,15 @@ private:
|
||||
SkPaint::Join fJoin;
|
||||
};
|
||||
|
||||
GrTextBlob(size_t size,
|
||||
GrTextBlob(size_t allocSize,
|
||||
GrStrikeCache* strikeCache,
|
||||
const SkMatrix& viewMatrix,
|
||||
SkPoint origin,
|
||||
GrColor color,
|
||||
bool forceWForDistanceFields);
|
||||
|
||||
void insertSubRun(SubRun* subRun);
|
||||
|
||||
std::unique_ptr<GrAtlasTextOp> makeOp(
|
||||
SubRun& info, int glyphCount,
|
||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
|
||||
@ -352,9 +355,6 @@ private:
|
||||
// Number of glyphs stored in fGlyphs while accumulating SubRuns.
|
||||
uint32_t fGlyphsCursor{0};
|
||||
|
||||
// Assume one run per text blob.
|
||||
SkSTArray<1, SubRun> fSubRuns;
|
||||
|
||||
SkMaskFilterBase::BlurRec fBlurRec;
|
||||
StrokeInfo fStrokeInfo;
|
||||
Key fKey;
|
||||
@ -367,6 +367,10 @@ private:
|
||||
SkScalar fMinMaxScale{SK_ScalarMax};
|
||||
|
||||
uint8_t fTextType{0};
|
||||
|
||||
SubRun* fFirstSubRun{nullptr};
|
||||
SubRun* fLastSubRun{nullptr};
|
||||
SkArenaAlloc fAlloc;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user