Purge GrTextBlobCache entries on SkTextBlob deletion
Similar to the SkImage purge mechanism. Change-Id: I0b7fb1bad507a3c7f30a4f7514bedd894d1748ac Reviewed-on: https://skia-review.googlesource.com/9631 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
b66b42f174
commit
4a01ac9e41
@ -9,6 +9,7 @@
|
||||
#define SkTextBlob_DEFINED
|
||||
|
||||
#include "../private/SkTemplates.h"
|
||||
#include "../private/SkAtomics.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkString.h"
|
||||
#include "SkRefCnt.h"
|
||||
@ -75,11 +76,19 @@ private:
|
||||
|
||||
static unsigned ScalarsPerGlyph(GlyphPositioning pos);
|
||||
|
||||
// Call when this blob is part of the key to a cache entry. This allows the cache
|
||||
// to know automatically those entries can be purged when this SkTextBlob is deleted.
|
||||
void notifyAddedToCache() const {
|
||||
fAddedToCache.store(true);
|
||||
}
|
||||
|
||||
friend class GrTextBlobCache;
|
||||
friend class SkTextBlobBuilder;
|
||||
friend class SkTextBlobRunIterator;
|
||||
|
||||
const SkRect fBounds;
|
||||
const uint32_t fUniqueID;
|
||||
const SkRect fBounds;
|
||||
const uint32_t fUniqueID;
|
||||
mutable SkAtomic<bool> fAddedToCache;
|
||||
|
||||
SkDEBUGCODE(size_t fStorageSize;)
|
||||
|
||||
|
@ -11,6 +11,10 @@
|
||||
#include "SkTypeface.h"
|
||||
#include "SkWriteBuffer.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "text/GrTextBlobCache.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(fmalita): replace with SkFont.
|
||||
@ -286,10 +290,16 @@ static int32_t next_id() {
|
||||
|
||||
SkTextBlob::SkTextBlob(const SkRect& bounds)
|
||||
: fBounds(bounds)
|
||||
, fUniqueID(next_id()) {
|
||||
}
|
||||
, fUniqueID(next_id())
|
||||
, fAddedToCache(false) {}
|
||||
|
||||
SkTextBlob::~SkTextBlob() {
|
||||
#if SK_SUPPORT_GPU
|
||||
if (fAddedToCache.load()) {
|
||||
GrTextBlobCache::PostPurgeBlobMessage(fUniqueID);
|
||||
}
|
||||
#endif
|
||||
|
||||
const auto* run = RunRecord::First(this);
|
||||
do {
|
||||
const auto* nextRun = RunRecord::Next(run);
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include "GrTextBlobCache.h"
|
||||
|
||||
DECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage)
|
||||
|
||||
GrTextBlobCache::~GrTextBlobCache() {
|
||||
SkDEBUGCODE(this->freeAll();)
|
||||
}
|
||||
@ -24,3 +26,8 @@ void GrTextBlobCache::freeAll() {
|
||||
SkASSERT(fPool.isEmpty());
|
||||
SkASSERT(fBlobList.isEmpty());
|
||||
}
|
||||
|
||||
void GrTextBlobCache::PostPurgeBlobMessage(uint32_t id) {
|
||||
SkASSERT(id != SK_InvalidGenID);
|
||||
SkMessageBus<PurgeBlobMessage>::Post(PurgeBlobMessage({id}));
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define GrTextBlobCache_DEFINED
|
||||
|
||||
#include "GrAtlasTextContext.h"
|
||||
#include "SkMessageBus.h"
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkTArray.h"
|
||||
#include "SkTextBlobRunIterator.h"
|
||||
@ -50,6 +51,7 @@ public:
|
||||
sk_sp<GrAtlasTextBlob> cacheBlob(this->makeBlob(blob));
|
||||
cacheBlob->setupKey(key, blurRec, paint);
|
||||
this->add(cacheBlob);
|
||||
blob->notifyAddedToCache();
|
||||
return cacheBlob;
|
||||
}
|
||||
|
||||
@ -94,6 +96,12 @@ public:
|
||||
this->checkPurge();
|
||||
}
|
||||
|
||||
struct PurgeBlobMessage {
|
||||
uint32_t fID;
|
||||
};
|
||||
|
||||
static void PostPurgeBlobMessage(uint32_t);
|
||||
|
||||
private:
|
||||
using BitmapBlobList = SkTInternalLList<GrAtlasTextBlob>;
|
||||
|
||||
@ -159,7 +167,30 @@ private:
|
||||
}
|
||||
|
||||
void checkPurge(GrAtlasTextBlob* blob = nullptr) {
|
||||
// If we are overbudget, then unref until we are below budget again
|
||||
// First, purge all stale blob IDs.
|
||||
{
|
||||
// TODO: tweak poll to allow mem-movable arrays, and update.
|
||||
SkSTArray<128, PurgeBlobMessage, false> msgs;
|
||||
fPurgeBlobInbox.poll(&msgs);
|
||||
|
||||
for (const auto& msg : msgs) {
|
||||
auto* idEntry = fBlobIDCache.find(msg.fID);
|
||||
if (!idEntry) {
|
||||
// no cache entries for id
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove all blob entries from the LRU list
|
||||
for (const auto& blob : idEntry->fBlobs) {
|
||||
fBlobList.remove(blob.get());
|
||||
}
|
||||
|
||||
// drop the idEntry itself (unrefs all blobs)
|
||||
fBlobIDCache.remove(msg.fID);
|
||||
}
|
||||
}
|
||||
|
||||
// If we are still overbudget, then unref until we are below budget again
|
||||
if (fPool.size() > fBudget) {
|
||||
BitmapBlobList::Iter iter;
|
||||
iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
|
||||
@ -197,6 +228,7 @@ private:
|
||||
PFOverBudgetCB fCallback;
|
||||
void* fData;
|
||||
size_t fBudget;
|
||||
SkMessageBus<PurgeBlobMessage>::Inbox fPurgeBlobInbox;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user