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>
diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp
index e8f08bb..7ae8d52 100644
--- a/src/gpu/text/GrTextBlob.cpp
+++ b/src/gpu/text/GrTextBlob.cpp
@@ -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 @@
, 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 @@
, 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 @@
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 @@
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 @@
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 @@
// 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 @@
target->drawShape(clip, runPaint, ctm, shape);
}
} else {
- int glyphCount = subRun.glyphCount();
+ int glyphCount = subRun->glyphCount();
if (0 == glyphCount) {
continue;
}
@@ -460,13 +464,13 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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);
}
}
diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h
index 3ecfd12..cd5cc25 100644
--- a/src/gpu/text/GrTextBlob.h
+++ b/src/gpu/text/GrTextBlob.h
@@ -138,6 +138,7 @@
const SkStrikeSpec& strikeSpec() const;
+ SubRun* fNextSubRun{nullptr};
const SubRunType fType;
GrTextBlob* const fBlob;
const GrMaskFormat fMaskFormat;
@@ -292,13 +293,15 @@
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 @@
// 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 @@
SkScalar fMinMaxScale{SK_ScalarMax};
uint8_t fTextType{0};
+
+ SubRun* fFirstSubRun{nullptr};
+ SubRun* fLastSubRun{nullptr};
+ SkArenaAlloc fAlloc;
};
/**