add counting to Globals, and refactor some for clarity
BUG= Review URL: https://codereview.chromium.org/24447003 git-svn-id: http://skia.googlecode.com/svn/trunk@11484 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
97b4b67ee7
commit
baed71fbfe
@ -101,6 +101,7 @@
|
|||||||
'<(skia_src_path)/core/SkGeometry.cpp',
|
'<(skia_src_path)/core/SkGeometry.cpp',
|
||||||
'<(skia_src_path)/core/SkGlyphCache.cpp',
|
'<(skia_src_path)/core/SkGlyphCache.cpp',
|
||||||
'<(skia_src_path)/core/SkGlyphCache.h',
|
'<(skia_src_path)/core/SkGlyphCache.h',
|
||||||
|
'<(skia_src_path)/core/SkGlyphCache_Globals.h',
|
||||||
'<(skia_src_path)/core/SkGraphics.cpp',
|
'<(skia_src_path)/core/SkGraphics.cpp',
|
||||||
'<(skia_src_path)/core/SkInstCnt.cpp',
|
'<(skia_src_path)/core/SkInstCnt.cpp',
|
||||||
'<(skia_src_path)/core/SkImageFilter.cpp',
|
'<(skia_src_path)/core/SkImageFilter.cpp',
|
||||||
|
@ -53,6 +53,25 @@ public:
|
|||||||
*/
|
*/
|
||||||
static size_t GetFontCacheUsed();
|
static size_t GetFontCacheUsed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of entries in the font cache.
|
||||||
|
* A cache "entry" is associated with each typeface + pointSize + matrix.
|
||||||
|
*/
|
||||||
|
static int GetFontCacheCountUsed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current limit to the number of entries in the font cache.
|
||||||
|
* A cache "entry" is associated with each typeface + pointSize + matrix.
|
||||||
|
*/
|
||||||
|
static int GetFontCacheCountLimit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the limit to the number of entries in the font cache, and return
|
||||||
|
* the previous value. If this new value is lower than the previous,
|
||||||
|
* it will automatically try to purge entries to meet the new limit.
|
||||||
|
*/
|
||||||
|
static int SetFontCacheCountLimit(int count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For debugging purposes, this will attempt to purge the font cache. It
|
* For debugging purposes, this will attempt to purge the font cache. It
|
||||||
* does not change the limit, but will cause subsequent font measures and
|
* does not change the limit, but will cause subsequent font measures and
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "SkGlyphCache.h"
|
#include "SkGlyphCache.h"
|
||||||
|
#include "SkGlyphCache_Globals.h"
|
||||||
#include "SkGraphics.h"
|
#include "SkGraphics.h"
|
||||||
#include "SkPaint.h"
|
#include "SkPaint.h"
|
||||||
#include "SkPath.h"
|
#include "SkPath.h"
|
||||||
@ -20,6 +21,20 @@
|
|||||||
|
|
||||||
bool gSkSuppressFontCachePurgeSpew;
|
bool gSkSuppressFontCachePurgeSpew;
|
||||||
|
|
||||||
|
// Returns the shared globals
|
||||||
|
static SkGlyphCache_Globals& getSharedGlobals() {
|
||||||
|
// we leak this, so we don't incur any shutdown cost of the destructor
|
||||||
|
static SkGlyphCache_Globals* gGlobals = SkNEW_ARGS(SkGlyphCache_Globals,
|
||||||
|
(SkGlyphCache_Globals::kYes_UseMutex));
|
||||||
|
return *gGlobals;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the TLS globals (if set), or the shared globals
|
||||||
|
static SkGlyphCache_Globals& getGlobals() {
|
||||||
|
SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
|
||||||
|
return tls ? *tls : getSharedGlobals();
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef RECORD_HASH_EFFICIENCY
|
#ifdef RECORD_HASH_EFFICIENCY
|
||||||
@ -397,108 +412,38 @@ void SkGlyphCache::invokeAndRemoveAuxProcs() {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SK_DEFAULT_FONT_CACHE_LIMIT
|
|
||||||
#define SK_DEFAULT_FONT_CACHE_LIMIT (2 * 1024 * 1024)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "SkThread.h"
|
#include "SkThread.h"
|
||||||
|
|
||||||
class SkGlyphCache_Globals {
|
size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) {
|
||||||
public:
|
|
||||||
enum UseMutex {
|
|
||||||
kNo_UseMutex, // thread-local cache
|
|
||||||
kYes_UseMutex // shared cache
|
|
||||||
};
|
|
||||||
|
|
||||||
SkGlyphCache_Globals(UseMutex um) {
|
|
||||||
fHead = NULL;
|
|
||||||
fTotalMemoryUsed = 0;
|
|
||||||
fFontCacheLimit = SK_DEFAULT_FONT_CACHE_LIMIT;
|
|
||||||
fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
~SkGlyphCache_Globals() {
|
|
||||||
SkGlyphCache* cache = fHead;
|
|
||||||
while (cache) {
|
|
||||||
SkGlyphCache* next = cache->fNext;
|
|
||||||
SkDELETE(cache);
|
|
||||||
cache = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkDELETE(fMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
SkMutex* fMutex;
|
|
||||||
SkGlyphCache* fHead;
|
|
||||||
size_t fTotalMemoryUsed;
|
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
|
||||||
void validate() const;
|
|
||||||
#else
|
|
||||||
void validate() const {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t getFontCacheLimit() const { return fFontCacheLimit; }
|
|
||||||
size_t setFontCacheLimit(size_t limit);
|
|
||||||
void purgeAll(); // does not change budget
|
|
||||||
|
|
||||||
// can return NULL
|
|
||||||
static SkGlyphCache_Globals* FindTLS() {
|
|
||||||
return (SkGlyphCache_Globals*)SkTLS::Find(CreateTLS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static SkGlyphCache_Globals& GetTLS() {
|
|
||||||
return *(SkGlyphCache_Globals*)SkTLS::Get(CreateTLS, DeleteTLS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DeleteTLS() { SkTLS::Delete(CreateTLS); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t fFontCacheLimit;
|
|
||||||
|
|
||||||
static void* CreateTLS() {
|
|
||||||
return SkNEW_ARGS(SkGlyphCache_Globals, (kNo_UseMutex));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DeleteTLS(void* ptr) {
|
|
||||||
SkDELETE((SkGlyphCache_Globals*)ptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) {
|
|
||||||
static const size_t minLimit = 256 * 1024;
|
static const size_t minLimit = 256 * 1024;
|
||||||
if (newLimit < minLimit) {
|
if (newLimit < minLimit) {
|
||||||
newLimit = minLimit;
|
newLimit = minLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t prevLimit = fFontCacheLimit;
|
SkAutoMutexAcquire ac(fMutex);
|
||||||
fFontCacheLimit = newLimit;
|
|
||||||
|
size_t prevLimit = fCacheSizeLimit;
|
||||||
size_t currUsed = fTotalMemoryUsed;
|
fCacheSizeLimit = newLimit;
|
||||||
if (currUsed > newLimit) {
|
this->internalPurge();
|
||||||
SkAutoMutexAcquire ac(fMutex);
|
|
||||||
SkGlyphCache::InternalFreeCache(this, currUsed - newLimit);
|
|
||||||
}
|
|
||||||
return prevLimit;
|
return prevLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SkGlyphCache_Globals::setCacheCountLimit(int newCount) {
|
||||||
|
if (newCount < 0) {
|
||||||
|
newCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkAutoMutexAcquire ac(fMutex);
|
||||||
|
|
||||||
|
int prevCount = fCacheCountLimit;
|
||||||
|
fCacheCountLimit = newCount;
|
||||||
|
this->internalPurge();
|
||||||
|
return prevCount;
|
||||||
|
}
|
||||||
|
|
||||||
void SkGlyphCache_Globals::purgeAll() {
|
void SkGlyphCache_Globals::purgeAll() {
|
||||||
SkAutoMutexAcquire ac(fMutex);
|
SkAutoMutexAcquire ac(fMutex);
|
||||||
SkGlyphCache::InternalFreeCache(this, fTotalMemoryUsed);
|
this->internalPurge(fTotalMemoryUsed);
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the shared globals
|
|
||||||
static SkGlyphCache_Globals& getSharedGlobals() {
|
|
||||||
// we leak this, so we don't incur any shutdown cost of the destructor
|
|
||||||
static SkGlyphCache_Globals* gGlobals = SkNEW_ARGS(SkGlyphCache_Globals,
|
|
||||||
(SkGlyphCache_Globals::kYes_UseMutex));
|
|
||||||
return *gGlobals;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the TLS globals (if set), or the shared globals
|
|
||||||
static SkGlyphCache_Globals& getGlobals() {
|
|
||||||
SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
|
|
||||||
return tls ? *tls : getSharedGlobals();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*),
|
void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*),
|
||||||
@ -509,7 +454,7 @@ void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*),
|
|||||||
|
|
||||||
globals.validate();
|
globals.validate();
|
||||||
|
|
||||||
for (cache = globals.fHead; cache != NULL; cache = cache->fNext) {
|
for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) {
|
||||||
if (proc(cache, context)) {
|
if (proc(cache, context)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -540,9 +485,9 @@ SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface,
|
|||||||
|
|
||||||
globals.validate();
|
globals.validate();
|
||||||
|
|
||||||
for (cache = globals.fHead; cache != NULL; cache = cache->fNext) {
|
for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) {
|
||||||
if (cache->fDesc->equals(*desc)) {
|
if (cache->fDesc->equals(*desc)) {
|
||||||
cache->detach(&globals.fHead);
|
globals.internalDetachCache(cache);
|
||||||
goto FOUND_IT;
|
goto FOUND_IT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -572,16 +517,11 @@ FOUND_IT:
|
|||||||
|
|
||||||
AutoValidate av(cache);
|
AutoValidate av(cache);
|
||||||
|
|
||||||
if (proc(cache, context)) { // stay detached
|
if (!proc(cache, context)) { // need to reattach
|
||||||
if (insideMutex) {
|
if (insideMutex) {
|
||||||
SkASSERT(globals.fTotalMemoryUsed >= cache->fMemoryUsed);
|
globals.internalAttachCacheToHead(cache);
|
||||||
globals.fTotalMemoryUsed -= cache->fMemoryUsed;
|
|
||||||
}
|
|
||||||
} else { // reattach
|
|
||||||
if (insideMutex) {
|
|
||||||
cache->attachToHead(&globals.fHead);
|
|
||||||
} else {
|
} else {
|
||||||
AttachCache(cache);
|
globals.attachCacheToHead(cache);
|
||||||
}
|
}
|
||||||
cache = NULL;
|
cache = NULL;
|
||||||
}
|
}
|
||||||
@ -592,30 +532,23 @@ void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
|
|||||||
SkASSERT(cache);
|
SkASSERT(cache);
|
||||||
SkASSERT(cache->fNext == NULL);
|
SkASSERT(cache->fNext == NULL);
|
||||||
|
|
||||||
SkGlyphCache_Globals& globals = getGlobals();
|
getGlobals().attachCacheToHead(cache);
|
||||||
SkAutoMutexAcquire ac(globals.fMutex);
|
|
||||||
|
|
||||||
globals.validate();
|
|
||||||
cache->validate();
|
|
||||||
|
|
||||||
// if we have a fixed budget for our cache, do a purge here
|
|
||||||
{
|
|
||||||
size_t allocated = globals.fTotalMemoryUsed + cache->fMemoryUsed;
|
|
||||||
size_t budgeted = globals.getFontCacheLimit();
|
|
||||||
if (allocated > budgeted) {
|
|
||||||
(void)InternalFreeCache(&globals, allocated - budgeted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cache->attachToHead(&globals.fHead);
|
|
||||||
globals.fTotalMemoryUsed += cache->fMemoryUsed;
|
|
||||||
|
|
||||||
globals.validate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SkGlyphCache* SkGlyphCache::FindTail(SkGlyphCache* cache) {
|
void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) {
|
||||||
|
SkAutoMutexAcquire ac(fMutex);
|
||||||
|
|
||||||
|
this->validate();
|
||||||
|
cache->validate();
|
||||||
|
|
||||||
|
this->internalAttachCacheToHead(cache);
|
||||||
|
this->internalPurge();
|
||||||
|
}
|
||||||
|
|
||||||
|
SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const {
|
||||||
|
SkGlyphCache* cache = fHead;
|
||||||
if (cache) {
|
if (cache) {
|
||||||
while (cache->fNext) {
|
while (cache->fNext) {
|
||||||
cache = cache->fNext;
|
cache = cache->fNext;
|
||||||
@ -624,63 +557,92 @@ SkGlyphCache* SkGlyphCache::FindTail(SkGlyphCache* cache) {
|
|||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
size_t SkGlyphCache_Globals::internalPurge(size_t minBytesNeeded) {
|
||||||
void SkGlyphCache_Globals::validate() const {
|
this->validate();
|
||||||
size_t computed = 0;
|
|
||||||
|
|
||||||
const SkGlyphCache* head = fHead;
|
size_t bytesNeeded = 0;
|
||||||
while (head != NULL) {
|
if (fTotalMemoryUsed > fCacheSizeLimit) {
|
||||||
computed += head->fMemoryUsed;
|
bytesNeeded = fTotalMemoryUsed - fCacheSizeLimit;
|
||||||
head = head->fNext;
|
}
|
||||||
|
bytesNeeded = SkMax32(bytesNeeded, minBytesNeeded);
|
||||||
|
if (bytesNeeded) {
|
||||||
|
// no small purges!
|
||||||
|
bytesNeeded = SkMax32(bytesNeeded, fTotalMemoryUsed >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fTotalMemoryUsed != computed) {
|
int countNeeded = 0;
|
||||||
printf("total %d, computed %d\n", (int)fTotalMemoryUsed, (int)computed);
|
if (fCacheCount > fCacheCountLimit) {
|
||||||
|
countNeeded = fCacheCount - fCacheCountLimit;
|
||||||
|
// no small purges!
|
||||||
|
countNeeded = SkMax32(countNeeded, fCacheCount >> 2);
|
||||||
}
|
}
|
||||||
SkASSERT(fTotalMemoryUsed == computed);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
size_t SkGlyphCache::InternalFreeCache(SkGlyphCache_Globals* globals,
|
// early exit
|
||||||
size_t bytesNeeded) {
|
if (!countNeeded && !bytesNeeded) {
|
||||||
globals->validate();
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t bytesFreed = 0;
|
size_t bytesFreed = 0;
|
||||||
int count = 0;
|
int countFreed = 0;
|
||||||
|
|
||||||
// don't do any "small" purges
|
// we start at the tail and proceed backwards, as the linklist is in LRU
|
||||||
size_t minToPurge = globals->fTotalMemoryUsed >> 2;
|
// order, with unimportant entries at the tail.
|
||||||
if (bytesNeeded < minToPurge)
|
SkGlyphCache* cache = this->internalGetTail();
|
||||||
bytesNeeded = minToPurge;
|
while (cache != NULL &&
|
||||||
|
(bytesFreed < bytesNeeded || countFreed < countNeeded)) {
|
||||||
SkGlyphCache* cache = FindTail(globals->fHead);
|
|
||||||
while (cache != NULL && bytesFreed < bytesNeeded) {
|
|
||||||
SkGlyphCache* prev = cache->fPrev;
|
SkGlyphCache* prev = cache->fPrev;
|
||||||
bytesFreed += cache->fMemoryUsed;
|
bytesFreed += cache->fMemoryUsed;
|
||||||
|
countFreed += 1;
|
||||||
|
|
||||||
cache->detach(&globals->fHead);
|
this->internalDetachCache(cache);
|
||||||
SkDELETE(cache);
|
SkDELETE(cache);
|
||||||
cache = prev;
|
cache = prev;
|
||||||
count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkASSERT(bytesFreed <= globals->fTotalMemoryUsed);
|
this->validate();
|
||||||
globals->fTotalMemoryUsed -= bytesFreed;
|
|
||||||
globals->validate();
|
|
||||||
|
|
||||||
#ifdef SPEW_PURGE_STATUS
|
#ifdef SPEW_PURGE_STATUS
|
||||||
if (count && !gSkSuppressFontCachePurgeSpew) {
|
if (countFreed && !gSkSuppressFontCachePurgeSpew) {
|
||||||
SkDebugf("purging %dK from font cache [%d entries]\n",
|
SkDebugf("purging %dK from font cache [%d entries]\n",
|
||||||
(int)(bytesFreed >> 10), count);
|
(int)(bytesFreed >> 10), countFreed);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return bytesFreed;
|
return bytesFreed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkGlyphCache_Globals::internalAttachCacheToHead(SkGlyphCache* cache) {
|
||||||
|
SkASSERT(NULL == cache->fPrev && NULL == cache->fNext);
|
||||||
|
if (fHead) {
|
||||||
|
fHead->fPrev = cache;
|
||||||
|
cache->fNext = fHead;
|
||||||
|
}
|
||||||
|
fHead = cache;
|
||||||
|
|
||||||
|
fCacheCount += 1;
|
||||||
|
fTotalMemoryUsed += cache->fMemoryUsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SkGlyphCache_Globals::internalDetachCache(SkGlyphCache* cache) {
|
||||||
|
SkASSERT(fCacheCount > 0);
|
||||||
|
fCacheCount -= 1;
|
||||||
|
fTotalMemoryUsed -= cache->fMemoryUsed;
|
||||||
|
|
||||||
|
if (cache->fPrev) {
|
||||||
|
cache->fPrev->fNext = cache->fNext;
|
||||||
|
} else {
|
||||||
|
fHead = cache->fNext;
|
||||||
|
}
|
||||||
|
if (cache->fNext) {
|
||||||
|
cache->fNext->fPrev = cache->fPrev;
|
||||||
|
}
|
||||||
|
cache->fPrev = cache->fNext = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
|
|
||||||
void SkGlyphCache::validate() const {
|
void SkGlyphCache::validate() const {
|
||||||
#ifdef SK_DEBUG_GLYPH_CACHE
|
#ifdef SK_DEBUG_GLYPH_CACHE
|
||||||
int count = fGlyphArray.count();
|
int count = fGlyphArray.count();
|
||||||
@ -694,6 +656,22 @@ void SkGlyphCache::validate() const {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SkGlyphCache_Globals::validate() const {
|
||||||
|
size_t computedBytes = 0;
|
||||||
|
int computedCount = 0;
|
||||||
|
|
||||||
|
const SkGlyphCache* head = fHead;
|
||||||
|
while (head != NULL) {
|
||||||
|
computedBytes += head->fMemoryUsed;
|
||||||
|
computedCount += 1;
|
||||||
|
head = head->fNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkASSERT(fTotalMemoryUsed == computedBytes);
|
||||||
|
SkASSERT(fCacheCount == computedCount);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -702,15 +680,27 @@ void SkGlyphCache::validate() const {
|
|||||||
#include "SkTypefaceCache.h"
|
#include "SkTypefaceCache.h"
|
||||||
|
|
||||||
size_t SkGraphics::GetFontCacheLimit() {
|
size_t SkGraphics::GetFontCacheLimit() {
|
||||||
return getSharedGlobals().getFontCacheLimit();
|
return getSharedGlobals().getCacheSizeLimit();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SkGraphics::SetFontCacheLimit(size_t bytes) {
|
size_t SkGraphics::SetFontCacheLimit(size_t bytes) {
|
||||||
return getSharedGlobals().setFontCacheLimit(bytes);
|
return getSharedGlobals().setCacheSizeLimit(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SkGraphics::GetFontCacheUsed() {
|
size_t SkGraphics::GetFontCacheUsed() {
|
||||||
return getSharedGlobals().fTotalMemoryUsed;
|
return getSharedGlobals().getTotalMemoryUsed();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkGraphics::GetFontCacheCountLimit() {
|
||||||
|
return getSharedGlobals().getCacheCountLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkGraphics::SetFontCacheCountLimit(int count) {
|
||||||
|
return getSharedGlobals().setCacheCountLimit(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SkGraphics::GetFontCacheCountUsed() {
|
||||||
|
return getSharedGlobals().getCacheCountUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkGraphics::PurgeFontCache() {
|
void SkGraphics::PurgeFontCache() {
|
||||||
@ -720,13 +710,13 @@ void SkGraphics::PurgeFontCache() {
|
|||||||
|
|
||||||
size_t SkGraphics::GetTLSFontCacheLimit() {
|
size_t SkGraphics::GetTLSFontCacheLimit() {
|
||||||
const SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
|
const SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
|
||||||
return tls ? tls->getFontCacheLimit() : 0;
|
return tls ? tls->getCacheSizeLimit() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
|
void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
|
||||||
if (0 == bytes) {
|
if (0 == bytes) {
|
||||||
SkGlyphCache_Globals::DeleteTLS();
|
SkGlyphCache_Globals::DeleteTLS();
|
||||||
} else {
|
} else {
|
||||||
SkGlyphCache_Globals::GetTLS().setFontCacheLimit(bytes);
|
SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,27 +197,6 @@ private:
|
|||||||
SkGlyph* lookupMetrics(uint32_t id, MetricsType);
|
SkGlyph* lookupMetrics(uint32_t id, MetricsType);
|
||||||
static bool DetachProc(const SkGlyphCache*, void*) { return true; }
|
static bool DetachProc(const SkGlyphCache*, void*) { return true; }
|
||||||
|
|
||||||
void detach(SkGlyphCache** head) {
|
|
||||||
if (fPrev) {
|
|
||||||
fPrev->fNext = fNext;
|
|
||||||
} else {
|
|
||||||
*head = fNext;
|
|
||||||
}
|
|
||||||
if (fNext) {
|
|
||||||
fNext->fPrev = fPrev;
|
|
||||||
}
|
|
||||||
fPrev = fNext = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void attachToHead(SkGlyphCache** head) {
|
|
||||||
SkASSERT(NULL == fPrev && NULL == fNext);
|
|
||||||
if (*head) {
|
|
||||||
(*head)->fPrev = this;
|
|
||||||
fNext = *head;
|
|
||||||
}
|
|
||||||
*head = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkGlyphCache* fNext, *fPrev;
|
SkGlyphCache* fNext, *fPrev;
|
||||||
SkDescriptor* fDesc;
|
SkDescriptor* fDesc;
|
||||||
SkScalerContext* fScalerContext;
|
SkScalerContext* fScalerContext;
|
||||||
@ -258,9 +237,6 @@ private:
|
|||||||
AuxProcRec* fAuxProcList;
|
AuxProcRec* fAuxProcList;
|
||||||
void invokeAndRemoveAuxProcs();
|
void invokeAndRemoveAuxProcs();
|
||||||
|
|
||||||
// This relies on the caller to have already acquired the mutex to access the global cache
|
|
||||||
static size_t InternalFreeCache(SkGlyphCache_Globals*, size_t bytesNeeded);
|
|
||||||
|
|
||||||
inline static SkGlyphCache* FindTail(SkGlyphCache* head);
|
inline static SkGlyphCache* FindTail(SkGlyphCache* head);
|
||||||
|
|
||||||
friend class SkGlyphCache_Globals;
|
friend class SkGlyphCache_Globals;
|
||||||
|
122
src/core/SkGlyphCache_Globals.h
Normal file
122
src/core/SkGlyphCache_Globals.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010 Google Inc.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SkGlyphCache_Globals_DEFINED
|
||||||
|
#define SkGlyphCache_Globals_DEFINED
|
||||||
|
|
||||||
|
#include "SkGlyphCache.h"
|
||||||
|
#include "SkTLS.h"
|
||||||
|
|
||||||
|
#ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
|
||||||
|
#define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SK_DEFAULT_FONT_CACHE_LIMIT
|
||||||
|
#define SK_DEFAULT_FONT_CACHE_LIMIT (2 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class SkMutex;
|
||||||
|
|
||||||
|
class SkGlyphCache_Globals {
|
||||||
|
public:
|
||||||
|
enum UseMutex {
|
||||||
|
kNo_UseMutex, // thread-local cache
|
||||||
|
kYes_UseMutex // shared cache
|
||||||
|
};
|
||||||
|
|
||||||
|
SkGlyphCache_Globals(UseMutex um) {
|
||||||
|
fHead = NULL;
|
||||||
|
fTotalMemoryUsed = 0;
|
||||||
|
fCacheSizeLimit = SK_DEFAULT_FONT_CACHE_LIMIT;
|
||||||
|
fCacheCount = 0;
|
||||||
|
fCacheCountLimit = SK_DEFAULT_FONT_CACHE_COUNT_LIMIT;
|
||||||
|
|
||||||
|
fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
~SkGlyphCache_Globals() {
|
||||||
|
SkGlyphCache* cache = fHead;
|
||||||
|
while (cache) {
|
||||||
|
SkGlyphCache* next = cache->fNext;
|
||||||
|
SkDELETE(cache);
|
||||||
|
cache = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkDELETE(fMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkMutex* fMutex;
|
||||||
|
|
||||||
|
SkGlyphCache* internalGetHead() const { return fHead; }
|
||||||
|
SkGlyphCache* internalGetTail() const;
|
||||||
|
|
||||||
|
size_t getTotalMemoryUsed() const { return fTotalMemoryUsed; }
|
||||||
|
int getCacheCountUsed() const { return fCacheCount; }
|
||||||
|
|
||||||
|
#ifdef SK_DEBUG
|
||||||
|
void validate() const;
|
||||||
|
#else
|
||||||
|
void validate() const {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int getCacheCountLimit() const { return fCacheCountLimit; }
|
||||||
|
int setCacheCountLimit(int limit);
|
||||||
|
|
||||||
|
size_t getCacheSizeLimit() const { return fCacheSizeLimit; }
|
||||||
|
size_t setCacheSizeLimit(size_t limit);
|
||||||
|
|
||||||
|
// returns true if this cache is over-budget either due to size limit
|
||||||
|
// or count limit.
|
||||||
|
bool isOverBudget() const {
|
||||||
|
return fCacheCount > fCacheCountLimit ||
|
||||||
|
fTotalMemoryUsed > fCacheSizeLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void purgeAll(); // does not change budget
|
||||||
|
|
||||||
|
// call when a glyphcache is available for caching (i.e. not in use)
|
||||||
|
void attachCacheToHead(SkGlyphCache*);
|
||||||
|
|
||||||
|
// can only be called when the mutex is already held
|
||||||
|
void internalDetachCache(SkGlyphCache*);
|
||||||
|
void internalAttachCacheToHead(SkGlyphCache*);
|
||||||
|
|
||||||
|
// can return NULL
|
||||||
|
static SkGlyphCache_Globals* FindTLS() {
|
||||||
|
return (SkGlyphCache_Globals*)SkTLS::Find(CreateTLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkGlyphCache_Globals& GetTLS() {
|
||||||
|
return *(SkGlyphCache_Globals*)SkTLS::Get(CreateTLS, DeleteTLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DeleteTLS() { SkTLS::Delete(CreateTLS); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SkGlyphCache* fHead;
|
||||||
|
size_t fTotalMemoryUsed;
|
||||||
|
size_t fCacheSizeLimit;
|
||||||
|
int32_t fCacheCountLimit;
|
||||||
|
int32_t fCacheCount;
|
||||||
|
|
||||||
|
// Checkout budgets, modulated by the specified min-bytes-needed-to-purge,
|
||||||
|
// and attempt to purge caches to match.
|
||||||
|
// Returns number of bytes freed.
|
||||||
|
size_t internalPurge(size_t minBytesNeeded = 0);
|
||||||
|
|
||||||
|
static void* CreateTLS() {
|
||||||
|
return SkNEW_ARGS(SkGlyphCache_Globals, (kNo_UseMutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DeleteTLS(void* ptr) {
|
||||||
|
SkDELETE((SkGlyphCache_Globals*)ptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user