diff options
author | Jim Van Verth <jvanverth@google.com> | 2018-02-06 21:30:20 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-02-06 21:30:26 +0000 |
commit | 89737decb4965ec250f02af432884366945d2e53 (patch) | |
tree | 0fc0febed63db177d8643239d4728f9446306916 /src/gpu/text/GrAtlasTextBlob.cpp | |
parent | 74416048652002955302cf7bb62c9e01f281efee (diff) |
Revert "Cleanup of large text rendering."
This reverts commit 2fb7c8aef57e4b94d5215e618d8c3b4cccd35edf.
Reason for revert: Causing flakes and incorrect GMs on ChromeOS.
Original change's description:
> Cleanup of large text rendering.
>
> * Switch all path glyphs to be rendered as part of the fBigGlyphs
> (now fPathGlyphs) system
> * Use one flush command for both cached and throwaway blobs
> * Store and render path glyphs per run rather than one list for the
> entire blob (fixes a layering bug)
> * Fix bug with scaled fallback glyphs, where fallback glyphs were
> trying to use more than one descriptor
>
> Bug: skia:7562
> Change-Id: Ic3d01887e2203a844102a04afe8674a16149b4bb
> Reviewed-on: https://skia-review.googlesource.com/102400
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Jim Van Verth <jvanverth@google.com>
TBR=jvanverth@google.com,bsalomon@google.com,robertphillips@google.com
Change-Id: I103a7419df96db9859e0f6f4d0a8e5aea4ba8ddc
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7562
Reviewed-on: https://skia-review.googlesource.com/104640
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Diffstat (limited to 'src/gpu/text/GrAtlasTextBlob.cpp')
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob.cpp | 253 |
1 files changed, 161 insertions, 92 deletions
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp index 12ad89a62a..887addd25c 100644 --- a/src/gpu/text/GrAtlasTextBlob.cpp +++ b/src/gpu/text/GrAtlasTextBlob.cpp @@ -73,22 +73,14 @@ void GrAtlasTextBlob::appendGlyph(int runIndex, GrAtlasTextStrike* strike, GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph, - SkScalar x, SkScalar y, SkScalar scale, bool preTransformed) { + SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP) { if (positions.isEmpty()) { return; } // If the glyph is too large we fall back to paths if (glyph->fTooLargeForAtlas) { - if (nullptr == glyph->fPath) { - const SkPath* glyphPath = cache->findPath(skGlyph); - if (!glyphPath) { - return; - } - - glyph->fPath = new SkPath(*glyphPath); - } - this->appendPathGlyph(runIndex, *glyph->fPath, x, y, scale, preTransformed); + this->appendBigGlyph(glyph, cache, skGlyph, x, y, scale, treatAsBMP); return; } @@ -148,10 +140,17 @@ void GrAtlasTextBlob::appendGlyph(int runIndex, subRun->glyphAppended(); } -void GrAtlasTextBlob::appendPathGlyph(int runIndex, const SkPath& path, SkScalar x, SkScalar y, - SkScalar scale, bool preTransformed) { - Run& run = fRuns[runIndex]; - run.fPathGlyphs.push_back(GrAtlasTextBlob::Run::PathGlyph(path, x, y, scale, preTransformed)); +void GrAtlasTextBlob::appendBigGlyph(GrGlyph* glyph, SkGlyphCache* cache, const SkGlyph& skGlyph, + SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP) { + if (nullptr == glyph->fPath) { + const SkPath* glyphPath = cache->findPath(skGlyph); + if (!glyphPath) { + return; + } + + glyph->fPath = new SkPath(*glyphPath); + } + fBigGlyphs.push_back(GrAtlasTextBlob::BigGlyph(*glyph->fPath, x, y, scale, treatAsBMP)); } bool GrAtlasTextBlob::mustRegenerate(const GrTextUtils::Paint& paint, @@ -274,6 +273,62 @@ inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp( return op; } +inline void GrAtlasTextBlob::flushRun(GrTextUtils::Target* target, const GrClip& clip, int run, + const SkMatrix& viewMatrix, SkScalar x, SkScalar y, + const GrTextUtils::Paint& paint, const SkSurfaceProps& props, + const GrDistanceFieldAdjustTable* distanceAdjustTable, + GrAtlasGlyphCache* cache) { + // GrAtlasTextBlob::makeOp only takes uint16_t values for run and subRun indices. + // Encountering something larger than this is highly unlikely, so we'll just not draw it. + if (run >= (1 << 16)) { + return; + } + int lastRun = SkTMin(fRuns[run].fSubRunInfo.count(), 1 << 16) - 1; + for (int subRun = 0; subRun <= lastRun; subRun++) { + const Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun]; + int glyphCount = info.glyphCount(); + if (0 == glyphCount) { + continue; + } + + bool skipClip = false; + bool submitOp = true; + SkIRect clipRect = SkIRect::MakeEmpty(); + SkRect rtBounds = SkRect::MakeWH(target->width(), target->height()); + SkRRect clipRRect; + GrAA aa; + // We can clip geometrically if we're not using SDFs, + // and we have an axis-aligned rectangular non-AA clip + if (!info.drawAsDistanceFields() && 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, run, subRun, viewMatrix, x, y); + if (!clipRRect.getBounds().contains(subRunBounds)) { + // If the subrun is completely outside, don't add an op for it + if (!clipRRect.getBounds().intersects(subRunBounds)) { + submitOp = false; + } else { + clipRRect.getBounds().round(&clipRect); + } + } + } + + if (submitOp) { + auto op = this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, clipRect, + std::move(paint), props, distanceAdjustTable, cache, target); + if (op) { + if (skipClip) { + target->addDrawOp(GrNoClip(), std::move(op)); + } else { + target->addDrawOp(clip, std::move(op)); + } + } + } + } +} + static void calculate_translation(bool applyVM, const SkMatrix& newViewMatrix, SkScalar newX, SkScalar newY, const SkMatrix& currentViewMatrix, SkScalar currentX, @@ -294,81 +349,94 @@ static void calculate_translation(bool applyVM, } } -void GrAtlasTextBlob::flush(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Target* target, - const SkSurfaceProps& props, - const GrDistanceFieldAdjustTable* distanceAdjustTable, - const GrTextUtils::Paint& paint, const GrClip& clip, - const SkMatrix& viewMatrix, const SkIRect& clipBounds, - SkScalar x, SkScalar y) { +void GrAtlasTextBlob::flushBigGlyphs(GrTextUtils::Target* target, + const GrClip& clip, const SkPaint& paint, + const SkMatrix& viewMatrix, SkScalar x, SkScalar y, + const SkIRect& clipBounds) { + SkScalar transX, transY; + for (int i = 0; i < fBigGlyphs.count(); i++) { + GrAtlasTextBlob::BigGlyph& bigGlyph = fBigGlyphs[i]; + calculate_translation(bigGlyph.fTreatAsBMP, viewMatrix, x, y, + fInitialViewMatrix, fInitialX, fInitialY, &transX, &transY); + SkMatrix ctm; + ctm.setScale(bigGlyph.fScale, bigGlyph.fScale); + ctm.postTranslate(bigGlyph.fX + transX, bigGlyph.fY + transY); + if (!bigGlyph.fTreatAsBMP) { + ctm.postConcat(viewMatrix); + } + target->drawPath(clip, bigGlyph.fPath, paint, ctm, nullptr, clipBounds); + } +} - // GrAtlasTextBlob::makeOp only takes uint16_t values for run and subRun indices. - // Encountering something larger than this is highly unlikely, so we'll just not draw it. - int lastRun = SkTMin(fRunCount, (1 << 16)) - 1; - for (int runIndex = 0; runIndex <= lastRun; runIndex++) { - Run& run = fRuns[runIndex]; - - // first flush each subrun - int lastSubRun = SkTMin(run.fSubRunInfo.count(), 1 << 16) - 1; - for (int subRun = 0; subRun <= lastSubRun; subRun++) { - const Run::SubRunInfo& info = run.fSubRunInfo[subRun]; - int glyphCount = info.glyphCount(); - if (0 == glyphCount) { - continue; - } +void GrAtlasTextBlob::flushBigRun(GrTextUtils::Target* target, + const SkSurfaceProps& props, const SkTextBlobRunIterator& it, + const GrClip& clip, const GrTextUtils::Paint& paint, + SkDrawFilter* drawFilter, const SkMatrix& viewMatrix, + const SkIRect& clipBounds, SkScalar x, SkScalar y) { + size_t textLen = it.glyphCount() * sizeof(uint16_t); + const SkPoint& offset = it.offset(); - bool skipClip = false; - bool submitOp = true; - SkIRect clipRect = SkIRect::MakeEmpty(); - SkRect rtBounds = SkRect::MakeWH(target->width(), target->height()); - SkRRect clipRRect; - GrAA aa; - // We can clip geometrically if we're not using SDFs, - // and we have an axis-aligned rectangular non-AA clip - if (!info.drawAsDistanceFields() && 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, runIndex, subRun, viewMatrix, x, y); - if (!clipRRect.getBounds().contains(subRunBounds)) { - // If the subrun is completely outside, don't add an op for it - if (!clipRRect.getBounds().intersects(subRunBounds)) { - submitOp = false; - } - else { - clipRRect.getBounds().round(&clipRect); - } - } - } + GrTextUtils::RunPaint runPaint(&paint, drawFilter, props); + if (!runPaint.modifyForRun(it)) { + return; + } - if (submitOp) { - auto op = this->makeOp(info, glyphCount, runIndex, subRun, viewMatrix, x, y, - clipRect, std::move(paint), props, distanceAdjustTable, - atlasGlyphCache, target); - if (op) { - if (skipClip) { - target->addDrawOp(GrNoClip(), std::move(op)); - } - else { - target->addDrawOp(clip, std::move(op)); - } - } - } - } + switch (it.positioning()) { + case SkTextBlob::kDefault_Positioning: + GrTextUtils::DrawBigText(target, clip, runPaint, viewMatrix, + (const char*)it.glyphs(), textLen, x + offset.x(), + y + offset.y(), clipBounds); + break; + case SkTextBlob::kHorizontal_Positioning: + GrTextUtils::DrawBigPosText(target, props, clip, runPaint, viewMatrix, + (const char*)it.glyphs(), textLen, it.pos(), 1, + SkPoint::Make(x, y + offset.y()), clipBounds); + break; + case SkTextBlob::kFull_Positioning: + GrTextUtils::DrawBigPosText(target, props, clip, runPaint, viewMatrix, + (const char*)it.glyphs(), textLen, it.pos(), 2, + SkPoint::Make(x, y), clipBounds); + break; + } +} - // now flush any path glyphs - SkScalar transX, transY; - for (int i = 0; i < run.fPathGlyphs.count(); i++) { - GrAtlasTextBlob::Run::PathGlyph& pathGlyph = run.fPathGlyphs[i]; - calculate_translation(pathGlyph.fPreTransformed, viewMatrix, x, y, - fInitialViewMatrix, fInitialX, fInitialY, &transX, &transY); - const SkMatrix& ctm = pathGlyph.fPreTransformed ? SkMatrix::I() : viewMatrix; - SkMatrix pathMatrix; - pathMatrix.setScale(pathGlyph.fScale, pathGlyph.fScale); - pathMatrix.postTranslate(pathGlyph.fX + transX, pathGlyph.fY + transY); - target->drawPath(clip, pathGlyph.fPath, paint, ctm, &pathMatrix, clipBounds); +void GrAtlasTextBlob::flushCached(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Target* target, + const SkTextBlob* blob, const SkSurfaceProps& props, + const GrDistanceFieldAdjustTable* distanceAdjustTable, + const GrTextUtils::Paint& paint, SkDrawFilter* drawFilter, + const GrClip& clip, const SkMatrix& viewMatrix, + const SkIRect& clipBounds, SkScalar x, SkScalar y) { + // We loop through the runs of the blob, flushing each. If any run is too large, then we flush + // it as paths + SkTextBlobRunIterator it(blob); + for (int run = 0; !it.done(); it.next(), run++) { + if (fRuns[run].fTooBigForAtlas) { + this->flushBigRun(target, props, it, clip, paint, drawFilter, viewMatrix, + clipBounds, x, y); + continue; } + this->flushRun(target, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable, + atlasGlyphCache); + } + + // Now flush big glyphs + this->flushBigGlyphs(target, clip, paint, viewMatrix, x, y, clipBounds); +} + +void GrAtlasTextBlob::flushThrowaway(GrAtlasGlyphCache* atlasGlyphCache, + GrTextUtils::Target* target, + const SkSurfaceProps& props, + const GrDistanceFieldAdjustTable* distanceAdjustTable, + const GrTextUtils::Paint& paint, const GrClip& clip, + const SkMatrix& viewMatrix, const SkIRect& clipBounds, + SkScalar x, SkScalar y) { + for (int run = 0; run < fRunCount; run++) { + this->flushRun(target, clip, run, viewMatrix, x, y, paint, props, distanceAdjustTable, + atlasGlyphCache); } + + // Now flush big glyphs + this->flushBigGlyphs(target, clip, paint, viewMatrix, x, y, clipBounds); } std::unique_ptr<GrDrawOp> GrAtlasTextBlob::test_makeOp( @@ -394,6 +462,15 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo SkASSERT_RELEASE(l.fStrokeInfo.fMiterLimit == r.fStrokeInfo.fMiterLimit); SkASSERT_RELEASE(l.fStrokeInfo.fJoin == r.fStrokeInfo.fJoin); + SkASSERT_RELEASE(l.fBigGlyphs.count() == r.fBigGlyphs.count()); + for (int i = 0; i < l.fBigGlyphs.count(); i++) { + const BigGlyph& lBigGlyph = l.fBigGlyphs[i]; + const BigGlyph& rBigGlyph = r.fBigGlyphs[i]; + + SkASSERT_RELEASE(lBigGlyph.fPath == rBigGlyph.fPath); + // We can't assert that these have the same translations + } + SkASSERT_RELEASE(l.fKey == r.fKey); //SkASSERT_RELEASE(l.fPaintColor == r.fPaintColor); // Colors might not actually be identical SkASSERT_RELEASE(l.fMaxMinScale == r.fMaxMinScale); @@ -429,6 +506,7 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo // color can be changed //SkASSERT(lRun.fColor == rRun.fColor); SkASSERT_RELEASE(lRun.fInitialized == rRun.fInitialized); + SkASSERT_RELEASE(lRun.fTooBigForAtlas == rRun.fTooBigForAtlas); SkASSERT_RELEASE(lRun.fSubRunInfo.count() == rRun.fSubRunInfo.count()); for(int j = 0; j < lRun.fSubRunInfo.count(); j++) { @@ -455,15 +533,6 @@ void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlo SkASSERT_RELEASE(lSubRun.drawAsDistanceFields() == rSubRun.drawAsDistanceFields()); SkASSERT_RELEASE(lSubRun.hasUseLCDText() == rSubRun.hasUseLCDText()); } - - SkASSERT_RELEASE(lRun.fPathGlyphs.count() == rRun.fPathGlyphs.count()); - for (int i = 0; i < lRun.fPathGlyphs.count(); i++) { - const Run::PathGlyph& lPathGlyph = lRun.fPathGlyphs[i]; - const Run::PathGlyph& rPathGlyph = rRun.fPathGlyphs[i]; - - SkASSERT_RELEASE(lPathGlyph.fPath == rPathGlyph.fPath); - // We can't assert that these have the same translations - } } } |