| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2013 Google Inc. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "SkThread.h" | |
| 9 #include "SkPurgeableImageCache.h" | |
| 10 #include "SkPurgeableMemoryBlock.h" | |
| 11 | |
| 12 #ifdef SK_DEBUG | |
| 13 #include "SkTSearch.h" | |
| 14 #endif | |
| 15 | |
| 16 SK_DEFINE_INST_COUNT(SkPurgeableImageCache) | |
| 17 SK_DECLARE_STATIC_MUTEX(gPurgeableImageMutex); | |
| 18 | |
| 19 SkImageCache* SkPurgeableImageCache::Create() { | |
| 20 if (!SkPurgeableMemoryBlock::IsSupported()) { | |
| 21 return NULL; | |
| 22 } | |
| 23 SkAutoMutexAcquire ac(&gPurgeableImageMutex); | |
| 24 static SkPurgeableImageCache gCache; | |
| 25 gCache.ref(); | |
| 26 return &gCache; | |
| 27 } | |
| 28 | |
| 29 SkPurgeableImageCache::SkPurgeableImageCache() {} | |
| 30 | |
| 31 #ifdef SK_DEBUG | |
| 32 SkPurgeableImageCache::~SkPurgeableImageCache() { | |
| 33 SkASSERT(fRecs.count() == 0); | |
| 34 } | |
| 35 #endif | |
| 36 | |
| 37 | |
| 38 void* SkPurgeableImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) { | |
| 39 SkAutoMutexAcquire ac(&gPurgeableImageMutex); | |
| 40 | |
| 41 SkPurgeableMemoryBlock* block = SkPurgeableMemoryBlock::Create(bytes); | |
| 42 if (NULL == block) { | |
| 43 return NULL; | |
| 44 } | |
| 45 | |
| 46 SkPurgeableMemoryBlock::PinResult pinResult; | |
| 47 void* data = block->pin(&pinResult); | |
| 48 if (NULL == data) { | |
| 49 SkDELETE(block); | |
| 50 return NULL; | |
| 51 } | |
| 52 | |
| 53 SkASSERT(ID != NULL); | |
| 54 *ID = reinterpret_cast<intptr_t>(block); | |
| 55 #ifdef SK_DEBUG | |
| 56 // Insert into the array of all recs: | |
| 57 int index = this->findRec(*ID); | |
| 58 SkASSERT(index < 0); | |
| 59 fRecs.insert(~index, 1, ID); | |
| 60 #endif | |
| 61 return data; | |
| 62 } | |
| 63 | |
| 64 void* SkPurgeableImageCache::pinCache(intptr_t ID, SkImageCache::DataStatus* sta
tus) { | |
| 65 SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); | |
| 66 SkAutoMutexAcquire ac(&gPurgeableImageMutex); | |
| 67 | |
| 68 SkASSERT(this->findRec(ID) >= 0); | |
| 69 SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID
); | |
| 70 SkPurgeableMemoryBlock::PinResult pinResult; | |
| 71 void* data = block->pin(&pinResult); | |
| 72 if (NULL == data) { | |
| 73 this->removeRec(ID); | |
| 74 return NULL; | |
| 75 } | |
| 76 | |
| 77 switch (pinResult) { | |
| 78 case SkPurgeableMemoryBlock::kRetained_PinResult: | |
| 79 *status = SkImageCache::kRetained_DataStatus; | |
| 80 break; | |
| 81 | |
| 82 case SkPurgeableMemoryBlock::kUninitialized_PinResult: | |
| 83 *status = SkImageCache::kUninitialized_DataStatus; | |
| 84 break; | |
| 85 | |
| 86 default: | |
| 87 // Invalid value. Treat as a failure to pin. | |
| 88 SkASSERT(false); | |
| 89 this->removeRec(ID); | |
| 90 return NULL; | |
| 91 } | |
| 92 | |
| 93 return data; | |
| 94 } | |
| 95 | |
| 96 void SkPurgeableImageCache::releaseCache(intptr_t ID) { | |
| 97 SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); | |
| 98 SkAutoMutexAcquire ac(&gPurgeableImageMutex); | |
| 99 | |
| 100 SkASSERT(this->findRec(ID) >= 0); | |
| 101 SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID
); | |
| 102 block->unpin(); | |
| 103 } | |
| 104 | |
| 105 void SkPurgeableImageCache::throwAwayCache(intptr_t ID) { | |
| 106 SkASSERT(ID != SkImageCache::UNINITIALIZED_ID); | |
| 107 SkAutoMutexAcquire ac(&gPurgeableImageMutex); | |
| 108 | |
| 109 this->removeRec(ID); | |
| 110 } | |
| 111 | |
| 112 #ifdef SK_DEBUG | |
| 113 SkImageCache::MemoryStatus SkPurgeableImageCache::getMemoryStatus(intptr_t ID) c
onst { | |
| 114 SkAutoMutexAcquire ac(&gPurgeableImageMutex); | |
| 115 if (SkImageCache::UNINITIALIZED_ID == ID || this->findRec(ID) < 0) { | |
| 116 return SkImageCache::kFreed_MemoryStatus; | |
| 117 } | |
| 118 | |
| 119 SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID
); | |
| 120 if (block->isPinned()) { | |
| 121 return SkImageCache::kPinned_MemoryStatus; | |
| 122 } | |
| 123 return SkImageCache::kUnpinned_MemoryStatus; | |
| 124 } | |
| 125 | |
| 126 void SkPurgeableImageCache::purgeAllUnpinnedCaches() { | |
| 127 SkAutoMutexAcquire ac(&gPurgeableImageMutex); | |
| 128 if (SkPurgeableMemoryBlock::PlatformSupportsPurgingAllUnpinnedBlocks()) { | |
| 129 SkPurgeableMemoryBlock::PurgeAllUnpinnedBlocks(); | |
| 130 } else { | |
| 131 // Go through the blocks, and purge them individually. | |
| 132 // Rather than deleting the blocks, which would interfere with further c
alls, purge them | |
| 133 // and keep them around. | |
| 134 for (int i = 0; i < fRecs.count(); i++) { | |
| 135 SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBl
ock*>(fRecs[i]); | |
| 136 if (!block->isPinned()) { | |
| 137 if (!block->purge()) { | |
| 138 // FIXME: This should be more meaningful (which one, etc...) | |
| 139 SkDebugf("Failed to purge\n"); | |
| 140 } | |
| 141 } | |
| 142 } | |
| 143 } | |
| 144 } | |
| 145 | |
| 146 int SkPurgeableImageCache::findRec(intptr_t rec) const { | |
| 147 return SkTSearch(fRecs.begin(), fRecs.count(), rec, sizeof(intptr_t)); | |
| 148 } | |
| 149 #endif | |
| 150 | |
| 151 void SkPurgeableImageCache::removeRec(intptr_t ID) { | |
| 152 #ifdef SK_DEBUG | |
| 153 int index = this->findRec(ID); | |
| 154 SkASSERT(index >= 0); | |
| 155 fRecs.remove(index); | |
| 156 #endif | |
| 157 SkPurgeableMemoryBlock* block = reinterpret_cast<SkPurgeableMemoryBlock*>(ID
); | |
| 158 SkASSERT(!block->isPinned()); | |
| 159 SkDELETE(block); | |
| 160 } | |
| OLD | NEW |