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:
parent
4f28d76c01
commit
ee2a3f36dc
@ -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) {
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user