Add back tight scaler context managment

Release the scaler context after the differences are calculated so
that the type faces can recoup resources.

Change-Id: Ieb65dafdeee6f84d0739399d58f8d8d53ad7364e
Reviewed-on: https://skia-review.googlesource.com/149233
Reviewed-by: Khusal Sagar <khushalsagar@chromium.org>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2018-08-24 11:43:58 -04:00 committed by Skia Commit-Bot
parent 4f28d76c01
commit ee2a3f36dc
2 changed files with 54 additions and 34 deletions

View File

@ -429,6 +429,33 @@ void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
fLockedDescs.clear();
}
SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState(
std::unique_ptr<SkDescriptor> keyDescriptor, uint32_t discardableHandleId)
: fKeyDescriptor(std::move(keyDescriptor))
, fDiscardableHandleId(discardableHandleId) {
SkASSERT(fKeyDescriptor);
}
SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default;
void SkStrikeServer::SkGlyphCacheState::ensureScalerContext(
const SkPaint& paint,
const SkSurfaceProps* props,
const SkMatrix* matrix,
SkScalerContextFlags flags,
SkScalerContextEffects* effects) {
if (fContext == nullptr || fDeviceDescriptor == nullptr) {
SkScalerContextRec deviceRec;
SkScalerContext::MakeRecAndEffects(paint, props, matrix, flags, &deviceRec, effects, true);
auto deviceDesc = SkScalerContext::DescriptorGivenRecAndEffects(deviceRec, *effects);
auto* tf = paint.getTypeface();
fContext = tf->createScalerContext(*effects, deviceDesc.get(), false);
fIsSubpixel = fContext->isSubpixel();
fAxisAlignmentForHText = fContext->computeAxisAlignmentForHText();
fDeviceDescriptor = std::move(deviceDesc);
}
}
SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
const SkPaint& paint,
const SkSurfaceProps* props,
@ -444,22 +471,26 @@ SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
if (fLockedDescs.find(keyDesc.get()) != fLockedDescs.end()) {
auto it = fRemoteGlyphStateMap.find(keyDesc.get());
SkASSERT(it != fRemoteGlyphStateMap.end());
return it->second.get();
SkGlyphCacheState* cache = it->second.get();
cache->ensureScalerContext(paint, props, matrix, flags, effects);
return cache;
}
// Try to lock.
auto it = fRemoteGlyphStateMap.find(keyDesc.get());
if (it != fRemoteGlyphStateMap.end()) {
SkGlyphCacheState* cache = it->second.get();
#ifdef SK_DEBUG
SkScalerContextRec deviceRec;
SkScalerContext::MakeRecAndEffects(paint, props, matrix, flags, &deviceRec, effects, true);
auto deviceDesc = SkScalerContext::DescriptorGivenRecAndEffects(deviceRec, *effects);
SkASSERT(it->second->getDeviceDescriptor() == *deviceDesc);
SkASSERT(cache->getDeviceDescriptor() == *deviceDesc);
#endif
bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
if (locked) {
fLockedDescs.insert(it->first);
return it->second.get();
cache->ensureScalerContext(paint, props, matrix, flags, effects);
return cache;
}
// If the lock failed, the entry was deleted on the client. Remove our
@ -475,39 +506,18 @@ SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
tf->isFixedPitch());
}
SkScalerContextRec deviceRec;
SkScalerContext::MakeRecAndEffects(paint, props, matrix, flags, &deviceRec, effects, true);
auto deviceDesc = SkScalerContext::DescriptorGivenRecAndEffects(deviceRec, *effects);
// Create a new cache state and insert it into the map.
auto* keyDescPtr = keyDesc.get();
auto newHandle = fDiscardableHandleManager->createHandle();
auto scalerContext = tf->createScalerContext(*effects, deviceDesc.get(), false);
auto cacheState = skstd::make_unique<SkGlyphCacheState>(
std::move(deviceDesc), std::move(keyDesc), newHandle, std::move(scalerContext));
auto cacheState = skstd::make_unique<SkGlyphCacheState>(std::move(keyDesc), newHandle);
auto* cacheStatePtr = cacheState.get();
fLockedDescs.insert(keyDescPtr);
fRemoteGlyphStateMap[keyDescPtr] = std::move(cacheState);
cacheStatePtr->ensureScalerContext(paint, props, matrix, flags, effects);
return cacheStatePtr;
}
SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState(std::unique_ptr<SkDescriptor> deviceDescriptor,
std::unique_ptr<SkDescriptor>
keyDescriptor,
uint32_t discardableHandleId,
std::unique_ptr<SkScalerContext> context)
: fDeviceDescriptor(std::move(deviceDescriptor))
, fKeyDescriptor(std::move(keyDescriptor))
, fDiscardableHandleId(discardableHandleId)
, fContext(std::move(context))
, fIsSubpixel(fContext->isSubpixel())
, fAxisAlignmentForHText(fContext->computeAxisAlignmentForHText()) {
SkASSERT(fDeviceDescriptor);
SkASSERT(fKeyDescriptor);
}
SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default;
void SkStrikeServer::SkGlyphCacheState::addGlyph(SkPackedGlyphID glyph, bool asPath) {
auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages;
auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages;
@ -525,6 +535,8 @@ void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serialize
// TODO(khushalsagar): Write a strike only if it has any pending glyphs.
serializer->emplace<bool>(this->hasPendingGlyphs());
if (!this->hasPendingGlyphs()) {
// See comment below for reset.
fContext.reset();
return;
}
@ -591,6 +603,10 @@ void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serialize
writeGlyphPath(glyphID, serializer);
}
fPendingGlyphPaths.clear();
// Note that we reset the context after serializing pending glyphs since we
// don't want to extend the lifetime of the typeface.
fContext.reset();
}
const SkGlyph& SkStrikeServer::SkGlyphCacheState::findGlyph(SkPackedGlyphID glyphID) {

View File

@ -149,10 +149,9 @@ public:
// Methods used internally in skia ------------------------------------------
class SkGlyphCacheState {
public:
SkGlyphCacheState(std::unique_ptr<SkDescriptor> deviceDescriptor,
std::unique_ptr<SkDescriptor> keyDescriptor,
SkDiscardableHandleId discardableHandleId,
std::unique_ptr<SkScalerContext> scalerContext);
// N.B. SkGlyphCacheState is not valid until ensureScalerContext is called.
SkGlyphCacheState(std::unique_ptr<SkDescriptor> keyDescriptor,
SkDiscardableHandleId discardableHandleId);
~SkGlyphCacheState();
void addGlyph(SkPackedGlyphID, bool pathOnly);
@ -168,6 +167,11 @@ public:
return *fKeyDescriptor;
}
const SkGlyph& findGlyph(SkPackedGlyphID);
void ensureScalerContext(const SkPaint& paint,
const SkSurfaceProps* props,
const SkMatrix* matrix,
SkScalerContextFlags flags,
SkScalerContextEffects* effects);
private:
bool hasPendingGlyphs() const {
@ -191,9 +195,9 @@ public:
std::unique_ptr<SkDescriptor> fKeyDescriptor;
const SkDiscardableHandleId fDiscardableHandleId;
// The context built using fDeviceDescriptor
const std::unique_ptr<SkScalerContext> fContext;
const bool fIsSubpixel;
const SkAxisAlignment fAxisAlignmentForHText;
std::unique_ptr<SkScalerContext> fContext;
bool fIsSubpixel = true;
SkAxisAlignment fAxisAlignmentForHText;
// FallbackTextHelper cases require glyph metrics when analyzing a glyph run, in which case
// we cache them here.