Modified: trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp (144241 => 144242)
--- trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp 2013-02-27 22:44:29 UTC (rev 144241)
+++ trunk/Source/WebCore/platform/graphics/chromium/ImageFrameGenerator.cpp 2013-02-27 22:49:32 UTC (rev 144242)
@@ -142,9 +142,21 @@
ASSERT(cachedDecoder);
if (m_data.hasNewData()) {
+ // For single frame images, the above ImageDecodingStore::lockCache()
+ // call should lock the pixelRef. As a result, this lockFrameBuffers()
+ // call should always succeed.
+ // TODO: this does not work for the multiframe images, which are not
+ // yet supported by this class.
+ bool frameBuffersLocked = cachedDecoder->lockFrameBuffers();
+ ASSERT_UNUSED(frameBuffersLocked, frameBuffersLocked);
// Only do decoding if there is new data.
OwnPtr<ScaledImageFragment> fullSizeImage = decode(&cachedDecoder);
cachedImage = ImageDecodingStore::instance()->overwriteAndLockCache(this, cachedImage, fullSizeImage.release());
+ // If the image is partially decoded, unlock the frames so that it
+ // can be evicted from the memory. For fully decoded images,
+ // ImageDecodingStore should have deleted the decoder here.
+ if (!cachedImage->isComplete())
+ cachedDecoder->unlockFrameBuffers();
}
if (m_fullSize == scaledSize)
@@ -171,6 +183,10 @@
const ScaledImageFragment* cachedFullSizeImage = ImageDecodingStore::instance()->insertAndLockCache(
this, fullSizeImage.release(), decoderContainer.release());
+ // The newly created SkBitmap in the decoder is locked. Unlock it here
+ // if the image is partially decoded.
+ if (!cachedFullSizeImage->isComplete())
+ decoder->unlockFrameBuffers();
if (m_fullSize == scaledSize)
return cachedFullSizeImage;
@@ -201,9 +217,8 @@
(*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.
+ // They will be unlocked after the image fragment is inserted into
+ // ImageDecodingStore.
ImageFrame* frame = (*decoder)->frameBufferAtIndex(0);
(*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
Modified: trunk/Source/WebKit/chromium/tests/ImageFrameGeneratorTest.cpp (144241 => 144242)
--- trunk/Source/WebKit/chromium/tests/ImageFrameGeneratorTest.cpp 2013-02-27 22:44:29 UTC (rev 144241)
+++ trunk/Source/WebKit/chromium/tests/ImageFrameGeneratorTest.cpp 2013-02-27 22:49:32 UTC (rev 144242)
@@ -73,6 +73,8 @@
m_generator->setImageDecoderFactoryForTesting(MockImageDecoderFactory::create(this));
m_decodersDestroyed = 0;
m_frameBufferRequestCount = 0;
+ m_frameBufferLockCount = 0;
+ m_frameBufferUnlockCount = 0;
m_frameStatus = ImageFrame::FrameEmpty;
}
@@ -91,6 +93,16 @@
++m_frameBufferRequestCount;
}
+ virtual void frameBuffersUnlocked()
+ {
+ ++m_frameBufferUnlockCount;
+ }
+
+ virtual void frameBuffersLocked()
+ {
+ ++m_frameBufferLockCount;
+ }
+
virtual ImageFrame::FrameStatus frameStatus()
{
return m_frameStatus;
@@ -117,6 +129,8 @@
RefPtr<ImageFrameGenerator> m_generator;
int m_decodersDestroyed;
int m_frameBufferRequestCount;
+ int m_frameBufferLockCount;
+ int m_frameBufferUnlockCount;
ImageFrame::FrameStatus m_frameStatus;
};
@@ -141,6 +155,7 @@
EXPECT_TRUE(m_generator->hasAlpha());
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(0, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
}
TEST_F(ImageFrameGeneratorTest, cacheMissWithScale)
@@ -164,6 +179,8 @@
EXPECT_TRUE(m_generator->hasAlpha());
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(0, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(0, m_frameBufferUnlockCount);
}
TEST_F(ImageFrameGeneratorTest, cacheMissWithDecodeAndScale)
@@ -173,6 +190,8 @@
// Cache miss.
const ScaledImageFragment* scaledImage = m_generator->decodeAndScale(scaledSize());
EXPECT_EQ(1, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(0, m_frameBufferUnlockCount);
EXPECT_EQ(scaledSize(), scaledImage->scaledSize());
EXPECT_FALSE(m_generator->hasAlpha());
ImageDecodingStore::instance()->unlockCache(m_generator.get(), scaledImage);
@@ -192,6 +211,8 @@
EXPECT_FALSE(m_generator->hasAlpha());
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(0, m_frameBufferUnlockCount);
}
TEST_F(ImageFrameGeneratorTest, cacheMissWithIncompleteDecode)
@@ -201,6 +222,8 @@
const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
@@ -208,6 +231,8 @@
tempImage = m_generator->decodeAndScale(fullSize());
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(2, m_frameBufferRequestCount);
+ EXPECT_EQ(1, m_frameBufferLockCount);
+ EXPECT_EQ(2, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
EXPECT_EQ(0, m_decodersDestroyed);
@@ -220,12 +245,16 @@
const ScaledImageFragment* tempImage= m_generator->decodeAndScale(fullSize());
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
tempImage = m_generator->decodeAndScale(fullSize());
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
EXPECT_EQ(0, m_decodersDestroyed);
@@ -238,6 +267,8 @@
const ScaledImageFragment* tempImage= m_generator->decodeAndScale(scaledSize());
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
@@ -245,6 +276,8 @@
tempImage = m_generator->decodeAndScale(scaledSize());
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(2, m_frameBufferRequestCount);
+ EXPECT_EQ(1, m_frameBufferLockCount);
+ EXPECT_EQ(2, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
EXPECT_EQ(0, m_decodersDestroyed);
@@ -258,6 +291,8 @@
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
EXPECT_EQ(0, m_decodersDestroyed);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
@@ -268,6 +303,8 @@
EXPECT_TRUE(tempImage->isComplete());
EXPECT_EQ(2, m_frameBufferRequestCount);
EXPECT_EQ(1, m_decodersDestroyed);
+ EXPECT_EQ(1, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
@@ -285,6 +322,8 @@
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
EXPECT_EQ(0, m_decodersDestroyed);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
@@ -295,6 +334,8 @@
EXPECT_TRUE(tempImage->isComplete());
EXPECT_EQ(2, m_frameBufferRequestCount);
EXPECT_EQ(1, m_decodersDestroyed);
+ EXPECT_EQ(1, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(2u, ImageDecodingStore::instance()->cacheEntries());
@@ -325,6 +366,8 @@
EXPECT_FALSE(tempImage->isComplete());
EXPECT_EQ(1, m_frameBufferRequestCount);
EXPECT_EQ(0, m_decodersDestroyed);
+ EXPECT_EQ(0, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
@@ -336,11 +379,15 @@
EXPECT_EQ(2, m_frameBufferRequestCount);
EXPECT_EQ(1, m_decodersDestroyed);
+ EXPECT_EQ(1, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
EXPECT_EQ(1u, ImageDecodingStore::instance()->cacheEntries());
tempImage = m_generator->decodeAndScale(fullSize());
EXPECT_TRUE(tempImage->isComplete());
EXPECT_EQ(2, m_frameBufferRequestCount);
+ EXPECT_EQ(1, m_frameBufferLockCount);
+ EXPECT_EQ(1, m_frameBufferUnlockCount);
ImageDecodingStore::instance()->unlockCache(m_generator.get(), tempImage);
}