From 0edb2149e44cd2468793af2418fe023ead8dd7b4 Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Tue, 16 Oct 2018 17:04:11 -0400 Subject: [PATCH] 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 Reviewed-by: Brian Salomon --- src/core/SkGlyphRun.cpp | 9 +++++++++ src/core/SkGlyphRun.h | 1 + src/core/SkGlyphRunPainter.cpp | 3 ++- src/gpu/text/GrTextBlob.cpp | 36 ++++++++++++++++++---------------- src/gpu/text/GrTextBlob.h | 2 +- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/core/SkGlyphRun.cpp b/src/core/SkGlyphRun.cpp index 31897436d2..9ae21c01a5 100644 --- a/src/core/SkGlyphRun.cpp +++ b/src/core/SkGlyphRun.cpp @@ -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); diff --git a/src/core/SkGlyphRun.h b/src/core/SkGlyphRun.h index 3f7c26eb0d..2d0d345523 100644 --- a/src/core/SkGlyphRun.h +++ b/src/core/SkGlyphRun.h @@ -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; } diff --git a/src/core/SkGlyphRunPainter.cpp b/src/core/SkGlyphRunPainter.cpp index 1d4d7daf73..cfaafe35aa 100644 --- a/src/core/SkGlyphRunPainter.cpp +++ b/src/core/SkGlyphRunPainter.cpp @@ -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 diff --git a/src/gpu/text/GrTextBlob.cpp b/src/gpu/text/GrTextBlob.cpp index 659a545455..6249c3a48f 100644 --- a/src/gpu/text/GrTextBlob.cpp +++ b/src/gpu/text/GrTextBlob.cpp @@ -144,9 +144,9 @@ 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, - const SkMaskFilterBase::BlurRec& blurRec, - const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { +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 // to regenerate the blob on any color change // We use the grPaint to get any color filter effects @@ -196,20 +196,22 @@ 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 - SkScalar transX = viewMatrix.getTranslateX() + - viewMatrix.getScaleX() * (x - fInitialX) + - viewMatrix.getSkewX() * (y - fInitialY) - - fInitialViewMatrix.getTranslateX(); - SkScalar transY = viewMatrix.getTranslateY() + - viewMatrix.getSkewY() * (x - fInitialX) + - viewMatrix.getScaleY() * (y - fInitialY) - - fInitialViewMatrix.getTranslateY(); - if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) { - return true; + 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) - + fInitialViewMatrix.getTranslateX(); + SkScalar transY = viewMatrix.getTranslateY() + + viewMatrix.getSkewY() * (x - fInitialX) + + viewMatrix.getScaleY() * (y - fInitialY) - + fInitialViewMatrix.getTranslateY(); + if (!SkScalarIsInt(transX) || !SkScalarIsInt(transY)) { + return true; + } } } else if (this->hasDistanceField()) { // A scale outside of [blob.fMaxMinScale, blob.fMinMaxScale] would result in a different diff --git a/src/gpu/text/GrTextBlob.h b/src/gpu/text/GrTextBlob.h index f8a45659e1..234039fb6a 100644 --- a/src/gpu/text/GrTextBlob.h +++ b/src/gpu/text/GrTextBlob.h @@ -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,