Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(130)

Side by Side Diff: Source/core/platform/graphics/chromium/ImageDecodingStore.cpp

Issue 26679003: Move platform/graphics/chromium/* to platform/graphics/ (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: rename fix Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "core/platform/graphics/chromium/ImageDecodingStore.h"
28
29 #include "platform/TraceEvent.h"
30 #include "platform/graphics/ScaledImageFragment.h"
31
32 namespace WebCore {
33
34 namespace {
35
36 // 32MB memory limit for cache.
37 static const size_t defaultCacheLimitInBytes = 32768 * 1024;
38 static ImageDecodingStore* s_instance = 0;
39
40 static void setInstance(ImageDecodingStore* imageDecodingStore)
41 {
42 delete s_instance;
43 s_instance = imageDecodingStore;
44 }
45
46 } // namespace
47
48 ImageDecodingStore::ImageDecodingStore()
49 : m_cacheLimitInBytes(defaultCacheLimitInBytes)
50 , m_memoryUsageInBytes(0)
51 {
52 }
53
54 ImageDecodingStore::~ImageDecodingStore()
55 {
56 #ifndef NDEBUG
57 setCacheLimitInBytes(0);
58 ASSERT(!m_imageCacheMap.size());
59 ASSERT(!m_decoderCacheMap.size());
60 ASSERT(!m_orderedCacheList.size());
61 ASSERT(!m_imageCacheKeyMap.size());
62 ASSERT(!m_decoderCacheKeyMap.size());
63 #endif
64 }
65
66 ImageDecodingStore* ImageDecodingStore::instance()
67 {
68 return s_instance;
69 }
70
71 void ImageDecodingStore::initializeOnce()
72 {
73 setInstance(ImageDecodingStore::create().leakPtr());
74 }
75
76 void ImageDecodingStore::shutdown()
77 {
78 setInstance(0);
79 }
80
81 bool ImageDecodingStore::lockCache(const ImageFrameGenerator* generator, const S kISize& scaledSize, size_t index, const ScaledImageFragment** cachedImage)
82 {
83 ASSERT(cachedImage);
84
85 Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete;
86 {
87 MutexLocker lock(m_mutex);
88 // Public access is restricted to complete images only.
89 ImageCacheMap::iterator iter = m_imageCacheMap.find(ImageCacheEntry::mak eCacheKey(generator, scaledSize, index, ScaledImageFragment::CompleteImage));
90 if (iter == m_imageCacheMap.end())
91 return false;
92 return lockCacheEntryInternal(iter->value.get(), cachedImage, &cacheEntr iesToDelete);
93 }
94 }
95
96 void ImageDecodingStore::unlockCache(const ImageFrameGenerator* generator, const ScaledImageFragment* cachedImage)
97 {
98 MutexLocker lock(m_mutex);
99 cachedImage->bitmap().unlockPixels();
100 ImageCacheMap::iterator iter = m_imageCacheMap.find(ImageCacheEntry::makeCac heKey(generator, cachedImage->scaledSize(), cachedImage->index(), cachedImage->g eneration()));
101 ASSERT(iter != m_imageCacheMap.end());
102
103 CacheEntry* cacheEntry = iter->value.get();
104 cacheEntry->decrementUseCount();
105
106 // Put the entry to the end of list.
107 m_orderedCacheList.remove(cacheEntry);
108 m_orderedCacheList.append(cacheEntry);
109 }
110
111 const ScaledImageFragment* ImageDecodingStore::insertAndLockCache(const ImageFra meGenerator* generator, PassOwnPtr<ScaledImageFragment> image)
112 {
113 // Prune old cache entries to give space for the new one.
114 prune();
115
116 ScaledImageFragment* newImage = image.get();
117 OwnPtr<ImageCacheEntry> newCacheEntry = ImageCacheEntry::createAndUse(genera tor, image);
118 Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete;
119 {
120 MutexLocker lock(m_mutex);
121
122 ImageCacheMap::iterator iter = m_imageCacheMap.find(newCacheEntry->cache Key());
123
124 // It is rare but possible that the key of a new cache entry is found.
125 // This happens if the generation ID of the image object wraps around.
126 // In this case we will try to return the existing cached object and
127 // discard the new cache object.
128 if (iter != m_imageCacheMap.end()) {
129 const ScaledImageFragment* oldImage;
130 if (lockCacheEntryInternal(iter->value.get(), &oldImage, &cacheEntri esToDelete)) {
131 newCacheEntry->decrementUseCount();
132 return oldImage;
133 }
134 }
135
136 // The new image is not locked yet so do it here.
137 newImage->bitmap().lockPixels();
138 insertCacheInternal(newCacheEntry.release(), &m_imageCacheMap, &m_imageC acheKeyMap);
139 }
140 return newImage;
141 }
142
143 bool ImageDecodingStore::lockDecoder(const ImageFrameGenerator* generator, const SkISize& scaledSize, ImageDecoder** decoder)
144 {
145 ASSERT(decoder);
146
147 MutexLocker lock(m_mutex);
148 DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::m akeCacheKey(generator, scaledSize));
149 if (iter == m_decoderCacheMap.end())
150 return false;
151
152 DecoderCacheEntry* cacheEntry = iter->value.get();
153
154 // There can only be one user of a decoder at a time.
155 ASSERT(!cacheEntry->useCount());
156 cacheEntry->incrementUseCount();
157 *decoder = cacheEntry->cachedDecoder();
158 return true;
159 }
160
161 void ImageDecodingStore::unlockDecoder(const ImageFrameGenerator* generator, con st ImageDecoder* decoder)
162 {
163 MutexLocker lock(m_mutex);
164 DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::m akeCacheKey(generator, decoder));
165 ASSERT(iter != m_decoderCacheMap.end());
166
167 CacheEntry* cacheEntry = iter->value.get();
168 cacheEntry->decrementUseCount();
169
170 // Put the entry to the end of list.
171 m_orderedCacheList.remove(cacheEntry);
172 m_orderedCacheList.append(cacheEntry);
173 }
174
175 void ImageDecodingStore::insertDecoder(const ImageFrameGenerator* generator, Pas sOwnPtr<ImageDecoder> decoder, bool isDiscardable)
176 {
177 // Prune old cache entries to give space for the new one.
178 prune();
179
180 OwnPtr<DecoderCacheEntry> newCacheEntry = DecoderCacheEntry::create(generato r, decoder, isDiscardable);
181
182 MutexLocker lock(m_mutex);
183 ASSERT(!m_decoderCacheMap.contains(newCacheEntry->cacheKey()));
184 insertCacheInternal(newCacheEntry.release(), &m_decoderCacheMap, &m_decoderC acheKeyMap);
185 }
186
187 void ImageDecodingStore::removeDecoder(const ImageFrameGenerator* generator, con st ImageDecoder* decoder)
188 {
189 Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete;
190 {
191 MutexLocker lock(m_mutex);
192 DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntr y::makeCacheKey(generator, decoder));
193 ASSERT(iter != m_decoderCacheMap.end());
194
195 CacheEntry* cacheEntry = iter->value.get();
196 ASSERT(cacheEntry->useCount());
197 cacheEntry->decrementUseCount();
198
199 // Delete only one decoder cache entry. Ownership of the cache entry
200 // is transfered to cacheEntriesToDelete such that object can be deleted
201 // outside of the lock.
202 removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete);
203
204 // Remove from LRU list.
205 removeFromCacheListInternal(cacheEntriesToDelete);
206 }
207 }
208
209 bool ImageDecodingStore::isCached(const ImageFrameGenerator* generator, const Sk ISize& scaledSize, size_t index)
210 {
211 MutexLocker lock(m_mutex);
212 ImageCacheMap::iterator iter = m_imageCacheMap.find(ImageCacheEntry::makeCac heKey(generator, scaledSize, index, ScaledImageFragment::CompleteImage));
213 if (iter == m_imageCacheMap.end())
214 return false;
215 return true;
216 }
217
218 void ImageDecodingStore::removeCacheIndexedByGenerator(const ImageFrameGenerator * generator)
219 {
220 Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete;
221 {
222 MutexLocker lock(m_mutex);
223
224 // Remove image cache objects and decoder cache objects associated
225 // with a ImageFrameGenerator.
226 removeCacheIndexedByGeneratorInternal(&m_imageCacheMap, &m_imageCacheKey Map, generator, &cacheEntriesToDelete);
227 removeCacheIndexedByGeneratorInternal(&m_decoderCacheMap, &m_decoderCach eKeyMap, generator, &cacheEntriesToDelete);
228
229 // Remove from LRU list as well.
230 removeFromCacheListInternal(cacheEntriesToDelete);
231 }
232 }
233
234 void ImageDecodingStore::clear()
235 {
236 size_t cacheLimitInBytes;
237 {
238 MutexLocker lock(m_mutex);
239 cacheLimitInBytes = m_cacheLimitInBytes;
240 m_cacheLimitInBytes = 0;
241 }
242
243 prune();
244
245 {
246 MutexLocker lock(m_mutex);
247 m_cacheLimitInBytes = cacheLimitInBytes;
248 }
249 }
250
251 void ImageDecodingStore::setCacheLimitInBytes(size_t cacheLimit)
252 {
253 {
254 MutexLocker lock(m_mutex);
255 m_cacheLimitInBytes = cacheLimit;
256 }
257 prune();
258 }
259
260 size_t ImageDecodingStore::memoryUsageInBytes()
261 {
262 MutexLocker lock(m_mutex);
263 return m_memoryUsageInBytes;
264 }
265
266 int ImageDecodingStore::cacheEntries()
267 {
268 MutexLocker lock(m_mutex);
269 return m_imageCacheMap.size() + m_decoderCacheMap.size();
270 }
271
272 int ImageDecodingStore::imageCacheEntries()
273 {
274 MutexLocker lock(m_mutex);
275 return m_imageCacheMap.size();
276 }
277
278 int ImageDecodingStore::decoderCacheEntries()
279 {
280 MutexLocker lock(m_mutex);
281 return m_decoderCacheMap.size();
282 }
283
284 void ImageDecodingStore::prune()
285 {
286 TRACE_EVENT0("webkit", "ImageDecodingStore::prune");
287
288 Vector<OwnPtr<CacheEntry> > cacheEntriesToDelete;
289 {
290 MutexLocker lock(m_mutex);
291
292 // Head of the list is the least recently used entry.
293 const CacheEntry* cacheEntry = m_orderedCacheList.head();
294
295 // Walk the list of cache entries starting from the least recently used
296 // and then keep them for deletion later.
297 while (cacheEntry && (m_memoryUsageInBytes > m_cacheLimitInBytes || !m_c acheLimitInBytes)) {
298 // Cache is not used; Remove it.
299 if (!cacheEntry->useCount())
300 removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete);
301 cacheEntry = cacheEntry->next();
302 }
303
304 // Remove from cache list as well.
305 removeFromCacheListInternal(cacheEntriesToDelete);
306 }
307 }
308
309 bool ImageDecodingStore::lockCacheEntryInternal(ImageCacheEntry* cacheEntry, con st ScaledImageFragment** cachedImage, Vector<OwnPtr<CacheEntry> >* deletionList)
310 {
311 ScaledImageFragment* image = cacheEntry->cachedImage();
312
313 image->bitmap().lockPixels();
314
315 // Memory for this image entry might be discarded already.
316 // In this case remove the entry.
317 if (!image->bitmap().getPixels()) {
318 image->bitmap().unlockPixels();
319 removeFromCacheInternal(cacheEntry, &m_imageCacheMap, &m_imageCacheKeyMa p, deletionList);
320 removeFromCacheListInternal(*deletionList);
321 return false;
322 }
323 cacheEntry->incrementUseCount();
324 *cachedImage = image;
325 return true;
326 }
327
328 template<class T, class U, class V>
329 void ImageDecodingStore::insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheM ap, V* identifierMap)
330 {
331 // Usage of discardable memory is not counted because we want to use more
332 // than the cache limit allows. Cache limit only applies to non-discardable
333 // objects.
334 if (!cacheEntry->isDiscardable())
335 incrementMemoryUsage(cacheEntry->memoryUsageInBytes());
336
337 // m_orderedCacheList is used to support LRU operations to reorder cache
338 // entries quickly.
339 m_orderedCacheList.append(cacheEntry.get());
340
341 typename U::KeyType key = cacheEntry->cacheKey();
342 typename V::AddResult result = identifierMap->add(cacheEntry->generator(), t ypename V::MappedType());
343 result.iterator->value.add(key);
344 cacheMap->add(key, cacheEntry);
345
346 TRACE_COUNTER1("webkit", "ImageDecodingStoreMemoryUsageBytes", m_memoryUsage InBytes);
347 TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfImages", m_imageCacheMap.si ze());
348 TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfDecoders", m_decoderCacheMa p.size());
349 }
350
351 template<class T, class U, class V>
352 void ImageDecodingStore::removeFromCacheInternal(const T* cacheEntry, U* cacheMa p, V* identifierMap, Vector<OwnPtr<CacheEntry> >* deletionList)
353 {
354 if (!cacheEntry->isDiscardable())
355 decrementMemoryUsage(cacheEntry->memoryUsageInBytes());
356
357 // Remove entry from identifier map.
358 typename V::iterator iter = identifierMap->find(cacheEntry->generator());
359 ASSERT(iter != identifierMap->end());
360 iter->value.remove(cacheEntry->cacheKey());
361 if (!iter->value.size())
362 identifierMap->remove(iter);
363
364 // Remove entry from cache map.
365 deletionList->append(cacheMap->take(cacheEntry->cacheKey()));
366
367 TRACE_COUNTER1("webkit", "ImageDecodingStoreMemoryUsageBytes", m_memoryUsage InBytes);
368 TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfImages", m_imageCacheMap.si ze());
369 TRACE_COUNTER1("webkit", "ImageDecodingStoreNumOfDecoders", m_decoderCacheMa p.size());
370 }
371
372 void ImageDecodingStore::removeFromCacheInternal(const CacheEntry* cacheEntry, V ector<OwnPtr<CacheEntry> >* deletionList)
373 {
374 if (cacheEntry->type() == CacheEntry::TypeImage) {
375 removeFromCacheInternal(static_cast<const ImageCacheEntry*>(cacheEntry), &m_imageCacheMap, &m_imageCacheKeyMap, deletionList);
376 } else if (cacheEntry->type() == CacheEntry::TypeDecoder) {
377 removeFromCacheInternal(static_cast<const DecoderCacheEntry*>(cacheEntry ), &m_decoderCacheMap, &m_decoderCacheKeyMap, deletionList);
378 } else {
379 ASSERT(false);
380 }
381 }
382
383 template<class U, class V>
384 void ImageDecodingStore::removeCacheIndexedByGeneratorInternal(U* cacheMap, V* i dentifierMap, const ImageFrameGenerator* generator, Vector<OwnPtr<CacheEntry> >* deletionList)
385 {
386 typename V::iterator iter = identifierMap->find(generator);
387 if (iter == identifierMap->end())
388 return;
389
390 // Get all cache identifiers associated with generator.
391 Vector<typename U::KeyType> cacheIdentifierList;
392 copyToVector(iter->value, cacheIdentifierList);
393
394 // For each cache identifier find the corresponding CacheEntry and remove it .
395 for (size_t i = 0; i < cacheIdentifierList.size(); ++i) {
396 ASSERT(cacheMap->contains(cacheIdentifierList[i]));
397 const typename U::MappedType::PtrType cacheEntry = cacheMap->get(cacheId entifierList[i]);
398 ASSERT(!cacheEntry->useCount());
399 removeFromCacheInternal(cacheEntry, cacheMap, identifierMap, deletionLis t);
400 }
401 }
402
403 void ImageDecodingStore::removeFromCacheListInternal(const Vector<OwnPtr<CacheEn try> >& deletionList)
404 {
405 for (size_t i = 0; i < deletionList.size(); ++i)
406 m_orderedCacheList.remove(deletionList[i].get());
407 }
408
409 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698