aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/text/GrAtlasTextBlob.cpp
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2018-02-06 21:30:20 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-06 21:30:26 +0000
commit89737decb4965ec250f02af432884366945d2e53 (patch)
tree0fc0febed63db177d8643239d4728f9446306916 /src/gpu/text/GrAtlasTextBlob.cpp
parent74416048652002955302cf7bb62c9e01f281efee (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.cpp253
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
- }
}
}