blob: 3a5d8884913894c72f3f0d432864de8d65a4b9d5 [file] [log] [blame]
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SKY_ENGINE_PLATFORM_GRAPHICS_IMAGEDECODINGSTORE_H_
#define SKY_ENGINE_PLATFORM_GRAPHICS_IMAGEDECODINGSTORE_H_
#include "platform/image-decoders/ImageDecoder.h"
#include "sky/engine/platform/graphics/skia/SkSizeHash.h"
#include "sky/engine/platform/PlatformExport.h"
#include "sky/engine/wtf/DoublyLinkedList.h"
#include "sky/engine/wtf/HashSet.h"
#include "sky/engine/wtf/OwnPtr.h"
#include "sky/engine/wtf/PassOwnPtr.h"
#include "sky/engine/wtf/ThreadingPrimitives.h"
#include "sky/engine/wtf/Vector.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkTypes.h"
namespace blink {
class ImageFrameGenerator;
// FUNCTION
//
// ImageDecodingStore is a class used to manage cached decoder objects.
//
// EXTERNAL OBJECTS
//
// ImageDecoder
// A decoder object. It is used to decode raw data into bitmap images.
//
// ImageFrameGenerator
// This is a direct user of this cache. Responsible for generating bitmap images
// using an ImageDecoder. It contains encoded image data and is used to represent
// one image file. It is used to index image and decoder objects in the cache.
//
// THREAD SAFETY
//
// All public methods can be used on any thread.
class PLATFORM_EXPORT ImageDecodingStore {
public:
static PassOwnPtr<ImageDecodingStore> create() { return adoptPtr(new ImageDecodingStore); }
~ImageDecodingStore();
static ImageDecodingStore* instance();
// Access a cached decoder object. A decoder is indexed by origin (ImageFrameGenerator)
// and scaled size. Return true if the cached object is found.
bool lockDecoder(const ImageFrameGenerator*, const SkISize& scaledSize, ImageDecoder**);
void unlockDecoder(const ImageFrameGenerator*, const ImageDecoder*);
void insertDecoder(const ImageFrameGenerator*, PassOwnPtr<ImageDecoder>);
void removeDecoder(const ImageFrameGenerator*, const ImageDecoder*);
// Remove all cache entries indexed by ImageFrameGenerator.
void removeCacheIndexedByGenerator(const ImageFrameGenerator*);
void clear();
void setCacheLimitInBytes(size_t);
size_t memoryUsageInBytes();
int cacheEntries();
int decoderCacheEntries();
private:
// Decoder cache entry is identified by:
// 1. Pointer to ImageFrameGenerator.
// 2. Size of the image.
typedef std::pair<const ImageFrameGenerator*, SkISize> DecoderCacheKey;
// Base class for all cache entries.
class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
friend class WTF::DoublyLinkedListNode<CacheEntry>;
public:
enum CacheType {
TypeDecoder,
};
CacheEntry(const ImageFrameGenerator* generator, int useCount)
: m_generator(generator)
, m_useCount(useCount)
, m_prev(0)
, m_next(0)
{
}
virtual ~CacheEntry()
{
ASSERT(!m_useCount);
}
const ImageFrameGenerator* generator() const { return m_generator; }
int useCount() const { return m_useCount; }
void incrementUseCount() { ++m_useCount; }
void decrementUseCount() { --m_useCount; ASSERT(m_useCount >= 0); }
// FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer.
// Find a way to get the size in 64-bits.
virtual size_t memoryUsageInBytes() const = 0;
virtual CacheType type() const = 0;
protected:
const ImageFrameGenerator* m_generator;
int m_useCount;
private:
CacheEntry* m_prev;
CacheEntry* m_next;
};
class DecoderCacheEntry final : public CacheEntry {
public:
static PassOwnPtr<DecoderCacheEntry> create(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder)
{
return adoptPtr(new DecoderCacheEntry(generator, 0, decoder));
}
DecoderCacheEntry(const ImageFrameGenerator* generator, int count, PassOwnPtr<ImageDecoder> decoder)
: CacheEntry(generator, count)
, m_cachedDecoder(decoder)
, m_size(SkISize::Make(m_cachedDecoder->decodedSize().width(), m_cachedDecoder->decodedSize().height()))
{
}
virtual size_t memoryUsageInBytes() const override { return m_size.width() * m_size.height() * 4; }
virtual CacheType type() const override { return TypeDecoder; }
static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const SkISize& size)
{
return std::make_pair(generator, size);
}
static DecoderCacheKey makeCacheKey(const ImageFrameGenerator* generator, const ImageDecoder* decoder)
{
return std::make_pair(generator, SkISize::Make(decoder->decodedSize().width(), decoder->decodedSize().height()));
}
DecoderCacheKey cacheKey() const { return makeCacheKey(m_generator, m_size); }
ImageDecoder* cachedDecoder() const { return m_cachedDecoder.get(); }
private:
OwnPtr<ImageDecoder> m_cachedDecoder;
SkISize m_size;
};
ImageDecodingStore();
void prune();
// These helper methods are called while m_mutex is locked.
template<class T, class U, class V> void insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap);
// Helper method to remove a cache entry. Ownership is transferred to
// deletionList. Use of Vector<> is handy when removing multiple entries.
template<class T, class U, class V> void removeFromCacheInternal(const T* cacheEntry, U* cacheMap, V* identifierMap, Vector<OwnPtr<CacheEntry> >* deletionList);
// Helper method to remove a cache entry. Uses the templated version base on
// the type of cache entry.
void removeFromCacheInternal(const CacheEntry*, Vector<OwnPtr<CacheEntry> >* deletionList);
// Helper method to remove all cache entries associated with a ImageFraneGenerator.
// Ownership of cache entries is transferred to deletionList.
template<class U, class V> void removeCacheIndexedByGeneratorInternal(U* cacheMap, V* identifierMap, const ImageFrameGenerator*, Vector<OwnPtr<CacheEntry> >* deletionList);
// Helper method to remove cache entry pointers from the LRU list.
void removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry> >& deletionList);
// A doubly linked list that maintains usage history of cache entries.
// This is used for eviction of old entries.
// Head of this list is the least recently used cache entry.
// Tail of this list is the most recently used cache entry.
DoublyLinkedList<CacheEntry> m_orderedCacheList;
// A lookup table for all decoder cache objects. Owns all decoder cache objects.
typedef HashMap<DecoderCacheKey, OwnPtr<DecoderCacheEntry> > DecoderCacheMap;
DecoderCacheMap m_decoderCacheMap;
// A lookup table to map ImageFrameGenerator to all associated
// decoder cache keys.
typedef HashSet<DecoderCacheKey> DecoderCacheKeySet;
typedef HashMap<const ImageFrameGenerator*, DecoderCacheKeySet> DecoderCacheKeyMap;
DecoderCacheKeyMap m_decoderCacheKeyMap;
size_t m_heapLimitInBytes;
size_t m_heapMemoryUsageInBytes;
// Protect concurrent access to these members:
// m_orderedCacheList
// m_decoderCacheMap and all CacheEntrys stored in it
// m_decoderCacheKeyMap
// m_heapLimitInBytes
// m_heapMemoryUsageInBytes
// This mutex also protects calls to underlying skBitmap's
// lockPixels()/unlockPixels() as they are not threadsafe.
Mutex m_mutex;
};
} // namespace blink
#endif // SKY_ENGINE_PLATFORM_GRAPHICS_IMAGEDECODINGSTORE_H_