Diff
Modified: trunk/Source/WebCore/ChangeLog (141019 => 141020)
--- trunk/Source/WebCore/ChangeLog 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/ChangeLog 2013-01-28 23:40:01 UTC (rev 141020)
@@ -1,3 +1,67 @@
+2013-01-28 Min Qin <[email protected]>
+
+ adding support for DiscardablePixelRef for caching lazily decoded images
+ https://bugs.webkit.org/show_bug.cgi?id=106842
+
+ Reviewed by Stephen White.
+
+ This change allows using discardable memory in the deferred image decoding path.
+ Fully decoded images are unpinned and stored in ImageDecodingStore.
+ Partially decoded images are pinned and stored in ImageDecodingStore.
+ Discardable memory allocation could fail. Fall back to heap allocation in that case.
+ There is a separate size limit for heap entries and no limit on discardable entries.
+ New tests are added to ImageDecodingStoreTests
+
+ * WebCore.gypi:
+ * platform/graphics/chromium/DiscardablePixelRef.cpp: Added.
+ Added implementation of the DiscardablePixelRef object that is backed by discardable memory.
+ Memory allocated to the DiscardablePixelRef can be purged when it is unlocked.
+ (WebCore::DiscardablePixelRefAllocator::allocPixelRef):
+ (WebCore):
+ (WebCore::DiscardablePixelRef::DiscardablePixelRef):
+ (WebCore::DiscardablePixelRef::~DiscardablePixelRef):
+ (WebCore::DiscardablePixelRef::allocAndLockDiscardableMemory):
+ (WebCore::DiscardablePixelRef::onLockPixels):
+ (WebCore::DiscardablePixelRef::onUnlockPixels):
+ (WebCore::DiscardablePixelRef::isDiscardable):
+ * platform/graphics/chromium/DiscardablePixelRef.h: Added.
+ Added class definition of the DiscardablePixelRef.
+ (WebCore):
+ (DiscardablePixelRefAllocator):
+ (DiscardablePixelRef):
+ * platform/graphics/chromium/ImageDecodingStore.cpp:
+ Added new cache replacement strategy for DiscardablePixelRef.
+ (WebCore::ImageDecodingStore::lockCache):
+ (WebCore::ImageDecodingStore::overwriteAndLockCache):
+ (WebCore::ImageDecodingStore::prune):
+ (WebCore::ImageDecodingStore::insertCacheInternal):
+ (WebCore::ImageDecodingStore::removeFromCacheInternal):
+ * platform/graphics/chromium/ImageDecodingStore.h:
+ Added isDiscardable() calls to check if a cache entry is discardable.
+ (WebCore::ImageDecodingStore::CacheEntry::CacheEntry):
+ (WebCore::ImageDecodingStore::CacheEntry::overwriteCachedImage):
+ (WebCore::ImageDecodingStore::CacheEntry::isDiscardable):
+ (CacheEntry):
+ * platform/graphics/chromium/ImageFrameGenerator.cpp:
+ Added some code to pass DiscardableMemoryAllocator to the image decoder.
+ (WebCore::ImageFrameGenerator::tryToScale):
+ (WebCore::ImageFrameGenerator::decode):
+ * platform/graphics/chromium/ImageFrameGenerator.h:
+ Added a new member variable of type DiscardableMemoryAllocator.
+ (ImageFrameGenerator):
+ * platform/image-decoders/ImageDecoder.h:
+ Added methods to pass Allocator to ImageFrame.
+ (ImageFrame):
+ (WebCore::ImageFrame::setMemoryAllocator):
+ (WebCore::ImageFrame::allocator):
+ (ImageDecoder):
+ (WebCore::ImageDecoder::setMemoryAllocator):
+ * platform/image-decoders/skia/ImageDecoderSkia.cpp:
+ Added code to allocate pixel memory using the allocator passed from the caller.
+ (WebCore::ImageFrame::ImageFrame):
+ (WebCore::ImageFrame::operator=):
+ (WebCore::ImageFrame::setSize):
+
2013-01-28 Sheriff Bot <[email protected]>
Unreviewed, rolling out r140869.
Modified: trunk/Source/WebCore/WebCore.gypi (141019 => 141020)
--- trunk/Source/WebCore/WebCore.gypi 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/WebCore.gypi 2013-01-28 23:40:01 UTC (rev 141020)
@@ -3867,6 +3867,8 @@
'platform/graphics/chromium/CrossProcessFontLoading.mm',
'platform/graphics/chromium/DeferredImageDecoder.cpp',
'platform/graphics/chromium/DeferredImageDecoder.h',
+ 'platform/graphics/chromium/DiscardablePixelRef.cpp',
+ 'platform/graphics/chromium/DiscardablePixelRef.h',
'platform/graphics/chromium/DrawingBufferChromium.cpp',
'platform/graphics/chromium/Extensions3DChromium.h',
'platform/graphics/chromium/FontCacheAndroid.cpp',
Added: trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.cpp (0 => 141020)
--- trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.cpp (rev 0)
+++ trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.cpp 2013-01-28 23:40:01 UTC (rev 141020)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#include "config.h"
+#include "DiscardablePixelRef.h"
+
+#include <public/Platform.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+namespace {
+
+// URI label for a discardable SkPixelRef.
+const char labelDiscardable[] = "discardable";
+
+} // namespace
+
+
+bool DiscardablePixelRefAllocator::allocPixelRef(SkBitmap* dst, SkColorTable* ctable)
+{
+ Sk64 size = dst->getSize64();
+ if (size.isNeg() || !size.is32())
+ return false;
+
+ SkAutoTUnref<DiscardablePixelRef> pixelRef(new DiscardablePixelRef(ctable, adoptPtr(new SkMutex())));
+ if (pixelRef->allocAndLockDiscardableMemory(size.get32())) {
+ pixelRef->setURI(labelDiscardable);
+ dst->setPixelRef(pixelRef.get());
+ // This method is only called when a DiscardablePixelRef is created to back a SkBitmap.
+ // It is necessary to lock this SkBitmap to have a valid pointer to pixels. Otherwise,
+ // this SkBitmap could be assigned to another SkBitmap and locking/unlocking the other
+ // SkBitmap will make this one losing its pixels.
+ dst->lockPixels();
+ return true;
+ }
+
+ // Fallback to heap allocator if discardable memory is not available.
+ return dst->allocPixels(ctable);
+}
+
+DiscardablePixelRef::DiscardablePixelRef(SkColorTable* ctable, PassOwnPtr<SkMutex> mutex)
+ : SkPixelRef(mutex.get())
+ , m_colorTable(ctable)
+ , m_lockedMemory(0)
+ , m_mutex(mutex)
+{
+}
+
+DiscardablePixelRef::~DiscardablePixelRef()
+{
+ SkSafeUnref(m_colorTable);
+}
+
+bool DiscardablePixelRef::allocAndLockDiscardableMemory(size_t bytes)
+{
+ m_discardable = adoptPtr(WebKit::Platform::current()->allocateAndLockDiscardableMemory(bytes));
+ if (m_discardable) {
+ m_lockedMemory = m_discardable->data();
+ return true;
+ }
+ return false;
+}
+
+void* DiscardablePixelRef::onLockPixels(SkColorTable** ctable)
+{
+ if (!m_lockedMemory && m_discardable->lock())
+ m_lockedMemory = m_discardable->data();
+
+ *ctable = m_colorTable;
+ return m_lockedMemory;
+}
+
+void DiscardablePixelRef::onUnlockPixels()
+{
+ if (m_lockedMemory)
+ m_discardable->unlock();
+ m_lockedMemory = 0;
+}
+
+bool DiscardablePixelRef::isDiscardable(SkPixelRef* pixelRef)
+{
+ // FIXME: DEFINE_STATIC_LOCAL is not thread safe.
+ // ImageDecodingStore provides the synchronization for this.
+ DEFINE_STATIC_LOCAL(const SkString, discardable, (labelDiscardable));
+ return pixelRef && pixelRef->getURI() && discardable.equals(pixelRef->getURI());
+}
+
+} // namespace WebCore
Property changes on: trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.cpp
___________________________________________________________________
Added: svn:eol-style
Added: trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.h (0 => 141020)
--- trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.h (rev 0)
+++ trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.h 2013-01-28 23:40:01 UTC (rev 141020)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2013 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 DiscardablePixelRef_h
+#define DiscardablePixelRef_h
+
+#include "SkBitmap.h"
+#include "SkPixelRef.h"
+
+#include <public/WebDiscardableMemory.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+// Class for allocating the DiscardablePixelRef object.
+class DiscardablePixelRefAllocator : public SkBitmap::Allocator {
+ // SkBitmap::Allocator implementation. The discardable memory allocated
+ // after this call is locked and will not be purged until next
+ // onUnlockPixels().
+ virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
+};
+
+// PixelRef object whose memory can be discarded when pixels are unlocked.
+class DiscardablePixelRef : public SkPixelRef {
+public:
+ DiscardablePixelRef(SkColorTable*, PassOwnPtr<SkMutex>);
+ ~DiscardablePixelRef();
+
+ static bool isDiscardable(SkPixelRef*);
+ bool allocAndLockDiscardableMemory(size_t);
+
+ SK_DECLARE_UNFLATTENABLE_OBJECT()
+
+protected:
+ // SkPixelRef implementation.
+ virtual void* onLockPixels(SkColorTable**);
+ virtual void onUnlockPixels();
+
+private:
+ SkColorTable* m_colorTable;
+ void* m_lockedMemory;
+ OwnPtr<WebKit::WebDiscardableMemory> m_discardable;
+ OwnPtr<SkMutex> m_mutex;
+};
+
+} // namespace WebCore
+
+#endif
Property changes on: trunk/Source/WebCore/platform/graphics/chromium/DiscardablePixelRef.h
___________________________________________________________________
Added: svn:eol-style
Modified: trunk/Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp (141019 => 141020)
--- trunk/Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/platform/graphics/chromium/ImageDecodingStore.cpp 2013-01-28 23:40:01 UTC (rev 141020)
@@ -82,28 +82,37 @@
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();
- if (condition == CacheMustBeComplete && !cacheEntry->cachedImage()->isComplete())
+ ScaledImageFragment* image = cacheEntry->cachedImage();
+ if (condition == CacheMustBeComplete && !image->isComplete())
return false;
// Incomplete cache entry cannot be used more than once.
- ASSERT(cacheEntry->cachedImage()->isComplete() || !cacheEntry->useCount());
+ ASSERT(image->isComplete() || !cacheEntry->useCount());
- // Increment use count such that it doesn't get evicted.
- cacheEntry->incrementUseCount();
+ 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(!cacheEntry->cachedImage()->isComplete() || !cacheEntry->cachedDecoder());
+ // Complete cache entry doesn't have a decoder.
+ ASSERT(!image->isComplete() || !cacheEntry->cachedDecoder());
- if (decoder)
- *decoder = cacheEntry->cachedDecoder();
- *cachedImage = cacheEntry->cachedImage();
- (*cachedImage)->bitmap().lockPixels();
+ if (decoder)
+ *decoder = cacheEntry->cachedDecoder();
+ *cachedImage = image;
+ } else {
+ image->bitmap().unlockPixels();
+ removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete);
+ removeFromCacheListInternal(cacheEntriesToDelete);
+ return false;
+ }
}
return true;
@@ -160,6 +169,11 @@
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.
@@ -230,7 +244,7 @@
// Walk the list of cache entries starting from the least recently used
// and then keep them for deletion later.
- while (cacheEntry && m_memoryUsageInBytes > m_cacheLimitInBytes) {
+ while (cacheEntry && (m_memoryUsageInBytes > m_cacheLimitInBytes || !m_cacheLimitInBytes)) {
// Cache is not used; Remove it.
if (!cacheEntry->useCount())
removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete);
@@ -244,7 +258,8 @@
void ImageDecodingStore::insertCacheInternal(PassOwnPtr<CacheEntry> cacheEntry)
{
- incrementMemoryUsage(cacheEntry->memoryUsageInBytes());
+ if (!cacheEntry->isDiscardable())
+ incrementMemoryUsage(cacheEntry->memoryUsageInBytes());
// m_orderedCacheList is used to support LRU operations to reorder cache
// entries quickly.
@@ -262,7 +277,8 @@
void ImageDecodingStore::removeFromCacheInternal(const CacheEntry* cacheEntry, Vector<OwnPtr<CacheEntry> >* deletionList)
{
- decrementMemoryUsage(cacheEntry->memoryUsageInBytes());
+ if (!cacheEntry->isDiscardable())
+ decrementMemoryUsage(cacheEntry->memoryUsageInBytes());
// Remove from m_cacheMap.
CacheIdentifier key = cacheEntry->cacheKey();
Modified: trunk/Source/WebCore/platform/graphics/chromium/ImageDecodingStore.h (141019 => 141020)
--- trunk/Source/WebCore/platform/graphics/chromium/ImageDecodingStore.h 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/platform/graphics/chromium/ImageDecodingStore.h 2013-01-28 23:40:01 UTC (rev 141020)
@@ -26,6 +26,7 @@
#ifndef ImageDecodingStore_h
#define ImageDecodingStore_h
+#include "DiscardablePixelRef.h"
#include "ImageDecoder.h"
#include "ScaledImageFragment.h"
#include "SkTypes.h"
@@ -92,6 +93,7 @@
, m_cachedImage(image)
, m_cachedDecoder(decoder)
, m_useCount(count)
+ , m_isDiscardable(DiscardablePixelRef::isDiscardable(m_cachedImage->bitmap().pixelRef()))
{
}
@@ -106,6 +108,7 @@
ImageDecoder* cachedDecoder() const { return m_cachedDecoder.get(); }
PassOwnPtr<ImageDecoder> overwriteCachedImage(PassOwnPtr<ScaledImageFragment> image)
{
+ m_isDiscardable = DiscardablePixelRef::isDiscardable(image->bitmap().pixelRef());
m_cachedImage = image;
if (m_cachedImage->isComplete())
return m_cachedDecoder.release();
@@ -114,6 +117,7 @@
int useCount() const { return m_useCount; }
void incrementUseCount() { ++m_useCount; }
void decrementUseCount() { --m_useCount; ASSERT(m_useCount >= 0); }
+ bool isDiscardable() const { return m_isDiscardable; }
// FIXME: getSafeSize() returns size in bytes truncated to a 32-bits integer.
// Find a way to get the size in 64-bits.
@@ -126,6 +130,7 @@
OwnPtr<ScaledImageFragment> m_cachedImage;
OwnPtr<ImageDecoder> m_cachedDecoder;
int m_useCount;
+ bool m_isDiscardable;
};
ImageDecodingStore();
Modified: trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp (141019 => 141020)
--- trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp 2013-01-28 23:40:01 UTC (rev 141020)
@@ -112,8 +112,13 @@
if (!fullSizeImage && !ImageDecodingStore::instance()->lockCache(this, m_fullSize, ImageDecodingStore::CacheMustBeComplete, &fullSizeImage))
return 0;
- SkBitmap scaledBitmap = skia::ImageOperations::Resize(
- fullSizeImage->bitmap(), resizeMethod(), scaledSize.width(), scaledSize.height());
+ DiscardablePixelRefAllocator allocator;
+ // This call allocates the DiscardablePixelRef and lock/unlocks it
+ // afterwards. So the memory allocated to the scaledBitmap can be
+ // discarded after this call. Need to lock the scaledBitmap and
+ // check the pixels before using it next time.
+ SkBitmap scaledBitmap = skia::ImageOperations::Resize(fullSizeImage->bitmap(), resizeMethod(), scaledSize.width(), scaledSize.height(), &allocator);
+
OwnPtr<ScaledImageFragment> scaledImage = ScaledImageFragment::create(scaledSize, scaledBitmap, fullSizeImage->isComplete());
ImageDecodingStore::instance()->unlockCache(this, fullSizeImage);
@@ -189,7 +194,15 @@
return nullptr;
}
+ // TODO: this is very ugly. We need to refactor the way how we can pass a
+ // memory allocator to image decoders.
+ (*decoder)->setMemoryAllocator(&m_allocator);
(*decoder)->setData(data, allDataReceived);
+ // If this call returns a newly allocated DiscardablePixelRef, then
+ // ImageFrame::m_bitmap and the contained DiscardablePixelRef are locked.
+ // They will be unlocked when ImageDecoder is destroyed since ImageDecoder
+ // owns the ImageFrame. Partially decoded SkBitmap is thus inserted into the
+ // ImageDecodingStore while locked.
ImageFrame* frame = (*decoder)->frameBufferAtIndex(0);
(*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
Modified: trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.h (141019 => 141020)
--- trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.h 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.h 2013-01-28 23:40:01 UTC (rev 141020)
@@ -26,6 +26,7 @@
#ifndef ImageFrameGenerator_h
#define ImageFrameGenerator_h
+#include "DiscardablePixelRef.h"
#include "SkTypes.h"
#include "SkBitmap.h"
#include "SkSize.h"
@@ -79,6 +80,7 @@
SkISize m_fullSize;
ThreadSafeDataTransport m_data;
bool m_decodeFailedAndEmpty;
+ DiscardablePixelRefAllocator m_allocator;
OwnPtr<ImageDecoderFactory> m_imageDecoderFactory;
Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h (141019 => 141020)
--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h 2013-01-28 23:40:01 UTC (rev 141020)
@@ -157,6 +157,13 @@
{
return m_bitmap.bitmap();
}
+
+ void setMemoryAllocator(SkBitmap::Allocator* allocator)
+ {
+ m_allocator = allocator;
+ }
+
+ SkBitmap::Allocator* allocator() const { return m_allocator; }
#endif
// Use fix point multiplier instead of integer division or floating point math.
@@ -212,6 +219,7 @@
#if USE(SKIA)
NativeImageSkia m_bitmap;
+ SkBitmap::Allocator* m_allocator;
#else
Vector<PixelData> m_backingStore;
PixelData* m_bytes; // The memory is backed by m_backingStore.
@@ -406,6 +414,15 @@
virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+#if USE(SKIA)
+ virtual void setMemoryAllocator(SkBitmap::Allocator* allocator)
+ {
+ // FIXME: this doesn't work for images with multiple frames.
+ if (m_frameBufferCache.isEmpty())
+ m_frameBufferCache.resize(1);
+ m_frameBufferCache[0].setMemoryAllocator(allocator);
+ }
+#endif
protected:
void prepareScaleDataIfNecessary();
int upperBoundScaledX(int origX, int searchStart = 0);
Modified: trunk/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp (141019 => 141020)
--- trunk/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp 2013-01-28 23:40:01 UTC (rev 141020)
@@ -32,7 +32,8 @@
namespace WebCore {
ImageFrame::ImageFrame()
- : m_hasAlpha(false)
+ : m_allocator(0)
+ , m_hasAlpha(false)
, m_status(FrameEmpty)
, m_duration(0)
, m_disposalMethod(DisposeNotSpecified)
@@ -49,6 +50,7 @@
// Keep the pixels locked since we will be writing directly into the
// bitmap throughout this object's lifetime.
m_bitmap.bitmap().lockPixels();
+ setMemoryAllocator(other.allocator());
setOriginalFrameRect(other.originalFrameRect());
setStatus(other.status());
setDuration(other.duration());
@@ -93,7 +95,7 @@
ASSERT(!width() && !height());
m_bitmap.bitmap().setConfig(SkBitmap::kARGB_8888_Config, newWidth, newHeight);
- if (!m_bitmap.bitmap().allocPixels())
+ if (!m_bitmap.bitmap().allocPixels(m_allocator, 0))
return false;
zeroFillPixelData();
Modified: trunk/Source/WebKit/chromium/ChangeLog (141019 => 141020)
--- trunk/Source/WebKit/chromium/ChangeLog 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebKit/chromium/ChangeLog 2013-01-28 23:40:01 UTC (rev 141020)
@@ -1,3 +1,35 @@
+2013-01-28 Min Qin <[email protected]>
+
+ adding support for DiscardablePixelRef for caching lazily decoded images
+ https://bugs.webkit.org/show_bug.cgi?id=106842
+
+ Reviewed by Stephen White.
+
+ Adding new tests for ImageDecodingStore
+
+ * WebKit.gypi:
+ * tests/ImageDecodingStoreTest.cpp:
+ (WebCore::ImageDecodingStoreTest::createCompleteImage):
+ (WebCore::ImageDecodingStoreTest::createIncompleteImage):
+ (WebCore::TEST_F):
+ (WebCore):
+ * tests/MockDiscardablePixelRef.h: Added.
+ (WebCore):
+ (MockDiscardablePixelRef):
+ (WebCore::MockDiscardablePixelRef::MockDiscardablePixelRef):
+ (WebCore::MockDiscardablePixelRef::~MockDiscardablePixelRef):
+ (WebCore::MockDiscardablePixelRef::discard):
+ (WebCore::MockDiscardablePixelRef::onLockPixels):
+ (WebCore::MockDiscardablePixelRef::onUnlockPixels):
+
+2013-01-28 Stephen Chenney <[email protected]>
+
+ [Chromium] Fix the build.
+
+ Unreviewed build fix.
+
+ * src/AssertMatchingEnums.cpp: Move the include to the right place and remove the bad directory prefix.
+
2013-01-28 Dan Alcantara <[email protected]>
[Chromium, Mobile] Do not show disambiguation pop up in mobile sites
Modified: trunk/Source/WebKit/chromium/WebKit.gypi (141019 => 141020)
--- trunk/Source/WebKit/chromium/WebKit.gypi 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebKit/chromium/WebKit.gypi 2013-01-28 23:40:01 UTC (rev 141020)
@@ -83,6 +83,7 @@
'tests/ImageDecodingStoreTest.cpp',
'tests/ImageFrameGeneratorTest.cpp',
'tests/ImageLayerChromiumTest.cpp',
+ 'tests/MockDiscardablePixelRef.h',
'tests/MockImageDecoder.h',
'tests/KeyboardTest.cpp',
'tests/KURLTest.cpp',
Modified: trunk/Source/WebKit/chromium/tests/ImageDecodingStoreTest.cpp (141019 => 141020)
--- trunk/Source/WebKit/chromium/tests/ImageDecodingStoreTest.cpp 2013-01-28 23:38:14 UTC (rev 141019)
+++ trunk/Source/WebKit/chromium/tests/ImageDecodingStoreTest.cpp 2013-01-28 23:40:01 UTC (rev 141020)
@@ -28,6 +28,7 @@
#include "ImageDecodingStore.h"
#include "ImageFrameGenerator.h"
+#include "MockDiscardablePixelRef.h"
#include "MockImageDecoder.h"
#include "SharedBuffer.h"
#include <gtest/gtest.h>
@@ -68,19 +69,25 @@
}
protected:
- PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size)
+ PassOwnPtr<ScaledImageFragment> createCompleteImage(const SkISize& size, bool discardable = false)
{
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- bitmap.allocPixels();
+ if (!discardable)
+ bitmap.allocPixels();
+ else
+ bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
return ScaledImageFragment::create(size, bitmap, true);
}
- PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size)
+ PassOwnPtr<ScaledImageFragment> createIncompleteImage(const SkISize& size, bool discardable = false)
{
SkBitmap bitmap;
bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
- bitmap.allocPixels();
+ if (!discardable)
+ bitmap.allocPixels();
+ else
+ bitmap.setPixelRef(new MockDiscardablePixelRef())->unref();
return ScaledImageFragment::create(size, bitmap, false);
}
@@ -281,4 +288,59 @@
ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
}
+TEST_F(ImageDecodingStoreTest, lockCacheFailedAfterMemoryDiscarded)
+{
+ const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
+ m_generator.get(), createCompleteImage(SkISize::Make(1, 1), true), MockImageDecoder::create(this));
+ unlockCache(cachedImage);
+ MockDiscardablePixelRef* pixelRef = static_cast<MockDiscardablePixelRef*>(cachedImage->bitmap().pixelRef());
+ pixelRef->discard();
+ EXPECT_EQ(0, lockCache(SkISize::Make(1, 1)));
+ EXPECT_EQ(0u, ImageDecodingStore::instance()->cacheEntries());
+}
+
+TEST_F(ImageDecodingStoreTest, overwriteNonDiscardableCacheWithDiscardable)
+{
+
+ const SkISize size = SkISize::Make(1, 1);
+ const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
+ m_generator.get(), createIncompleteImage(size), MockImageDecoder::create(this));
+ ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
+ EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
+ EXPECT_LT(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
+
+ ImageDecoder* decoder = 0;
+ EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage, &decoder));
+ EXPECT_FALSE(cachedImage->isComplete());
+
+ cachedImage = ImageDecodingStore::instance()->overwriteAndLockCache(
+ m_generator.get(), cachedImage, createCompleteImage(size, true));
+ EXPECT_TRUE(cachedImage->isComplete());
+ EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
+ EXPECT_EQ(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
+ ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
+}
+
+TEST_F(ImageDecodingStoreTest, overwriteDiscardableCacheWithNonDiscardable)
+{
+
+ const SkISize size = SkISize::Make(1, 1);
+ const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(
+ m_generator.get(), createIncompleteImage(size, true), MockImageDecoder::create(this));
+ ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
+ EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
+ EXPECT_EQ(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
+
+ ImageDecoder* decoder = 0;
+ EXPECT_TRUE(ImageDecodingStore::instance()->lockCache(m_generator.get(), size, ImageDecodingStore::CacheCanBeIncomplete, &cachedImage, &decoder));
+ EXPECT_FALSE(cachedImage->isComplete());
+
+ cachedImage = ImageDecodingStore::instance()->overwriteAndLockCache(
+ m_generator.get(), cachedImage, createCompleteImage(size));
+ EXPECT_TRUE(cachedImage->isComplete());
+ EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
+ EXPECT_LT(0u, ImageDecodingStore::instance()->memoryUsageInBytes());
+ ImageDecodingStore::instance()->unlockCache(m_generator.get(), cachedImage);
+}
+
} // namespace
Added: trunk/Source/WebKit/chromium/tests/MockDiscardablePixelRef.h (0 => 141020)
--- trunk/Source/WebKit/chromium/tests/MockDiscardablePixelRef.h (rev 0)
+++ trunk/Source/WebKit/chromium/tests/MockDiscardablePixelRef.h 2013-01-28 23:40:01 UTC (rev 141020)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 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 AND ITS CONTRIBUTORS "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 OR ITS 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 MockDiscardablePixelRef_h
+
+#include "SkBitmap.h"
+#include "SkPixelRef.h"
+
+namespace WebCore {
+
+class MockDiscardablePixelRef : public SkPixelRef {
+public:
+ MockDiscardablePixelRef() : discarded(false) { setURI("discardable"); }
+ ~MockDiscardablePixelRef() { }
+
+ void discard()
+ {
+ ASSERT(!m_lockedMemory);
+ discarded = true;
+ }
+
+ SK_DECLARE_UNFLATTENABLE_OBJECT()
+
+protected:
+ // SkPixelRef implementation.
+ virtual void* onLockPixels(SkColorTable**)
+ {
+ if (discarded)
+ return 0;
+ m_lockedMemory = &discarded;
+ return m_lockedMemory;
+ }
+
+ virtual void onUnlockPixels()
+ {
+ m_lockedMemory = 0;
+ }
+
+private:
+ void* m_lockedMemory;
+ bool discarded;
+};
+
+} // namespace WebCore
+
+#endif // MockDiscardablePixelRef_h
Property changes on: trunk/Source/WebKit/chromium/tests/MockDiscardablePixelRef.h
___________________________________________________________________
Added: svn:eol-style