| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkGlyphCache.h" | 8 #include "SkGlyphCache.h" |
| 9 #include "SkGlyphCache_Globals.h" | 9 #include "SkGlyphCache_Globals.h" |
| 10 #include "SkGraphics.h" | 10 #include "SkGraphics.h" |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 /////////////////////////////////////////////////////////////////////////////// | 418 /////////////////////////////////////////////////////////////////////////////// |
| 419 | 419 |
| 420 #include "SkThread.h" | 420 #include "SkThread.h" |
| 421 | 421 |
| 422 size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) { | 422 size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) { |
| 423 static const size_t minLimit = 256 * 1024; | 423 static const size_t minLimit = 256 * 1024; |
| 424 if (newLimit < minLimit) { | 424 if (newLimit < minLimit) { |
| 425 newLimit = minLimit; | 425 newLimit = minLimit; |
| 426 } | 426 } |
| 427 | 427 |
| 428 SkAutoMutexAcquire ac(fMutex); | 428 SkScopedLock<Lock> ac(*fMutex); |
| 429 | 429 |
| 430 size_t prevLimit = fCacheSizeLimit; | 430 size_t prevLimit = fCacheSizeLimit; |
| 431 fCacheSizeLimit = newLimit; | 431 fCacheSizeLimit = newLimit; |
| 432 this->internalPurge(); | 432 this->internalPurge(); |
| 433 return prevLimit; | 433 return prevLimit; |
| 434 } | 434 } |
| 435 | 435 |
| 436 int SkGlyphCache_Globals::setCacheCountLimit(int newCount) { | 436 int SkGlyphCache_Globals::setCacheCountLimit(int newCount) { |
| 437 if (newCount < 0) { | 437 if (newCount < 0) { |
| 438 newCount = 0; | 438 newCount = 0; |
| 439 } | 439 } |
| 440 | 440 |
| 441 SkAutoMutexAcquire ac(fMutex); | 441 SkScopedLock<Lock> ac(*fMutex); |
| 442 | 442 |
| 443 int prevCount = fCacheCountLimit; | 443 int prevCount = fCacheCountLimit; |
| 444 fCacheCountLimit = newCount; | 444 fCacheCountLimit = newCount; |
| 445 this->internalPurge(); | 445 this->internalPurge(); |
| 446 return prevCount; | 446 return prevCount; |
| 447 } | 447 } |
| 448 | 448 |
| 449 void SkGlyphCache_Globals::purgeAll() { | 449 void SkGlyphCache_Globals::purgeAll() { |
| 450 SkAutoMutexAcquire ac(fMutex); | 450 SkScopedLock<Lock> ac(*fMutex); |
| 451 this->internalPurge(fTotalMemoryUsed); | 451 this->internalPurge(fTotalMemoryUsed); |
| 452 } | 452 } |
| 453 | 453 |
| 454 /* This guy calls the visitor from within the mutext lock, so the visitor | 454 /* This guy calls the visitor from within the mutext lock, so the visitor |
| 455 cannot: | 455 cannot: |
| 456 - take too much time | 456 - take too much time |
| 457 - try to acquire the mutext again | 457 - try to acquire the mutext again |
| 458 - call a fontscaler (which might call into the cache) | 458 - call a fontscaler (which might call into the cache) |
| 459 */ | 459 */ |
| 460 SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface, | 460 SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface, |
| 461 const SkDescriptor* desc, | 461 const SkDescriptor* desc, |
| 462 bool (*proc)(const SkGlyphCache*, void*), | 462 bool (*proc)(const SkGlyphCache*, void*), |
| 463 void* context) { | 463 void* context) { |
| 464 if (!typeface) { | 464 if (!typeface) { |
| 465 typeface = SkTypeface::GetDefaultTypeface(); | 465 typeface = SkTypeface::GetDefaultTypeface(); |
| 466 } | 466 } |
| 467 SkASSERT(desc); | 467 SkASSERT(desc); |
| 468 | 468 |
| 469 SkGlyphCache_Globals& globals = getGlobals(); | 469 SkGlyphCache_Globals& globals = getGlobals(); |
| 470 SkAutoMutexAcquire ac(globals.fMutex); | |
| 471 SkGlyphCache* cache; | 470 SkGlyphCache* cache; |
| 472 bool insideMutex = true; | |
| 473 | 471 |
| 474 globals.validate(); | 472 { |
| 473 SkScopedLock<SkGlyphCache_Globals::Lock> ac(*globals.fMutex); |
| 475 | 474 |
| 476 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext)
{ | 475 globals.validate(); |
| 477 if (cache->fDesc->equals(*desc)) { | 476 |
| 478 globals.internalDetachCache(cache); | 477 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fN
ext) { |
| 479 goto FOUND_IT; | 478 if (cache->fDesc->equals(*desc)) { |
| 479 globals.internalDetachCache(cache); |
| 480 if (!proc(cache, context)) { |
| 481 globals.internalAttachCacheToHead(cache); |
| 482 cache = NULL; |
| 483 } |
| 484 return cache; |
| 485 } |
| 480 } | 486 } |
| 481 } | 487 } |
| 482 | 488 |
| 483 /* Release the mutex now, before we create a new entry (which might have | |
| 484 side-effects like trying to access the cache/mutex (yikes!) | |
| 485 */ | |
| 486 ac.release(); // release the mutex now | |
| 487 insideMutex = false; // can't use globals anymore | |
| 488 | |
| 489 // Check if we can create a scaler-context before creating the glyphcache. | 489 // Check if we can create a scaler-context before creating the glyphcache. |
| 490 // If not, we may have exhausted OS/font resources, so try purging the | 490 // If not, we may have exhausted OS/font resources, so try purging the |
| 491 // cache once and try again. | 491 // cache once and try again. |
| 492 { | 492 { |
| 493 // pass true the first time, to notice if the scalercontext failed, | 493 // pass true the first time, to notice if the scalercontext failed, |
| 494 // so we can try the purge. | 494 // so we can try the purge. |
| 495 SkScalerContext* ctx = typeface->createScalerContext(desc, true); | 495 SkScalerContext* ctx = typeface->createScalerContext(desc, true); |
| 496 if (!ctx) { | 496 if (!ctx) { |
| 497 getSharedGlobals().purgeAll(); | 497 getSharedGlobals().purgeAll(); |
| 498 ctx = typeface->createScalerContext(desc, false); | 498 ctx = typeface->createScalerContext(desc, false); |
| 499 SkASSERT(ctx); | 499 SkASSERT(ctx); |
| 500 } | 500 } |
| 501 cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx)); | 501 cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx)); |
| 502 } | 502 } |
| 503 | 503 |
| 504 FOUND_IT: | |
| 505 | |
| 506 AutoValidate av(cache); | 504 AutoValidate av(cache); |
| 507 | 505 |
| 508 if (!proc(cache, context)) { // need to reattach | 506 if (!proc(cache, context)) { // need to reattach |
| 509 if (insideMutex) { | 507 globals.attachCacheToHead(cache); |
| 510 globals.internalAttachCacheToHead(cache); | |
| 511 } else { | |
| 512 globals.attachCacheToHead(cache); | |
| 513 } | |
| 514 cache = NULL; | 508 cache = NULL; |
| 515 } | 509 } |
| 516 return cache; | 510 return cache; |
| 517 } | 511 } |
| 518 | 512 |
| 519 void SkGlyphCache::AttachCache(SkGlyphCache* cache) { | 513 void SkGlyphCache::AttachCache(SkGlyphCache* cache) { |
| 520 SkASSERT(cache); | 514 SkASSERT(cache); |
| 521 SkASSERT(cache->fNext == NULL); | 515 SkASSERT(cache->fNext == NULL); |
| 522 | 516 |
| 523 getGlobals().attachCacheToHead(cache); | 517 getGlobals().attachCacheToHead(cache); |
| 524 } | 518 } |
| 525 | 519 |
| 526 void SkGlyphCache::Dump() { | 520 void SkGlyphCache::Dump() { |
| 527 SkGlyphCache_Globals& globals = getGlobals(); | 521 SkGlyphCache_Globals& globals = getGlobals(); |
| 528 SkAutoMutexAcquire ac(globals.fMutex); | 522 SkScopedLock<SkGlyphCache_Globals::Lock> ac(*globals.fMutex); |
| 529 SkGlyphCache* cache; | 523 SkGlyphCache* cache; |
| 530 | 524 |
| 531 globals.validate(); | 525 globals.validate(); |
| 532 | 526 |
| 533 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", | 527 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", |
| 534 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); | 528 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); |
| 535 | 529 |
| 536 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | 530 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS |
| 537 int hitCount = 0; | 531 int hitCount = 0; |
| 538 int missCount = 0; | 532 int missCount = 0; |
| 539 #endif | 533 #endif |
| 540 | 534 |
| 541 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext)
{ | 535 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext)
{ |
| 542 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | 536 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS |
| 543 hitCount += cache->fHashHitCount; | 537 hitCount += cache->fHashHitCount; |
| 544 missCount += cache->fHashMissCount; | 538 missCount += cache->fHashMissCount; |
| 545 #endif | 539 #endif |
| 546 cache->dump(); | 540 cache->dump(); |
| 547 } | 541 } |
| 548 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | 542 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS |
| 549 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount)); | 543 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount)); |
| 550 #endif | 544 #endif |
| 551 } | 545 } |
| 552 | 546 |
| 553 /////////////////////////////////////////////////////////////////////////////// | 547 /////////////////////////////////////////////////////////////////////////////// |
| 554 | 548 |
| 555 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { | 549 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { |
| 556 SkAutoMutexAcquire ac(fMutex); | 550 SkScopedLock<Lock> ac(*fMutex); |
| 557 | 551 |
| 558 this->validate(); | 552 this->validate(); |
| 559 cache->validate(); | 553 cache->validate(); |
| 560 | 554 |
| 561 this->internalAttachCacheToHead(cache); | 555 this->internalAttachCacheToHead(cache); |
| 562 this->internalPurge(); | 556 this->internalPurge(); |
| 563 } | 557 } |
| 564 | 558 |
| 565 SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const { | 559 SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const { |
| 566 SkGlyphCache* cache = fHead; | 560 SkGlyphCache* cache = fHead; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 return tls ? tls->getCacheSizeLimit() : 0; | 721 return tls ? tls->getCacheSizeLimit() : 0; |
| 728 } | 722 } |
| 729 | 723 |
| 730 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { | 724 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { |
| 731 if (0 == bytes) { | 725 if (0 == bytes) { |
| 732 SkGlyphCache_Globals::DeleteTLS(); | 726 SkGlyphCache_Globals::DeleteTLS(); |
| 733 } else { | 727 } else { |
| 734 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); | 728 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); |
| 735 } | 729 } |
| 736 } | 730 } |
| OLD | NEW |