From cddab25218c52327ee1c527d726e69aa89540917 Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Mon, 16 Jul 2018 11:19:04 -0400 Subject: Use SkGlyphRunListIterator in gpu Instead of using the text blob through the stack start using the glyph run list. This CL is similar to a portion of https://skia-review.googlesource.com/c/skia/+/137224 which was reverted. Change-Id: I1f0619bd2d13523f9af1a68ab27fb26abd086add Reviewed-on: https://skia-review.googlesource.com/141543 Commit-Queue: Herb Derby Reviewed-by: Jim Van Verth --- src/gpu/text/GrTextContext.cpp | 158 +++++++++++------------------------------ 1 file changed, 43 insertions(+), 115 deletions(-) (limited to 'src/gpu/text/GrTextContext.cpp') diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp index a2ef40f16d..e68be09bfb 100644 --- a/src/gpu/text/GrTextContext.cpp +++ b/src/gpu/text/GrTextContext.cpp @@ -84,56 +84,48 @@ SkScalerContextFlags GrTextContext::ComputeScalerContextFlags( } } -// TODO if this function ever shows up in profiling, then we can compute this value when the -// textblob is being built and cache it. However, for the time being textblobs mostly only have 1 -// run so this is not a big deal to compute here. -bool GrTextContext::HasLCD(const SkTextBlob* blob) { - SkTextBlobRunIterator it(blob); - for (; !it.done(); it.next()) { - if (it.isLCD()) { - return true; - } - } - return false; -} +void GrTextContext::drawGlyphRunList( + GrContext* context, GrTextUtils::Target* target, const GrClip& clip, + const SkMatrix& viewMatrix, const SkSurfaceProps& props, SkGlyphRunList* glyphRunList, + const SkIRect& clipBounds) { + SkPoint origin = glyphRunList->origin(); + + // Get the first paint to use as the key paint. + const SkPaint& skPaint = glyphRunList->paint(); -void GrTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target, - const GrClip& clip, const SkPaint& skPaint, - const SkMatrix& viewMatrix, const SkSurfaceProps& props, - const SkTextBlob* blob, SkScalar x, SkScalar y, - const SkIRect& clipBounds) { // If we have been abandoned, then don't draw if (context->abandoned()) { return; } - sk_sp cacheBlob; SkMaskFilterBase::BlurRec blurRec; - GrTextBlob::Key key; // It might be worth caching these things, but its not clear at this time // TODO for animated mask filters, this will fill up our cache. We need a safeguard here const SkMaskFilter* mf = skPaint.getMaskFilter(); - bool canCache = !(skPaint.getPathEffect() || (mf && !as_MFB(mf)->asABlur(&blurRec))); + bool canCache = glyphRunList->canCache() && !(skPaint.getPathEffect() || + (mf && !as_MFB(mf)->asABlur(&blurRec))); SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo()); auto glyphCache = context->contextPriv().getGlyphCache(); GrTextBlobCache* textBlobCache = context->contextPriv().getTextBlobCache(); + sk_sp cacheBlob; + GrTextBlob::Key key; if (canCache) { - bool hasLCD = HasLCD(blob); + bool hasLCD = glyphRunList->anyRunsLCD(); // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() : - kUnknown_SkPixelGeometry; + kUnknown_SkPixelGeometry; // TODO we want to figure out a way to be able to use the canonical color on LCD text, // see the note on ComputeCanonicalColor above. We pick a dummy value for LCD text to // ensure we always match the same key GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : - ComputeCanonicalColor(skPaint, hasLCD); + ComputeCanonicalColor(skPaint, hasLCD); key.fPixelGeometry = pixelGeometry; - key.fUniqueID = blob->uniqueID(); + key.fUniqueID = glyphRunList->uniqueID(); key.fStyle = skPaint.getStyle(); key.fHasBlur = SkToBool(mf); key.fCanonicalColor = canonicalColor; @@ -143,139 +135,77 @@ void GrTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* target GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); if (cacheBlob) { - if (cacheBlob->mustRegenerate(paint, blurRec, viewMatrix, x, y)) { + if (cacheBlob->mustRegenerate(paint, 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 textBlobCache->remove(cacheBlob.get()); - cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint); - this->regenerateTextBlob(cacheBlob.get(), glyphCache, + cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint); + this->regenerateGlyphRunList(cacheBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(), paint, - scalerContextFlags, viewMatrix, props, blob, x, y); + scalerContextFlags, viewMatrix, props, glyphRunList); } else { textBlobCache->makeMRU(cacheBlob.get()); if (CACHE_SANITY_CHECK) { - int glyphCount = 0; - int runCount = 0; - GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); + int glyphCount = glyphRunList->totalGlyphCount(); + int runCount = glyphRunList->runCount(); sk_sp sanityBlob(textBlobCache->makeBlob(glyphCount, runCount)); sanityBlob->setupKey(key, blurRec, skPaint); - this->regenerateTextBlob( + this->regenerateGlyphRunList( sanityBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(), - paint, scalerContextFlags, viewMatrix, props, blob, x, y); + paint, scalerContextFlags, viewMatrix, props, glyphRunList); GrTextBlob::AssertEqual(*sanityBlob, *cacheBlob); } } } else { if (canCache) { - cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint); + cacheBlob = textBlobCache->makeCachedBlob(glyphRunList, key, blurRec, skPaint); } else { - cacheBlob = textBlobCache->makeBlob(blob); + cacheBlob = textBlobCache->makeBlob(glyphRunList); } - this->regenerateTextBlob(cacheBlob.get(), glyphCache, + this->regenerateGlyphRunList(cacheBlob.get(), glyphCache, *context->contextPriv().caps()->shaderCaps(), paint, - scalerContextFlags, viewMatrix, props, blob, x, y); + scalerContextFlags, viewMatrix, props, glyphRunList); } cacheBlob->flush(target, props, fDistanceAdjustTable.get(), paint, - clip, viewMatrix, clipBounds, x, y); + clip, viewMatrix, clipBounds, origin.x(), origin.y()); } -void GrTextContext::regenerateTextBlob(GrTextBlob* cacheBlob, +void GrTextContext::regenerateGlyphRunList(GrTextBlob* cacheBlob, GrGlyphCache* glyphCache, const GrShaderCaps& shaderCaps, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, - const SkSurfaceProps& props, const SkTextBlob* blob, - SkScalar x, SkScalar y) const { - cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, x, y); + const SkSurfaceProps& props, + SkGlyphRunList* glyphRunList) const { + SkPoint origin = glyphRunList->origin(); + cacheBlob->initReusableBlob(paint.luminanceColor(), viewMatrix, origin.x(), origin.y()); // Regenerate textblob - SkTextBlobRunIterator it(blob); + SkGlyphRunListIterator it(glyphRunList); GrTextUtils::RunPaint runPaint(&paint); for (int run = 0; !it.done(); it.next(), run++) { int glyphCount = it.glyphCount(); size_t textLen = glyphCount * sizeof(uint16_t); - const SkPoint& offset = it.offset(); cacheBlob->push_back_run(run); if (!runPaint.modifyForRun([it](SkPaint* p) { it.applyFontToPaint(p); })) { continue; } cacheBlob->setRunPaintFlags(run, runPaint.skPaint().getFlags()); + SkASSERT(it.positioning() == SkTextBlob::kFull_Positioning); if (CanDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps.supportsDistanceFieldText(), fOptions)) { - switch (it.positioning()) { - case SkTextBlob::kDefault_Positioning: { - auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); - SkGlyphRunBuilder builder; - builder.drawText(runPaint.skPaint(), - (const char*) it.glyphs(), textLen, origin); - - auto glyphRunList = builder.useGlyphRunList(); - if (!glyphRunList->empty()) { - auto glyphRun = (*glyphRunList)[0]; - glyphRun.temporaryShuntToCallback( - [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { - this->drawDFPosText( - cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, glyphIDs, 2 * runSize, - pos, 2, SkPoint::Make(0, 0)); - }); - } - break; - } - - case SkTextBlob::kHorizontal_Positioning: { - SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); - this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, (const char*)it.glyphs(), - textLen, it.pos(), 1, dfOffset); - break; - } - case SkTextBlob::kFull_Positioning: { - SkPoint dfOffset = SkPoint::Make(x, y); - this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, (const char*)it.glyphs(), - textLen, it.pos(), 2, dfOffset); - break; - } - } + this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, + scalerContextFlags, viewMatrix, (const char*)it.glyphs(), + textLen, it.pos(), 2, origin); } else { - switch (it.positioning()) { - case SkTextBlob::kDefault_Positioning: { - auto origin = SkPoint::Make(x + offset.x(), y + offset.y()); - SkGlyphRunBuilder builder; - builder.drawText(runPaint.skPaint(), - (const char*) it.glyphs(), textLen, origin); - - auto glyphRunList = builder.useGlyphRunList(); - if (!glyphRunList->empty()) { - auto glyphRun = (*glyphRunList)[0]; - - glyphRun.temporaryShuntToCallback( - [&](size_t runSize, const char* glyphIDs, const SkScalar* pos) { - this->DrawBmpPosText( - cacheBlob, run, glyphCache, props, runPaint, - scalerContextFlags, viewMatrix, glyphIDs, 2 * runSize, - pos, 2, SkPoint::Make(0, 0)); - }); - } - break; - } - case SkTextBlob::kHorizontal_Positioning: - DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, - viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, - SkPoint::Make(x, y + offset.y())); - break; - case SkTextBlob::kFull_Positioning: - DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, - viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, - SkPoint::Make(x, y)); - break; - } + DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, + origin); } } } @@ -335,7 +265,6 @@ void GrTextContext::drawPosText(GrContext* context, GrTextUtils::Target* target, } } - void GrTextContext::DrawBmpPosText(GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, @@ -798,8 +727,7 @@ std::unique_ptr GrTextContext::createOp_TestingOnly(GrContext* context context->contextPriv().getTextBlobCache(), glyphCache, *context->contextPriv().caps()->shaderCaps(), utilsPaint, GrTextContext::kTextBlobOpScalerContextFlags, viewMatrix, surfaceProps, - text, - textLen, pos, 2, origin); + text, textLen, pos, 2, origin); }); } -- cgit v1.2.3