Optimize GPU text regen for full pixel position text

If the GrTextBlob does not contain any subpixel position text,
then any translation is ok. This is because all positions and
SkGlyphCache entries will be aligned to pixel boundaries.

Change-Id: Ie2bfd72710295b98c65052a857b6bd33a4858b65
Reviewed-on: https://skia-review.googlesource.com/c/162860
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Herb Derby 2018-10-16 17:04:11 -04:00 committed by Skia Commit-Bot
parent b093c82b0f
commit 0edb2149e4
5 changed files with 32 additions and 19 deletions

View File

@ -104,6 +104,15 @@ bool SkGlyphRunList::anyRunsLCD() const {
return false;
}
bool SkGlyphRunList::anyRunsSubpixelPositioned() const {
for (const auto& r : fGlyphRuns) {
if (r.paint().isSubpixelText()) {
return true;
}
}
return false;
}
void SkGlyphRunList::temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const {
SkASSERT(fOriginalTextBlob != nullptr);
fOriginalTextBlob->notifyAddedToCache(cacheID);

View File

@ -151,6 +151,7 @@ public:
uint64_t uniqueID() const;
bool anyRunsLCD() const;
bool anyRunsSubpixelPositioned() const;
void temporaryShuntBlobNotifyAddedToCache(uint32_t cacheID) const;
bool canCache() const { return fOriginalTextBlob != nullptr; }

View File

@ -388,7 +388,8 @@ void GrTextContext::drawGlyphRunList(
}
if (cacheBlob) {
if (cacheBlob->mustRegenerate(listPaint, blurRec, viewMatrix, origin.x(), origin.y())) {
if (cacheBlob->mustRegenerate(listPaint, glyphRunList.anyRunsSubpixelPositioned(),
blurRec, viewMatrix, origin.x(),origin.y())) {
// We have to remake the blob because changes may invalidate our masks.
// TODO we could probably get away reuse most of the time if the pointer is unique,
// but we'd have to clear the subrun information

View File

@ -144,7 +144,7 @@ void GrTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, S
run.fPathGlyphs.push_back(GrTextBlob::Run::PathGlyph(path, x, y, scale, preTransformed));
}
bool GrTextBlob::mustRegenerate(const SkPaint& paint,
bool GrTextBlob::mustRegenerate(const SkPaint& paint, bool anyRunHasSubpixelPosition,
const SkMaskFilterBase::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
// If we have LCD text then our canonical color will be set to transparent, in this case we have
@ -196,10 +196,11 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint,
return true;
}
// We can update the positions in the cachedtextblobs without regenerating the whole blob,
// but only for integer translations.
// This cool bit of math will determine the necessary translation to apply to the already
// generated vertex coordinates to move them to the correct position
if (!anyRunHasSubpixelPosition) {
// We can update the positions in the cachedtextblobs without regenerating the whole
// blob, but only for integer translations.
// This cool bit of math will determine the necessary translation to apply to the
// already generated vertex coordinates to move them to the correct position.
SkScalar transX = viewMatrix.getTranslateX() +
viewMatrix.getScaleX() * (x - fInitialX) +
viewMatrix.getSkewX() * (y - fInitialY) -
@ -211,6 +212,7 @@ bool GrTextBlob::mustRegenerate(const SkPaint& paint,
if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) {
return true;
}
}
} else if (this->hasDistanceField()) {
// A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different
// distance field being generated, so we have to regenerate in those cases

View File

@ -196,7 +196,7 @@ public:
}
}
bool mustRegenerate(const SkPaint&, const SkMaskFilterBase::BlurRec& blurRec,
bool mustRegenerate(const SkPaint&, bool, const SkMaskFilterBase::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
void flush(GrTextTarget*, const SkSurfaceProps& props,