diff options
author | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-08-08 20:43:22 +0000 |
---|---|---|
committer | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-08-08 20:43:22 +0000 |
commit | ae0891cf0a0d8210caee404ebc844510244a41cf (patch) | |
tree | 40c90d3884a5e2a57dd2e0ca5f44a86d8f1effcd /core/SkBitmapHeap.cpp | |
parent | 8511c203ae88fe01798744aa259aafc12da7bae8 (diff) | |
download | src-ae0891cf0a0d8210caee404ebc844510244a41cf.tar.gz |
Make SkGPipe use SkBitmapHeap.
In the single process (or hypothetical cross process/shared address
space) mode, SkGPipe now uses SkBitmapHeap instead of SharedHeap.
Still need to use the shared heap for shaders as well as for cross
process.
TEST=PipeTest
Review URL: https://codereview.appspot.com/6461059
git-svn-id: http://skia.googlecode.com/svn/trunk/src@5008 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'core/SkBitmapHeap.cpp')
-rw-r--r-- | core/SkBitmapHeap.cpp | 123 |
1 files changed, 100 insertions, 23 deletions
diff --git a/core/SkBitmapHeap.cpp b/core/SkBitmapHeap.cpp index 7cff8eaa..924264bf 100644 --- a/core/SkBitmapHeap.cpp +++ b/core/SkBitmapHeap.cpp @@ -55,9 +55,26 @@ SkBitmapHeap::SkBitmapHeap(ExternalStorage* storage, int32_t preferredSize) , fPreferredCount(preferredSize) , fOwnerCount(IGNORE_OWNERS) , fBytesAllocated(0) { + SkSafeRef(storage); } SkBitmapHeap::~SkBitmapHeap() { + SkDEBUGCODE( + for (int i = 0; i < fStorage.count(); i++) { + bool unused = false; + for (int j = 0; j < fUnusedSlots.count(); j++) { + if (fUnusedSlots[j] == fStorage[i]->fSlot) { + unused = true; + break; + } + } + if (!unused) { + fBytesAllocated -= fStorage[i]->fBytesAllocated; + } + } + fBytesAllocated -= (fStorage.count() * sizeof(SkBitmapHeapEntry)); + ) + SkASSERT(0 == fBytesAllocated); fStorage.deleteAll(); SkSafeUnref(fExternalStorage); } @@ -132,15 +149,53 @@ SkBitmapHeapEntry* SkBitmapHeap::findEntryToReplace(const SkBitmap& replacement) return NULL; } -int SkBitmapHeap::findInLookupTable(const SkBitmap& bitmap, SkBitmapHeapEntry** entry) { - LookupEntry indexEntry; - indexEntry.fGenerationId = bitmap.getGenerationID(); - indexEntry.fPixelOffset = bitmap.pixelRefOffset(); - indexEntry.fWidth = bitmap.width(); - indexEntry.fHeight = bitmap.height(); +size_t SkBitmapHeap::freeMemoryIfPossible(size_t bytesToFree) { + if (UNLIMITED_SIZE == fPreferredCount) { + return 0; + } + SkBitmapHeapEntry* iter = fLeastRecentlyUsed; + size_t origBytesAllocated = fBytesAllocated; + // Purge starting from LRU until a non-evictable bitmap is found or until + // everything is evicted. + while (iter && 0 == iter->fRefCount) { + SkBitmapHeapEntry* next = iter->fMoreRecentlyUsed; + this->removeEntryFromLookupTable(*iter); + // Free the pixel memory. removeEntryFromLookupTable already reduced + // fBytesAllocated properly. + iter->fBitmap.reset(); + // Add to list of unused slots which can be reused in the future. + fUnusedSlots.push(iter->fSlot); + // Remove its LRU pointers, so that it does not pretend it is already in + // the list the next time it is used. + iter->fMoreRecentlyUsed = iter->fLessRecentlyUsed = NULL; + iter = next; + if (origBytesAllocated - fBytesAllocated >= bytesToFree) { + break; + } + } + + if (fLeastRecentlyUsed != iter) { + // There was at least one eviction. + fLeastRecentlyUsed = iter; + if (NULL == fLeastRecentlyUsed) { + // Everything was evicted + fMostRecentlyUsed = NULL; + fBytesAllocated -= (fStorage.count() * sizeof(SkBitmapHeapEntry)); + fStorage.deleteAll(); + fUnusedSlots.reset(); + SkASSERT(0 == fBytesAllocated); + } else { + fLeastRecentlyUsed->fLessRecentlyUsed = NULL; + } + } + + return origBytesAllocated - fBytesAllocated; +} + +int SkBitmapHeap::findInLookupTable(const LookupEntry& indexEntry, SkBitmapHeapEntry** entry) { int index = SkTSearch<const LookupEntry>(fLookupTable.begin(), - fLookupTable.count(), - indexEntry, sizeof(indexEntry)); + fLookupTable.count(), + indexEntry, sizeof(indexEntry)); if (index < 0) { // insert ourselves into the bitmapIndex @@ -174,9 +229,25 @@ bool SkBitmapHeap::copyBitmap(const SkBitmap& originalBitmap, SkBitmap& copiedBi return true; } +int SkBitmapHeap::removeEntryFromLookupTable(const SkBitmapHeapEntry& entry) { + // remove the bitmap index for the deleted entry + SkDEBUGCODE(int count = fLookupTable.count();) + // FIXME: If copying bitmaps retained the generation ID, we could + // just grab the generation ID from entry.fBitmap + LookupEntry key(entry.fBitmap, entry.fGenerationID); + int index = this->findInLookupTable(key, NULL); + // Verify that findInLookupTable found an existing entry rather than adding + // a new entry to the lookup table. + SkASSERT(count == fLookupTable.count()); + + fLookupTable.remove(index); + fBytesAllocated -= entry.fBytesAllocated; + return index; +} + int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { SkBitmapHeapEntry* entry = NULL; - int searchIndex = this->findInLookupTable(originalBitmap, &entry); + int searchIndex = this->findInLookupTable(LookupEntry(originalBitmap), &entry); // check to see if we already had a copy of the bitmap in the heap if (entry) { @@ -195,13 +266,7 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { entry = this->findEntryToReplace(originalBitmap); // we found an entry to evict if (entry) { - // remove the bitmap index for the deleted entry - SkDEBUGCODE(int count = fLookupTable.count();) - int index = findInLookupTable(entry->fBitmap, NULL); - SkASSERT(count == fLookupTable.count()); - - fLookupTable.remove(index); - fBytesAllocated -= entry->fBytesAllocated; + int index = this->removeEntryFromLookupTable(*entry); // update the current search index now that we have removed one if (index < searchIndex) { @@ -212,10 +277,16 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { // if we didn't have an entry yet we need to create one if (!entry) { - entry = SkNEW(SkBitmapHeapEntry); - fStorage.append(1, &entry); - entry->fSlot = fStorage.count() - 1; - fBytesAllocated += sizeof(SkBitmapHeapEntry); + if (fPreferredCount != UNLIMITED_SIZE && fUnusedSlots.count() > 0) { + int slot; + fUnusedSlots.pop(&slot); + entry = fStorage[slot]; + } else { + entry = SkNEW(SkBitmapHeapEntry); + fStorage.append(1, &entry); + entry->fSlot = fStorage.count() - 1; + fBytesAllocated += sizeof(SkBitmapHeapEntry); + } } // create a copy of the bitmap @@ -230,9 +301,13 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { if (!copySucceeded) { // delete the index fLookupTable.remove(searchIndex); - // free the slot - fStorage.remove(entry->fSlot); - SkDELETE(entry); + // If entry is the last slot in storage, it is safe to delete it. + if (fStorage.count() - 1 == entry->fSlot) { + // free the slot + fStorage.remove(entry->fSlot); + fBytesAllocated -= sizeof(SkBitmapHeapEntry); + SkDELETE(entry); + } return INVALID_SLOT; } @@ -248,6 +323,8 @@ int32_t SkBitmapHeap::insert(const SkBitmap& originalBitmap) { // add the bytes from this entry to the total count fBytesAllocated += entry->fBytesAllocated; + entry->fGenerationID = originalBitmap.getGenerationID(); + if (fOwnerCount != IGNORE_OWNERS) { entry->addReferences(fOwnerCount); } |