aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Khushal <khushalsagar@chromium.org>2018-06-06 17:46:38 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-07 18:03:11 +0000
commitfa8ff09457f82119be0d00b7f37afb790487819e (patch)
tree65ee0f8eff9997add651bf8f3b48ac74b4413cdf
parentd5b4593024544c3405615066aa5b4f94352eb3cb (diff)
fonts: Hook up FallbackTextHelper to font remoting.
Use GrContext::FallbackTextHelper in SkTextBlobCacheDiffCanvas to replicate glyph generation logic for fallback text during analysis. This ensures that we correctly handle these fallback cases when using distance field or paths for text rendering. R=herb@google.com, jvanverth@google.com Bug: skia:7913 Change-Id: I3067c4f1bd09231a564ac7c4cd89efcb876d2abd Reviewed-on: https://skia-review.googlesource.com/132285 Reviewed-by: Jim Van Verth <jvanverth@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Khusal Sagar <khushalsagar@chromium.org>
-rw-r--r--include/gpu/GrContextOptions.h2
-rw-r--r--src/core/SkRemoteGlyphCache.cpp185
-rw-r--r--src/core/SkRemoteGlyphCache.h25
-rw-r--r--src/core/SkTypeface_remote.cpp10
-rw-r--r--src/gpu/text/GrAtlasManager.cpp14
-rw-r--r--src/gpu/text/GrAtlasManager.h4
-rw-r--r--src/gpu/text/GrGlyphCache.cpp20
-rw-r--r--src/gpu/text/GrGlyphCache.h3
-rw-r--r--src/gpu/text/GrTextContext.cpp33
-rw-r--r--src/gpu/text/GrTextContext.h23
-rw-r--r--tests/SkRemoteGlyphCacheTest.cpp13
11 files changed, 232 insertions, 100 deletions
diff --git a/include/gpu/GrContextOptions.h b/include/gpu/GrContextOptions.h
index 2d3151db67..11838707b5 100644
--- a/include/gpu/GrContextOptions.h
+++ b/include/gpu/GrContextOptions.h
@@ -98,7 +98,7 @@ struct GrContextOptions {
/**
* The maximum size of cache textures used for Skia's Glyph cache.
*/
- float fGlyphCacheTextureMaximumBytes = 2048 * 1024 * 4;
+ size_t fGlyphCacheTextureMaximumBytes = 2048 * 1024 * 4;
/**
* Below this threshold size in device space distance field fonts won't be used. Distance field
diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp
index 922014b173..fe3b900fe6 100644
--- a/src/core/SkRemoteGlyphCache.cpp
+++ b/src/core/SkRemoteGlyphCache.cpp
@@ -168,6 +168,49 @@ bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkGlyphCache* cache)
return cache->initializePath(glyph, path, pathSize);
}
+#if SK_SUPPORT_GPU
+SkScalar glyph_size_limit(const SkTextBlobCacheDiffCanvas::Settings& settings) {
+ return GrGlyphCache::ComputeGlyphSizeLimit(settings.fMaxTextureSize, settings.fMaxTextureBytes);
+}
+
+void add_glyph_to_cache(SkStrikeServer::SkGlyphCacheState* cache, SkTypeface* tf,
+ const SkScalerContextEffects& effects, const char** text) {
+ SkASSERT(cache != nullptr);
+ SkASSERT(text != nullptr);
+
+ const uint16_t* ptr = *(const uint16_t**)text;
+ unsigned glyphID = *ptr;
+ ptr += 1;
+ *text = (const char*)ptr;
+ cache->addGlyph(tf, effects, SkPackedGlyphID(glyphID, 0, 0), false);
+}
+
+void add_fallback_text_to_cache(const GrTextContext::FallbackTextHelper& helper,
+ const SkSurfaceProps& props,
+ const SkMatrix& matrix,
+ const SkPaint& origPaint,
+ SkStrikeServer* server) {
+ if (!helper.fallbackText().count()) return;
+
+ SkPaint fallbackPaint{origPaint};
+ SkScalar textRatio;
+ SkMatrix fallbackMatrix = matrix;
+ helper.initializeForDraw(&fallbackPaint, &textRatio, &fallbackMatrix);
+
+ SkScalerContextRec deviceSpecificRec;
+ SkScalerContextEffects effects;
+ auto* glyphCacheState = server->getOrCreateCache(
+ fallbackPaint, &props, &fallbackMatrix,
+ SkScalerContextFlags::kFakeGammaAndBoostContrast, &deviceSpecificRec, &effects);
+
+ const char* text = helper.fallbackText().begin();
+ const char* stop = text + helper.fallbackText().count();
+ while (text < stop) {
+ add_glyph_to_cache(glyphCacheState, fallbackPaint.getTypeface(), effects, &text);
+ }
+}
+#endif
+
size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
return key->getChecksum();
}
@@ -277,26 +320,14 @@ void SkTextBlobCacheDiffCanvas::processGlyphRun(
runMatrix.preConcat(this->getTotalMatrix());
#if SK_SUPPORT_GPU
- GrTextContext::Options options;
- options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize;
- options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize;
- GrTextContext::SanitizeOptions(&options);
- if (GrTextContext::CanDrawAsDistanceFields(runPaint, runMatrix, this->surfaceProps(),
- fSettings.fContextSupportsDistanceFieldText,
- options)) {
- SkScalar textRatio;
- SkPaint dfPaint(runPaint);
- SkScalerContextFlags flags;
- GrTextContext::InitDistanceFieldPaint(nullptr, &dfPaint, runMatrix, options,
- &textRatio, &flags);
- this->processGlyphRunForDFT(it, dfPaint, flags);
+ if (this->processGlyphRunForDFT(it, runPaint, runMatrix)) {
+ return;
}
#endif
// If the matrix has perspective, we fall back to using distance field text or paths.
- // TODO: Add distance field text support, and FallbackTextHelper logic from GrTextContext.
if (SkDraw::ShouldDrawTextAsPaths(runPaint, runMatrix)) {
- this->processGlyphRunForPaths(it, runPaint);
+ this->processGlyphRunForPaths(it, runPaint, runMatrix);
return;
}
@@ -326,11 +357,9 @@ void SkTextBlobCacheDiffCanvas::processGlyphRun(
SkScalerContextRec deviceSpecificRec;
SkScalerContextEffects effects;
- auto* glyphCacheState =
- static_cast<SkStrikeServer*>(fStrikeServer)
- ->getOrCreateCache(runPaint, &this->surfaceProps(), &runMatrix,
- SkScalerContextFlags::kFakeGammaAndBoostContrast,
- &deviceSpecificRec, &effects);
+ auto* glyphCacheState = fStrikeServer->getOrCreateCache(
+ runPaint, &this->surfaceProps(), &runMatrix,
+ SkScalerContextFlags::kFakeGammaAndBoostContrast, &deviceSpecificRec, &effects);
SkASSERT(glyphCacheState);
const bool asPath = false;
@@ -354,53 +383,104 @@ void SkTextBlobCacheDiffCanvas::processGlyphRun(
}
void SkTextBlobCacheDiffCanvas::processGlyphRunForPaths(const SkTextBlobRunIterator& it,
- const SkPaint& runPaint) {
+ const SkPaint& runPaint,
+ const SkMatrix& runMatrix) {
TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForPaths");
// The code below borrowed from GrTextContext::DrawBmpPosTextAsPaths.
SkPaint pathPaint(runPaint);
+#if SK_SUPPORT_GPU
+ SkScalar matrixScale = pathPaint.setupForAsPaths();
+ GrTextContext::FallbackTextHelper fallbackTextHelper(runMatrix, runPaint,
+ glyph_size_limit(fSettings), matrixScale);
+ const SkPoint emptyPosition{0, 0};
+#else
pathPaint.setupForAsPaths();
+#endif
+
pathPaint.setStyle(SkPaint::kFill_Style);
pathPaint.setPathEffect(nullptr);
SkScalerContextRec deviceSpecificRec;
SkScalerContextEffects effects;
- auto* glyphCacheState =
- static_cast<SkStrikeServer*>(fStrikeServer)
- ->getOrCreateCache(pathPaint, &this->surfaceProps(), nullptr,
- SkScalerContextFlags::kFakeGammaAndBoostContrast,
- &deviceSpecificRec, &effects);
+ auto* glyphCacheState = fStrikeServer->getOrCreateCache(
+ pathPaint, &this->surfaceProps(), nullptr,
+ SkScalerContextFlags::kFakeGammaAndBoostContrast, &deviceSpecificRec, &effects);
const bool asPath = true;
const SkIPoint subPixelPos{0, 0};
const uint16_t* glyphs = it.glyphs();
for (uint32_t index = 0; index < it.glyphCount(); index++) {
- glyphCacheState->addGlyph(runPaint.getTypeface(),
- effects,
- SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y()),
- asPath);
+ auto glyphID = SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y());
+#if SK_SUPPORT_GPU
+ const auto& glyph = glyphCacheState->findGlyph(runPaint.getTypeface(), effects, glyphID);
+ if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
+ // 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.appendText(glyph, sizeof(uint16_t), (const char*)&glyphs[index],
+ emptyPosition);
+ }
+#endif
+ glyphCacheState->addGlyph(runPaint.getTypeface(), effects, glyphID, asPath);
}
+
+#if SK_SUPPORT_GPU
+ add_fallback_text_to_cache(fallbackTextHelper, this->surfaceProps(), runMatrix, runPaint,
+ fStrikeServer);
+#endif
}
-void SkTextBlobCacheDiffCanvas::processGlyphRunForDFT(const SkTextBlobRunIterator& it,
+#if SK_SUPPORT_GPU
+bool SkTextBlobCacheDiffCanvas::processGlyphRunForDFT(const SkTextBlobRunIterator& it,
const SkPaint& runPaint,
- SkScalerContextFlags flags) {
+ const SkMatrix& runMatrix) {
+ GrTextContext::Options options;
+ options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize;
+ options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize;
+ GrTextContext::SanitizeOptions(&options);
+ if (!GrTextContext::CanDrawAsDistanceFields(runPaint, runMatrix, this->surfaceProps(),
+ fSettings.fContextSupportsDistanceFieldText,
+ options)) {
+ return false;
+ }
+
+ SkScalar textRatio;
+ SkPaint dfPaint(runPaint);
+ SkScalerContextFlags flags;
+ GrTextContext::InitDistanceFieldPaint(nullptr, &dfPaint, runMatrix, options, &textRatio,
+ &flags);
SkScalerContextRec deviceSpecificRec;
SkScalerContextEffects effects;
- auto* glyphCacheState = static_cast<SkStrikeServer*>(fStrikeServer)
- ->getOrCreateCache(runPaint, &this->surfaceProps(), nullptr,
- flags, &deviceSpecificRec, &effects);
+ auto* glyphCacheState = fStrikeServer->getOrCreateCache(dfPaint, &this->surfaceProps(), nullptr,
+ flags, &deviceSpecificRec, &effects);
+ GrTextContext::FallbackTextHelper fallbackTextHelper(runMatrix, runPaint,
+ glyph_size_limit(fSettings), textRatio);
const bool asPath = false;
const SkIPoint subPixelPos{0, 0};
+ const SkPoint emptyPosition{0, 0};
const uint16_t* glyphs = it.glyphs();
for (uint32_t index = 0; index < it.glyphCount(); index++) {
+ auto glyphID = SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y());
+ const auto& glyph = glyphCacheState->findGlyph(runPaint.getTypeface(), effects, glyphID);
+ if (glyph.fMaskFormat != SkMask::kSDF_Format) {
+ // 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.appendText(glyph, sizeof(uint16_t), (const char*)&glyphs[index],
+ emptyPosition);
+ }
+
glyphCacheState->addGlyph(runPaint.getTypeface(),
effects,
SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y()),
asPath);
}
+
+ add_fallback_text_to_cache(fallbackTextHelper, this->surfaceProps(), runMatrix, runPaint,
+ fStrikeServer);
+ return true;
}
+#endif
const SkSurfaceProps& SkTextBlobCacheDiffCanvas::surfaceProps() const {
// SaveLayers can change the SurfaceProps used, and we ensure that the props used by the top
@@ -460,13 +540,6 @@ void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
for (const auto* desc : fLockedDescs) {
auto it = fRemoteGlyphStateMap.find(desc);
SkASSERT(it != fRemoteGlyphStateMap.end());
-
- // TODO: This is unnecessary, write only the descs which has any glyphs
- // to send. It was getting awkward to write the size after writing the
- // descs because the vector reallocs.
- serializer.emplace<bool>(it->second->has_pending_glyphs());
- if (!it->second->has_pending_glyphs()) continue;
-
it->second->writePendingGlyphs(&serializer);
}
fLockedDescs.clear();
@@ -499,7 +572,7 @@ SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
auto it = fRemoteGlyphStateMap.find(keyDesc.get());
if (it != fRemoteGlyphStateMap.end()) {
SkASSERT(it->second->getDeviceDescriptor() == *deviceDesc);
- bool locked = fDiscardableHandleManager->lockHandle(it->second->discardable_handle_id());
+ bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
if (locked) {
fLockedDescs.insert(it->first);
return it->second.get();
@@ -532,10 +605,10 @@ SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState(std::unique_ptr<SkDescriptor> deviceDescriptor,
std::unique_ptr<SkDescriptor>
keyDescriptor,
- uint32_t discardable_handle_id)
+ uint32_t discardableHandleId)
: fDeviceDescriptor(std::move(deviceDescriptor))
, fKeyDescriptor(std::move(keyDescriptor))
- , fDiscardableHandleId(discardable_handle_id) {
+ , fDiscardableHandleId(discardableHandleId) {
SkASSERT(fDeviceDescriptor);
SkASSERT(fKeyDescriptor);
}
@@ -562,6 +635,13 @@ void SkStrikeServer::SkGlyphCacheState::addGlyph(SkTypeface* typeface,
}
void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) {
+ // TODO(khushalsagar): Write a strike only if it has any pending glyphs.
+ serializer->emplace<bool>(this->hasPendingGlyphs());
+ if (!this->hasPendingGlyphs()) {
+ fContext.reset();
+ return;
+ }
+
// Write the desc.
serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId);
serializer->writeDescriptor(*fKeyDescriptor.get());
@@ -622,6 +702,21 @@ void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serialize
fContext.reset();
}
+const SkGlyph& SkStrikeServer::SkGlyphCacheState::findGlyph(SkTypeface* tf,
+ const SkScalerContextEffects& effects,
+ SkPackedGlyphID glyphID) {
+ auto* glyph = fGlyphMap.find(glyphID);
+ if (glyph) return *glyph;
+
+ glyph = fGlyphMap.set(glyphID, SkGlyph());
+ glyph->initWithGlyphID(glyphID);
+ if (!fContext) {
+ fContext = tf->createScalerContext(effects, fDeviceDescriptor.get(), false);
+ }
+ fContext->getMetrics(glyph);
+ return *glyph;
+}
+
void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID,
Serializer* serializer) const {
SkPath path;
diff --git a/src/core/SkRemoteGlyphCache.h b/src/core/SkRemoteGlyphCache.h
index 4fa4e0afc1..2772de67cb 100644
--- a/src/core/SkRemoteGlyphCache.h
+++ b/src/core/SkRemoteGlyphCache.h
@@ -59,6 +59,8 @@ public:
bool fContextSupportsDistanceFieldText = true;
SkScalar fMinDistanceFieldFontSize = -1.f;
SkScalar fMaxDistanceFieldFontSize = -1.f;
+ int fMaxTextureSize = 0;
+ size_t fMaxTextureBytes = 0u;
};
SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix,
const SkSurfaceProps& props, SkStrikeServer* strikeserver,
@@ -79,9 +81,12 @@ private:
void processGlyphRun(const SkPoint& position,
const SkTextBlobRunIterator& it,
const SkPaint& runPaint);
- void processGlyphRunForPaths(const SkTextBlobRunIterator& it, const SkPaint& runPaint);
- void processGlyphRunForDFT(const SkTextBlobRunIterator& it, const SkPaint& runPaint,
- SkScalerContextFlags flags);
+ void processGlyphRunForPaths(const SkTextBlobRunIterator& it, const SkPaint& runPaint,
+ const SkMatrix& runMatrix);
+#if SK_SUPPORT_GPU
+ bool processGlyphRunForDFT(const SkTextBlobRunIterator& it, const SkPaint& runPaint,
+ const SkMatrix& runMatrix);
+#endif
const SkSurfaceProps& surfaceProps() const;
const SkMatrix fDeviceMatrix;
@@ -138,10 +143,7 @@ public:
void addGlyph(SkTypeface*, const SkScalerContextEffects&, SkPackedGlyphID, bool pathOnly);
void writePendingGlyphs(Serializer* serializer);
- bool has_pending_glyphs() const {
- return !fPendingGlyphImages.empty() || !fPendingGlyphPaths.empty();
- }
- SkDiscardableHandleId discardable_handle_id() const { return fDiscardableHandleId; }
+ SkDiscardableHandleId discardableHandleId() const { return fDiscardableHandleId; }
const SkDescriptor& getDeviceDescriptor() {
return *fDeviceDescriptor;
}
@@ -149,8 +151,12 @@ public:
const SkDescriptor& getKeyDescriptor() {
return *fKeyDescriptor;
}
+ const SkGlyph& findGlyph(SkTypeface*, const SkScalerContextEffects&, SkPackedGlyphID);
private:
+ bool hasPendingGlyphs() const {
+ return !fPendingGlyphImages.empty() || !fPendingGlyphPaths.empty();
+ }
void writeGlyphPath(const SkPackedGlyphID& glyphID, Serializer* serializer) const;
// The set of glyphs cached on the remote client.
@@ -171,6 +177,9 @@ public:
// The context built using fDeviceDescriptor
std::unique_ptr<SkScalerContext> fContext;
+ // FallbackTextHelper cases require glyph metrics when analyzing a glyph run, in which case
+ // we cache them here.
+ SkTHashMap<SkPackedGlyphID, SkGlyph> fGlyphMap;
};
SkGlyphCacheState* getOrCreateCache(const SkPaint&, const SkSurfaceProps*, const SkMatrix*,
@@ -206,7 +215,7 @@ public:
// successful, subsequent attempts to delete the same handle are invalid.
virtual bool deleteHandle(SkDiscardableHandleId) = 0;
- virtual void NotifyCacheMiss(CacheMissType) {}
+ virtual void notifyCacheMiss(CacheMissType) {}
};
SkStrikeClient(sk_sp<DiscardableHandleManager>, bool isLogging = true);
diff --git a/src/core/SkTypeface_remote.cpp b/src/core/SkTypeface_remote.cpp
index b5871ded25..472c009dcc 100644
--- a/src/core/SkTypeface_remote.cpp
+++ b/src/core/SkTypeface_remote.cpp
@@ -38,7 +38,7 @@ void SkScalerContextProxy::generateMetrics(SkGlyph* glyph) {
SkDebugf("GlyphCacheMiss generateMetrics: %s\n", this->getRec().dump().c_str());
}
- fDiscardableManager->NotifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphMetrics);
+ fDiscardableManager->notifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphMetrics);
glyph->zeroMetrics();
}
@@ -48,7 +48,7 @@ void SkScalerContextProxy::generateImage(const SkGlyph& glyph) {
SkDebugf("GlyphCacheMiss generateImage: %s\n", this->getRec().dump().c_str());
}
- fDiscardableManager->NotifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphImage);
+ fDiscardableManager->notifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphImage);
}
bool SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
@@ -57,7 +57,7 @@ bool SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
SkDebugf("GlyphCacheMiss generatePath: %s\n", this->getRec().dump().c_str());
}
- fDiscardableManager->NotifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphPath);
+ fDiscardableManager->notifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphPath);
return false;
}
@@ -69,10 +69,10 @@ void SkScalerContextProxy::generateFontMetrics(SkPaint::FontMetrics* metrics) {
SkDEBUGCODE(SkStrikeCache::Dump());
}
- fDiscardableManager->NotifyCacheMiss(SkStrikeClient::CacheMissType::kFontMetrics);
+ fDiscardableManager->notifyCacheMiss(SkStrikeClient::CacheMissType::kFontMetrics);
sk_bzero(metrics, sizeof(*metrics));
}
SkTypefaceProxy* SkScalerContextProxy::getProxyTypeface() const {
return (SkTypefaceProxy*)this->getTypeface();
-} \ No newline at end of file
+}
diff --git a/src/gpu/text/GrAtlasManager.cpp b/src/gpu/text/GrAtlasManager.cpp
index f75224d0bc..ec07429180 100644
--- a/src/gpu/text/GrAtlasManager.cpp
+++ b/src/gpu/text/GrAtlasManager.cpp
@@ -12,15 +12,16 @@
#include "GrGlyphCache.h"
#include "GrProxyProvider.h"
-void GrAtlasManager::ComputeAtlasLimits(const GrCaps* caps, float maxTextureBytes,
- int* maxDim, int* minDim, int* maxPlot, int* minPlot) {
+void GrAtlasManager::ComputeAtlasLimits(int maxTextureSize, size_t maxTextureBytes, int* maxDim,
+ int* minDim, int* maxPlot, int* minPlot) {
SkASSERT(maxDim && minDim && maxPlot && minPlot);
// Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
- int log2MaxTextureSize = SkPrevLog2(caps->maxTextureSize());
+ int log2MaxTextureSize = SkPrevLog2(maxTextureSize);
int log2MaxDim = 9;
+ static const size_t kOne = 1u;
for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
- int maxDimTmp = 1 << log2MaxDim;
- int minDimTmp = 1 << (log2MaxDim - 1);
+ size_t maxDimTmp = kOne << log2MaxDim;
+ size_t minDimTmp = kOne << (log2MaxDim - 1);
if (maxDimTmp * minDimTmp * 4 >= maxTextureBytes) {
break;
@@ -45,7 +46,8 @@ GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrGlyphCache* gly
fCaps = fProxyProvider->refCaps();
int maxDim, minDim, maxPlot, minPlot;
- ComputeAtlasLimits(fCaps.get(), maxTextureBytes, &maxDim, &minDim, &maxPlot, &minPlot);
+ ComputeAtlasLimits(fCaps->maxTextureSize(), maxTextureBytes, &maxDim, &minDim, &maxPlot,
+ &minPlot);
// Setup default atlas configs. The A8 atlas uses maxDim for both width and height, as the A8
// format is already very compact.
diff --git a/src/gpu/text/GrAtlasManager.h b/src/gpu/text/GrAtlasManager.h
index 18ccfd096f..38e2781d4d 100644
--- a/src/gpu/text/GrAtlasManager.h
+++ b/src/gpu/text/GrAtlasManager.h
@@ -43,8 +43,8 @@ public:
SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
- static void ComputeAtlasLimits(const GrCaps* caps, float maxTextureBytes,
- int* maxDim, int* minDim, int* maxPlot, int* minPlot);
+ static void ComputeAtlasLimits(int maxTextureSize, size_t maxTextureBytes, int* maxDim,
+ int* minDim, int* maxPlot, int* minPlot);
void freeAll();
diff --git a/src/gpu/text/GrGlyphCache.cpp b/src/gpu/text/GrGlyphCache.cpp
index b564c93c02..f6a18c3271 100644
--- a/src/gpu/text/GrGlyphCache.cpp
+++ b/src/gpu/text/GrGlyphCache.cpp
@@ -5,20 +5,17 @@
* found in the LICENSE file.
*/
+#include "GrGlyphCache.h"
#include "GrAtlasManager.h"
+#include "GrCaps.h"
#include "GrDistanceFieldGenFromVector.h"
-#include "GrGlyphCache.h"
#include "SkAutoMalloc.h"
#include "SkDistanceFieldGen.h"
-GrGlyphCache::GrGlyphCache(const GrCaps* caps, float maxTextureBytes)
- : fPreserveStrike(nullptr)
- , fGlyphSizeLimit(0) {
-
- int maxDim, minDim, maxPlot, minPlot;
- GrAtlasManager::ComputeAtlasLimits(caps, maxTextureBytes, &maxDim, &minDim, &maxPlot, &minPlot);
- fGlyphSizeLimit = minPlot;
+GrGlyphCache::GrGlyphCache(const GrCaps* caps, size_t maxTextureBytes)
+ : fPreserveStrike(nullptr), fGlyphSizeLimit(0) {
+ fGlyphSizeLimit = ComputeGlyphSizeLimit(caps->maxTextureSize(), maxTextureBytes);
}
GrGlyphCache::~GrGlyphCache() {
@@ -40,6 +37,13 @@ void GrGlyphCache::freeAll() {
fCache.rewind();
}
+SkScalar GrGlyphCache::ComputeGlyphSizeLimit(int maxTextureSize, size_t maxTextureBytes) {
+ int maxDim, minDim, maxPlot, minPlot;
+ GrAtlasManager::ComputeAtlasLimits(maxTextureSize, maxTextureBytes, &maxDim, &minDim, &maxPlot,
+ &minPlot);
+ return minPlot;
+}
+
void GrGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) {
GrGlyphCache* glyphCache = reinterpret_cast<GrGlyphCache*>(ptr);
diff --git a/src/gpu/text/GrGlyphCache.h b/src/gpu/text/GrGlyphCache.h
index cff309501d..7e707ec64c 100644
--- a/src/gpu/text/GrGlyphCache.h
+++ b/src/gpu/text/GrGlyphCache.h
@@ -108,7 +108,7 @@ private:
*/
class GrGlyphCache {
public:
- GrGlyphCache(const GrCaps* caps, float maxTextureBytes);
+ GrGlyphCache(const GrCaps* caps, size_t maxTextureBytes);
~GrGlyphCache();
SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
@@ -130,6 +130,7 @@ public:
void freeAll();
static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
+ static SkScalar ComputeGlyphSizeLimit(int maxTextureSize, size_t maxTextureBytes);
private:
sk_sp<GrTextStrike> generateStrike(const SkGlyphCache* cache) {
diff --git a/src/gpu/text/GrTextContext.cpp b/src/gpu/text/GrTextContext.cpp
index 033506f220..9864d027de 100644
--- a/src/gpu/text/GrTextContext.cpp
+++ b/src/gpu/text/GrTextContext.cpp
@@ -380,7 +380,8 @@ void GrTextContext::DrawBmpPosTextAsPaths(GrTextBlob* blob, int runIndex,
// setup our std paint, in hopes of getting hits in the cache
SkPaint pathPaint(origPaint);
SkScalar matrixScale = pathPaint.setupForAsPaths();
- FallbackTextHelper fallbackTextHelper(viewMatrix, origPaint, glyphCache, matrixScale);
+ FallbackTextHelper fallbackTextHelper(viewMatrix, origPaint, glyphCache->getGlyphSizeLimit(),
+ matrixScale);
// Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
pathPaint.setStyle(SkPaint::kFill_Style);
@@ -596,7 +597,8 @@ void GrTextContext::drawDFPosText(GrTextBlob* blob, int runIndex,
blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(),
paint.skPaint().isAntiAlias(), hasWCoord);
- FallbackTextHelper fallbackTextHelper(viewMatrix, paint, glyphCache, textRatio);
+ FallbackTextHelper fallbackTextHelper(viewMatrix, paint, glyphCache->getGlyphSizeLimit(),
+ textRatio);
sk_sp<GrTextStrike> currStrike;
@@ -672,6 +674,8 @@ void GrTextContext::DfAppendGlyph(GrTextBlob* blob, int runIndex,
void GrTextContext::FallbackTextHelper::appendText(const SkGlyph& glyph, int count,
const char* text, SkPoint glyphPos) {
SkScalar maxDim = SkTMax(glyph.fWidth, glyph.fHeight)*fTextRatio;
+ if (SkScalarNearlyZero(maxDim)) return;
+
if (!fUseTransformedFallback) {
if (!fViewMatrix.isScaleTranslate() || maxDim*fMaxScale > fMaxTextSize) {
fUseTransformedFallback = true;
@@ -706,18 +710,12 @@ void GrTextContext::FallbackTextHelper::drawText(GrTextBlob* blob, int runIndex,
SkPaint::GlyphCacheProc glyphCacheProc =
SkPaint::GetGlyphCacheProc(skPaint.getTextEncoding(), true);
SkColor textColor = paint.filteredPremulColor();
+
SkScalar textRatio = SK_Scalar1;
- if (fUseTransformedFallback) {
- // Set up paint and matrix to scale glyphs
- SkPaint scaledPaint(skPaint);
- scaledPaint.setTextSize(fTransformedFallbackTextSize);
- textRatio = fTextSize / fTransformedFallbackTextSize;
- cache = blob->setupCache(runIndex, props, scalerContextFlags, scaledPaint,
- &SkMatrix::I());
- } else {
- cache = blob->setupCache(runIndex, props, scalerContextFlags, paint,
- &fViewMatrix);
- }
+ SkPaint fallbackPaint(skPaint);
+ SkMatrix matrix = fViewMatrix;
+ this->initializeForDraw(&fallbackPaint, &textRatio, &matrix);
+ cache = blob->setupCache(runIndex, props, scalerContextFlags, fallbackPaint, &matrix);
sk_sp<GrTextStrike> currStrike;
const char* text = fFallbackTxt.begin();
@@ -738,6 +736,15 @@ void GrTextContext::FallbackTextHelper::drawText(GrTextBlob* blob, int runIndex,
}
}
+void GrTextContext::FallbackTextHelper::initializeForDraw(SkPaint* paint, SkScalar* textRatio,
+ SkMatrix* matrix) const {
+ if (!fUseTransformedFallback) return;
+
+ paint->setTextSize(fTransformedFallbackTextSize);
+ *textRatio = fTextSize / fTransformedFallbackTextSize;
+ *matrix = SkMatrix::I();
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
#if GR_TEST_UTILS
diff --git a/src/gpu/text/GrTextContext.h b/src/gpu/text/GrTextContext.h
index 7d31d84a05..478d4c42b6 100644
--- a/src/gpu/text/GrTextContext.h
+++ b/src/gpu/text/GrTextContext.h
@@ -69,21 +69,18 @@ public:
SkScalar* textRatio,
SkScalerContextFlags* flags);
-private:
- GrTextContext(const Options& options);
-
class FallbackTextHelper {
public:
FallbackTextHelper(const SkMatrix& viewMatrix,
const SkPaint& pathPaint,
- const GrGlyphCache* glyphCache,
+ SkScalar maxTextSize,
SkScalar textRatio)
- : fViewMatrix(viewMatrix)
- , fTextSize(pathPaint.getTextSize())
- , fMaxTextSize(glyphCache->getGlyphSizeLimit())
- , fTextRatio(textRatio)
- , fTransformedFallbackTextSize(fMaxTextSize)
- , fUseTransformedFallback(false) {
+ : fViewMatrix(viewMatrix)
+ , fTextSize(pathPaint.getTextSize())
+ , fMaxTextSize(maxTextSize)
+ , fTextRatio(textRatio)
+ , fTransformedFallbackTextSize(fMaxTextSize)
+ , fUseTransformedFallback(false) {
fMaxScale = viewMatrix.getMaxScale();
}
@@ -91,6 +88,9 @@ private:
void drawText(GrTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&,
const GrTextUtils::Paint&, SkScalerContextFlags);
+ void initializeForDraw(SkPaint* paint, SkScalar* textRatio, SkMatrix* matrix) const;
+ const SkTDArray<char>& fallbackText() const { return fFallbackTxt; }
+
private:
SkTDArray<char> fFallbackTxt;
SkTDArray<SkPoint> fFallbackPos;
@@ -104,6 +104,9 @@ private:
bool fUseTransformedFallback;
};
+private:
+ GrTextContext(const Options& options);
+
// sets up the descriptor on the blob and returns a detached cache. Client must attach
static SkColor ComputeCanonicalColor(const SkPaint&, bool lcd);
// Determines if we need to use fake gamma (and contrast boost):
diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp
index 013eead9db..af73158eb9 100644
--- a/tests/SkRemoteGlyphCacheTest.cpp
+++ b/tests/SkRemoteGlyphCacheTest.cpp
@@ -37,7 +37,7 @@ public:
// Client implementation.
bool deleteHandle(SkDiscardableHandleId id) override { return id <= fLastDeletedHandleId; }
- void NotifyCacheMiss(SkStrikeClient::CacheMissType type) override { fCacheMissCount[type]++; }
+ void notifyCacheMiss(SkStrikeClient::CacheMissType type) override { fCacheMissCount[type]++; }
void unlockAll() { fLockedHandles.reset(); }
void unlockAndDeleteAll() {
@@ -47,6 +47,12 @@ public:
const SkTHashSet<SkDiscardableHandleId>& lockedHandles() const { return fLockedHandles; }
SkDiscardableHandleId handleCount() { return fNextHandleId; }
int cacheMissCount(SkStrikeClient::CacheMissType type) { return fCacheMissCount[type]; }
+ bool hasCacheMiss() const {
+ for (uint32_t i = 0; i <= SkStrikeClient::CacheMissType::kLast; ++i) {
+ if (fCacheMissCount[i] > 0) return true;
+ }
+ return false;
+ }
private:
SkDiscardableHandleId fNextHandleId = 0u;
@@ -87,6 +93,8 @@ sk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) {
SkTextBlobCacheDiffCanvas::Settings MakeSettings(GrContext* context) {
SkTextBlobCacheDiffCanvas::Settings settings;
settings.fContextSupportsDistanceFieldText = context->supportsDistanceFieldText();
+ settings.fMaxTextureSize = context->maxTextureSize();
+ settings.fMaxTextureBytes = GrContextOptions().fGlyphCacheTextureMaximumBytes;
return settings;
}
@@ -149,6 +157,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization, repor
SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext());
SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext());
COMPARE_BLOBS(expected, actual, reporter);
+ REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
// Must unlock everything on termination, otherwise valgrind complains about memory leaks.
discardableManager->unlockAndDeleteAll();
@@ -316,6 +325,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath, reporter,
SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext());
SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext());
COMPARE_BLOBS(expected, actual, reporter);
+ REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
SkStrikeCache::Validate();
// Must unlock everything on termination, otherwise valgrind complains about memory leaks.
@@ -362,6 +372,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, c
SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext(), &matrix);
SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext(), &matrix);
COMPARE_BLOBS(expected, actual, reporter);
+ REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
SkStrikeCache::Validate();
// Must unlock everything on termination, otherwise valgrind complains about memory leaks.