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:
Herb Derby 2019-12-07 00:07:42 -05:00 committed by Skia Commit-Bot
parent 15ee970d79
commit cb71889318
2 changed files with 66 additions and 47 deletions

View File

@ -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);
}
}

View File

@ -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;
};
/**