const ScaledImageFragment* ImageDecodingStore::overwriteAndLockCache(const ImageFrameGenerator* generator, const ScaledImageFragment* cachedImage, PassOwnPtr<ScaledImageFragment> newImage) { OwnPtr<ImageDecoder> trash; const ScaledImageFragment* newCachedImage = 0; { MutexLocker lock(m_mutex); cachedImage->bitmap().unlockPixels(); CacheMap::iterator iter = m_cacheMap.find(std::make_pair(generator, cachedImage->scaledSize())); ASSERT(iter != m_cacheMap.end()); CacheEntry* cacheEntry = iter->value.get(); ASSERT(cacheEntry->useCount() == 1); ASSERT(!cacheEntry->cachedImage()->isComplete()); bool isNewImageDiscardable = DiscardablePixelRef::isDiscardable(newImage->bitmap().pixelRef()); if (cacheEntry->isDiscardable() && !isNewImageDiscardable) incrementMemoryUsage(cacheEntry->memoryUsageInBytes()); else if (!cacheEntry->isDiscardable() && isNewImageDiscardable) decrementMemoryUsage(cacheEntry->memoryUsageInBytes()); trash = cacheEntry->overwriteCachedImage(newImage); newCachedImage = cacheEntry->cachedImage(); // Lock the underlying SkBitmap to prevent it from being purged. newCachedImage->bitmap().lockPixels(); } return newCachedImage; }
bool ImageDecodingStore::lockCache(const ImageFrameGenerator* generator, const SkISize& scaledSize, CacheCondition condition, const ScaledImageFragment** cachedImage, ImageDecoder** decoder) { ASSERT(cachedImage); CacheEntry* cacheEntry = 0; Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete; { MutexLocker lock(m_mutex); CacheMap::iterator iter = m_cacheMap.find(std::make_pair(generator, scaledSize)); if (iter == m_cacheMap.end()) return false; cacheEntry = iter->value.get(); ScaledImageFragment* image = cacheEntry->cachedImage(); if (condition == CacheMustBeComplete && !image->isComplete()) return false; // Incomplete cache entry cannot be used more than once. ASSERT(image->isComplete() || !cacheEntry->useCount()); image->bitmap().lockPixels(); if (image->bitmap().getPixels()) { // Increment use count such that it doesn't get evicted. cacheEntry->incrementUseCount(); // Complete cache entry doesn't have a decoder. ASSERT(!image->isComplete() || !cacheEntry->cachedDecoder()); if (decoder) *decoder = cacheEntry->cachedDecoder(); *cachedImage = image; } else { image->bitmap().unlockPixels(); removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete); removeFromCacheListInternal(cacheEntriesToDelete); return false; } } return true; }