Move remote glyph cache DFT handling to painter

Change-Id: I68178e0675a45d77355b76a50eff06238ee1c54c
Reviewed-on: https://skia-review.googlesource.com/158380
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Herb Derby 2018-10-01 14:09:25 -04:00 committed by Skia Commit-Bot
parent 8ef78eae93
commit 7d8e1f7ca3
6 changed files with 77 additions and 223 deletions

View File

@ -335,40 +335,6 @@ void SkGlyphRunListPainter::processARGBFallback(
}
#if SK_SUPPORT_GPU
template <typename PerSDFT, typename PerPathT>
void SkGlyphRunListPainter::drawGlyphRunAsSDFWithARGBFallback(
SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun,
SkPoint origin, const SkMatrix& viewMatrix, SkScalar textScale,
PerSDFT perSDF, PerPathT perPath, ARGBFallback argbFallback) {
fARGBGlyphsIDs.clear();
fARGBPositions.clear();
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
const SkPoint* positionCursor = glyphRun.positions().data();
for (auto glyphID : glyphRun.shuntGlyphsIDs()) {
const SkGlyph& glyph = cache->getGlyphMetrics(glyphID, {0, 0});
SkPoint glyphPos = origin + *positionCursor++;
if (glyph.fMaskFormat == SkMask::kSDF_Format || glyph.isEmpty()) {
if (!SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
perSDF(glyph, glyphPos);
} else {
perPath(glyph, glyphPos);
}
} else {
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
maxFallbackDimension = std::max(maxFallbackDimension, largestDimension);
fARGBGlyphsIDs.push_back(glyphID);
fARGBPositions.push_back(glyphPos);
}
}
if (!fARGBGlyphsIDs.empty()) {
this->processARGBFallback(
maxFallbackDimension, glyphRun.paint(), origin, viewMatrix, textScale, argbFallback);
}
}
// -- GrTextContext --------------------------------------------------------------------------------
GrColor generate_filtered_color(const SkPaint& paint, const GrColorSpaceInfo& colorSpaceInfo) {
GrColor4f filteredColor = SkColor4fToUnpremulGrColor4f(paint.getColor4f(), colorSpaceInfo);

View File

@ -224,4 +224,37 @@ void SkGlyphRunListPainter::drawGlyphRunAsBMPWithPathFallback(
this->forEachMappedDrawableGlyph(glyphRun, origin, deviceMatrix, cache, eachGlyph);
}
template <typename PerSDFT, typename PerPathT>
void SkGlyphRunListPainter::drawGlyphRunAsSDFWithARGBFallback(
SkGlyphCacheInterface* cache, const SkGlyphRun& glyphRun,
SkPoint origin, const SkMatrix& viewMatrix, SkScalar textScale,
PerSDFT perSDF, PerPathT perPath, ARGBFallback argbFallback) {
fARGBGlyphsIDs.clear();
fARGBPositions.clear();
SkScalar maxFallbackDimension{-SK_ScalarInfinity};
const SkPoint* positionCursor = glyphRun.positions().data();
for (auto glyphID : glyphRun.shuntGlyphsIDs()) {
const SkGlyph& glyph = cache->getGlyphMetrics(glyphID, {0, 0});
SkPoint glyphPos = origin + *positionCursor++;
if (glyph.fMaskFormat == SkMask::kSDF_Format || glyph.isEmpty()) {
if (!SkGlyphCacheCommon::GlyphTooBigForAtlas(glyph)) {
perSDF(glyph, glyphPos);
} else {
perPath(glyph, glyphPos);
}
} else {
SkScalar largestDimension = std::max(glyph.fWidth, glyph.fHeight);
maxFallbackDimension = std::max(maxFallbackDimension, largestDimension);
fARGBGlyphsIDs.push_back(glyphID);
fARGBPositions.push_back(glyphPos);
}
}
if (!fARGBGlyphsIDs.empty()) {
this->processARGBFallback(
maxFallbackDimension, glyphRun.paint(), origin, viewMatrix, textScale, argbFallback);
}
}
#endif // SkGlyphRunPainter_DEFINED

View File

@ -182,40 +182,6 @@ bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkGlyphCache* cache)
return cache->initializePath(glyph, path, pathSize);
}
void add_glyph_to_cache(SkStrikeServer::SkGlyphCacheState* cache, SkTypeface* tf,
const SkScalerContextEffects& effects, SkGlyphID glyphID) {
SkASSERT(cache != nullptr);
cache->addGlyph(SkPackedGlyphID(glyphID, 0, 0), false);
}
#if SK_SUPPORT_GPU
void add_fallback_text_to_cache(const GrTextContext::FallbackGlyphRunHelper& helper,
const SkSurfaceProps& props,
const SkMatrix& matrix,
const SkPaint& origPaint,
SkStrikeServer* server) {
if (helper.fallbackText().empty()) {
return;
}
TRACE_EVENT0("skia", "add_fallback_text_to_cache");
SkPaint fallbackPaint{origPaint};
SkScalar textRatio;
SkMatrix fallbackMatrix = matrix;
helper.initializeForDraw(&fallbackPaint, &textRatio, &fallbackMatrix);
SkScalerContextEffects effects;
auto* glyphCacheState =
server->getOrCreateCache(fallbackPaint, props, fallbackMatrix,
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
for (auto glyphID : helper.fallbackText()) {
add_glyph_to_cache(glyphCacheState, fallbackPaint.getTypeface(), effects, glyphID);
}
}
#endif
size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
return key->getChecksum();
}
@ -267,7 +233,7 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRun(
// If the matrix has perspective, we fall back to using distance field text or paths.
#if SK_SUPPORT_GPU
if (this->maybeProcessGlyphRunForDFT(glyphRun, runMatrix)) {
if (this->maybeProcessGlyphRunForDFT(glyphRun, runMatrix, origin)) {
return;
} else
#endif
@ -305,6 +271,29 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForMask(
glyphCacheState, glyphRun, origin, runMatrix, perGlyph, perPath);
}
struct ARGBHelper {
void operator () (const SkPaint& fallbackPaint, SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkPoint> positions, SkScalar textScale,
const SkMatrix& glyphCacheMatrix,
SkGlyphRunListPainter::NeedsTransform needsTransform) {
TRACE_EVENT0("skia", "argbFallback");
SkScalerContextEffects effects;
auto* fallbackCache =
fStrikeServer->getOrCreateCache(
fallbackPaint, fSurfaceProps, fFallbackMatrix,
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
for (auto glyphID : glyphIDs) {
fallbackCache->addGlyph(SkPackedGlyphID(glyphID, 0, 0), false);
}
}
const SkMatrix& fFallbackMatrix;
const SkSurfaceProps& fSurfaceProps;
SkStrikeServer* const fStrikeServer;
};
void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin) {
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForPaths");
@ -323,24 +312,7 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
glyphCacheState->addGlyph(glyph.getGlyphID(), asPath);
};
auto argbFallback = [this, &runMatrix]
(const SkPaint& fallbackPaint, SkSpan<const SkGlyphID> glyphIDs,
SkSpan<const SkPoint> positions, SkScalar textScale,
const SkMatrix& glyphCacheMatrix,
SkGlyphRunListPainter::NeedsTransform needsTransform) {
TRACE_EVENT0("skia", "argbFallback_path");
SkMatrix fallbackMatrix = runMatrix;
SkScalerContextEffects effects;
auto* glyphCacheState =
fStrikeServer->getOrCreateCache(
fallbackPaint, surfaceProps(), fallbackMatrix,
SkScalerContextFlags::kFakeGammaAndBoostContrast, &effects);
for (auto glyphID : glyphIDs) {
add_glyph_to_cache(glyphCacheState, fallbackPaint.getTypeface(), effects, glyphID);
}
};
ARGBHelper argbFallback{runMatrix, surfaceProps(), fStrikeServer};
fPainter.drawGlyphRunAsPathWithARGBFallback(
glyphCacheState, glyphRun, origin, runMatrix, textScale, perPath, argbFallback);
@ -348,7 +320,7 @@ void SkTextBlobCacheDiffCanvas::TrackLayerDevice::processGlyphRunForPaths(
#if SK_SUPPORT_GPU
bool SkTextBlobCacheDiffCanvas::TrackLayerDevice::maybeProcessGlyphRunForDFT(
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix) {
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin) {
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::maybeProcessGlyphRunForDFT");
const SkPaint& runPaint = glyphRun.paint();
@ -369,33 +341,29 @@ bool SkTextBlobCacheDiffCanvas::TrackLayerDevice::maybeProcessGlyphRunForDFT(
GrTextContext::InitDistanceFieldPaint(nullptr, &dfPaint, runMatrix, options, &textRatio,
&flags);
SkScalerContextEffects effects;
auto* glyphCacheState = fStrikeServer->getOrCreateCache(dfPaint, this->surfaceProps(),
auto* sdfCache = fStrikeServer->getOrCreateCache(dfPaint, this->surfaceProps(),
SkMatrix::I(), flags, &effects);
GrTextContext::FallbackGlyphRunHelper fallbackTextHelper(runMatrix, runPaint, textRatio);
const bool asPath = false;
const SkPoint emptyPosition{0, 0};
auto glyphs = glyphRun.shuntGlyphsIDs();
for (uint32_t index = 0; index < glyphRun.runSize(); index++) {
auto glyphID = glyphs[index];
const auto& glyph =
glyphCacheState->findGlyph(glyphID);
if (glyph.fMaskFormat != SkMask::kSDF_Format && !glyph.isEmpty()) {
// Note that we send data for the original glyph even in the case of fallback
// since its glyph metrics will still be used on the client.
fallbackTextHelper.appendGlyph(glyph, glyphID, emptyPosition);
}
ARGBHelper argbFallback{runMatrix, surfaceProps(), fStrikeServer};
glyphCacheState->addGlyph(SkPackedGlyphID(glyphs[index]), asPath);
}
auto perSDF = [sdfCache] (const SkGlyph& glyph, SkPoint position) {
const bool asPath = false;
sdfCache->addGlyph(glyph.getGlyphID(), asPath);
};
auto perPath = [sdfCache] (const SkGlyph& glyph, SkPoint position) {
const bool asPath = true;
sdfCache->addGlyph(glyph.getGlyphID(), asPath);
};
fPainter.drawGlyphRunAsSDFWithARGBFallback(
sdfCache, glyphRun, origin, runMatrix, textRatio,
perSDF, perPath, argbFallback);
add_fallback_text_to_cache(fallbackTextHelper, this->surfaceProps(), runMatrix, runPaint,
fStrikeServer);
return true;
}
#endif
// -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
SkTextBlobCacheDiffCanvas::Settings::Settings() = default;

View File

@ -10,6 +10,7 @@
#include "SkDescriptor.h"
#include "SkGlyphRun.h"
#include "SkGlyphRunPainter.h"
#include "SkRemoteGlyphCache.h"
class SkStrikeServer::SkGlyphCacheState : public SkGlyphCacheInterface {
@ -104,7 +105,8 @@ private:
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin);
#if SK_SUPPORT_GPU
bool maybeProcessGlyphRunForDFT(const SkGlyphRun& glyphRun, const SkMatrix& runMatrix);
bool maybeProcessGlyphRunForDFT(
const SkGlyphRun& glyphRun, const SkMatrix& runMatrix, SkPoint origin);
#endif
SkStrikeServer* const fStrikeServer;

View File

@ -200,94 +200,6 @@ void GrTextContext::InitDistanceFieldPaint(GrTextBlob* blob,
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Fallback uses a fast strategy and a general strategy. If the viewMatrix is only scale and
// translate, and all the glyphs in the run are small enough, then the font uses the runPaint for
// the size of the colored glyph, and the positions are all transformed. In the general case,
// a suitable font size is found, and the view transformation happens during rendering. The font
// in the general case is oriented with x and y, and all rotations, scaling, etc. happen during
// rendering.
GrTextContext::FallbackGlyphRunHelper::FallbackGlyphRunHelper(
const SkMatrix& viewMatrix, const SkPaint& runPaint, SkScalar textRatio)
: fViewMatrix(viewMatrix)
, fTextSize(runPaint.getTextSize())
, fMaxTextSize(SkGlyphCacheCommon::kSkSideTooBigForAtlas)
, fTextRatio(textRatio)
, fTransformedFallbackTextSize(fMaxTextSize)
, fMaxScale(viewMatrix.getMaxScale())
, fUseTransformedFallback(false) { }
void GrTextContext::FallbackGlyphRunHelper::appendGlyph(
const SkGlyph& glyph, SkGlyphID glyphID, SkPoint glyphPos) {
SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio;
if (SkScalarNearlyZero(maxDim)) return;
if (!fUseTransformedFallback) {
if (!fViewMatrix.isScaleTranslate() || maxDim*fMaxScale > fMaxTextSize) {
fUseTransformedFallback = true;
fMaxTextSize -= 2; // Subtract 2 to account for the bilerp pad around the glyph
}
}
if (fUseTransformedFallback) {
// If there's a glyph in the font that's particularly large, it's possible
// that fScaledFallbackTextSize may end up minimizing too much. We'd rather skip
// that glyph than make the others blurry, so we set a minimum size of half the
// maximum text size to avoid this case.
SkScalar glyphTextSize =
SkTMax(SkScalarFloorToScalar(fTextSize * fMaxTextSize/maxDim), 0.5f*fMaxTextSize);
fTransformedFallbackTextSize = SkTMin(glyphTextSize, fTransformedFallbackTextSize);
}
fFallbackTxt.push_back(glyphID);
fFallbackPos.push_back(glyphPos);
}
void GrTextContext::FallbackGlyphRunHelper::drawGlyphs(
GrTextBlob* blob, int runIndex, GrGlyphCache* glyphCache, const SkSurfaceProps& props,
const SkPaint& paint, GrColor filteredColor, SkScalerContextFlags scalerContextFlags) {
if (!fFallbackTxt.empty()) {
blob->initOverride(runIndex);
blob->setHasBitmap();
blob->setSubRunHasW(runIndex, fViewMatrix.hasPerspective());
const SkPaint& skPaint = paint;
SkColor textColor = filteredColor;
SkScalar textRatio = SK_Scalar1;
SkPaint fallbackPaint(skPaint);
SkMatrix matrix = fViewMatrix;
this->initializeForDraw(&fallbackPaint, &textRatio, &matrix);
SkExclusiveStrikePtr cache =
blob->setupCache(runIndex, props, scalerContextFlags, fallbackPaint, &matrix);
sk_sp<GrTextStrike> currStrike = glyphCache->getStrike(cache.get());
auto glyphPos = fFallbackPos.begin();
for (auto glyphID : fFallbackTxt) {
const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
if (!fUseTransformedFallback) {
fViewMatrix.mapPoints(&*glyphPos, 1);
glyphPos->fX = SkScalarFloorToScalar(glyphPos->fX);
glyphPos->fY = SkScalarFloorToScalar(glyphPos->fY);
}
GrTextContext::AppendGlyph(blob, runIndex, currStrike,
glyph, GrGlyph::kCoverage_MaskStyle,
glyphPos->fX, glyphPos->fY, textColor,
cache.get(), textRatio, fUseTransformedFallback);
glyphPos++;
}
}
}
void GrTextContext::FallbackGlyphRunHelper::initializeForDraw(
SkPaint* paint, SkScalar* textRatio, SkMatrix* matrix) const {
if (!fUseTransformedFallback) return;
paint->setTextSize(fTransformedFallbackTextSize);
*textRatio = fTextSize / fTransformedFallbackTextSize;
*matrix = SkMatrix::I();
}
///////////////////////////////////////////////////////////////////////////////////////////////////
#if GR_TEST_UTILS

View File

@ -68,33 +68,6 @@ public:
SkScalar* textRatio,
SkScalerContextFlags* flags);
class FallbackGlyphRunHelper {
public:
FallbackGlyphRunHelper(
const SkMatrix& viewMatrix, const SkPaint& runPaint, SkScalar textRatio);
void appendGlyph(const SkGlyph& glyph, SkGlyphID glyphID, SkPoint glyphPos);
void drawGlyphs(
GrTextBlob* blob, int runIndex, GrGlyphCache* cache,
const SkSurfaceProps& props, const SkPaint& runPaint, GrColor filteredColor,
SkScalerContextFlags scalerContextFlags);
void initializeForDraw(SkPaint* paint, SkScalar* textRatio, SkMatrix* matrix) const;
const std::vector<SkGlyphID>& fallbackText() const { return fFallbackTxt; }
private:
std::vector<SkGlyphID> fFallbackTxt;
std::vector<SkPoint> fFallbackPos;
const SkMatrix& fViewMatrix;
SkScalar fTextSize;
SkScalar fMaxTextSize{SkGlyphCacheCommon::kSkSideTooBigForAtlas};
SkScalar fTextRatio;
SkScalar fTransformedFallbackTextSize;
SkScalar fMaxScale;
bool fUseTransformedFallback;
};
private:
GrTextContext(const Options& options);