Update GrTextBlobCache for DDL

Although, theoretically, we could update the DDLs to maintain pointers to the GrMemoryPools being used by their GrAtlasTextBlobs this method seems simpler.

Change-Id: I4835284630b9cd29eb78cf25bcdfe5c56974a8cb
Reviewed-on: https://skia-review.googlesource.com/107345
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Robert Phillips 2018-02-14 18:54:01 -05:00 committed by Skia Commit-Bot
parent d5811b2d44
commit 303cd58870
5 changed files with 37 additions and 15 deletions

View File

@ -299,7 +299,8 @@ bool GrContext::init(const GrContextOptions& options) {
allowMultitexturing);
this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache);
fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this, this->uniqueID()));
fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB,
this, this->uniqueID(), SkToBool(fGpu)));
if (options.fExecutor) {
fTaskGroup = skstd::make_unique<SkTaskGroup>(*options.fExecutor);

View File

@ -27,7 +27,12 @@ sk_sp<GrAtlasTextBlob> GrAtlasTextBlob::Make(GrMemoryPool* pool, int glyphCount,
glyphCount * sizeof(GrGlyph**) +
sizeof(GrAtlasTextBlob::Run) * runCount;
void* allocation = pool->allocate(size);
void* allocation;
if (pool) {
allocation = pool->allocate(size);
} else {
allocation = ::operator new (size);
}
if (CACHE_SANITY_CHECK) {
sk_bzero(allocation, size);
}

View File

@ -52,7 +52,7 @@ public:
class VertexRegenerator;
static sk_sp<GrAtlasTextBlob> Make(GrMemoryPool* pool, int glyphCount, int runCount);
static sk_sp<GrAtlasTextBlob> Make(GrMemoryPool*, int glyphCount, int runCount);
/**
* We currently force regeneration of a blob if old or new matrix differ in having perspective.
@ -104,7 +104,11 @@ public:
void operator delete(void* p) {
GrAtlasTextBlob* blob = reinterpret_cast<GrAtlasTextBlob*>(p);
blob->fPool->release(p);
if (blob->fPool) {
blob->fPool->release(p);
} else {
::operator delete(p);
}
}
void* operator new(size_t) {
SK_ABORT("All blobs are created by placement new.");
@ -521,7 +525,7 @@ private:
char* fVertices;
GrGlyph** fGlyphs;
Run* fRuns;
GrMemoryPool* fPool;
GrMemoryPool* fPool; // this will be null when DDLs are being recorded
SkMaskFilterBase::BlurRec fBlurRec;
StrokeInfo fStrokeInfo;
Key fKey;

View File

@ -10,7 +10,8 @@
DECLARE_SKMESSAGEBUS_MESSAGE(GrTextBlobCache::PurgeBlobMessage)
GrTextBlobCache::~GrTextBlobCache() {
SkDEBUGCODE(this->freeAll();)
this->freeAll();
delete fPool;
}
void GrTextBlobCache::freeAll() {
@ -23,7 +24,7 @@ void GrTextBlobCache::freeAll() {
fBlobIDCache.reset();
// There should be no allocations in the memory pool at this point
SkASSERT(fPool.isEmpty());
SkASSERT(!fPool || fPool->isEmpty());
SkASSERT(fBlobList.isEmpty());
}
@ -53,16 +54,26 @@ void GrTextBlobCache::purgeStaleBlobs() {
}
}
bool GrTextBlobCache::overBudget() const {
if (fPool) {
return fPool->size() > fBudget;
}
// When DDLs are being recorded no GrAtlasTextBlob will be deleted so the cache budget is
// somewhat meaningless.
return false;
}
void GrTextBlobCache::checkPurge(GrAtlasTextBlob* blob) {
// First, purge all stale blob IDs.
this->purgeStaleBlobs();
// If we are still over budget, then unref until we are below budget again
if (fPool.size() > fBudget) {
if (this->overBudget()) {
BitmapBlobList::Iter iter;
iter.init(fBlobList, BitmapBlobList::Iter::kTail_IterStart);
GrAtlasTextBlob* lruBlob = nullptr;
while (fPool.size() > fBudget && (lruBlob = iter.get()) && lruBlob != blob) {
while (this->overBudget() && (lruBlob = iter.get()) && lruBlob != blob) {
// Backup the iterator before removing and unrefing the blob
iter.prev();
@ -77,7 +88,7 @@ void GrTextBlobCache::checkPurge(GrAtlasTextBlob* blob) {
}
#ifdef SPEW_BUDGET_MESSAGE
if (fPool.size() > fBudget) {
if (this->overBudget()) {
SkDebugf("Single textblob is larger than our whole budget");
}
#endif

View File

@ -23,8 +23,8 @@ public:
*/
typedef void (*PFOverBudgetCB)(void* data);
GrTextBlobCache(PFOverBudgetCB cb, void* data, uint32_t uniqueID)
: fPool(0u, kMinGrowthSize)
GrTextBlobCache(PFOverBudgetCB cb, void* data, uint32_t uniqueID, bool usePool)
: fPool(usePool ? new GrMemoryPool(0u, kMinGrowthSize) : nullptr)
, fCallback(cb)
, fData(data)
, fBudget(kDefaultBudget)
@ -36,14 +36,14 @@ public:
// creates an uncached blob
sk_sp<GrAtlasTextBlob> makeBlob(int glyphCount, int runCount) {
return GrAtlasTextBlob::Make(&fPool, glyphCount, runCount);
return GrAtlasTextBlob::Make(fPool, glyphCount, runCount);
}
sk_sp<GrAtlasTextBlob> makeBlob(const SkTextBlob* blob) {
int glyphCount = 0;
int runCount = 0;
BlobGlyphCount(&glyphCount, &runCount, blob);
return GrAtlasTextBlob::Make(&fPool, glyphCount, runCount);
return GrAtlasTextBlob::Make(fPool, glyphCount, runCount);
}
sk_sp<GrAtlasTextBlob> makeCachedBlob(const SkTextBlob* blob,
@ -171,10 +171,11 @@ private:
}
void checkPurge(GrAtlasTextBlob* blob = nullptr);
bool overBudget() const;
static const int kMinGrowthSize = 1 << 16;
static const int kDefaultBudget = 1 << 22;
GrMemoryPool fPool;
GrMemoryPool* fPool;
BitmapBlobList fBlobList;
SkTHashMap<uint32_t, BlobIDCacheEntry> fBlobIDCache;
PFOverBudgetCB fCallback;