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

Unified Diff: Source/core/platform/graphics/chromium/ImageFrameGenerator.cpp

Issue 17999003: Deferred image decoding to support animated GIFs (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: done Created 7 years, 5 months 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 side-by-side diff with in-line comments
Download patch
Index: Source/core/platform/graphics/chromium/ImageFrameGenerator.cpp
diff --git a/Source/core/platform/graphics/chromium/ImageFrameGenerator.cpp b/Source/core/platform/graphics/chromium/ImageFrameGenerator.cpp
index e5027cb88b144ce945766d9ea5830e5382a23364..bd0890860f4e0018e0384ca737912063e854918d 100644
--- a/Source/core/platform/graphics/chromium/ImageFrameGenerator.cpp
+++ b/Source/core/platform/graphics/chromium/ImageFrameGenerator.cpp
@@ -47,8 +47,9 @@ skia::ImageOperations::ResizeMethod resizeMethod()
} // namespace
-ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<SharedBuffer> data, bool allDataReceived)
+ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<SharedBuffer> data, bool allDataReceived, bool isMultiFrame)
: m_fullSize(fullSize)
+ , m_isMultiFrame(isMultiFrame)
, m_decodeFailedAndEmpty(false)
, m_hasAlpha(true)
, m_decodeCount(ScaledImageFragment::FirstPartialImage)
@@ -78,7 +79,7 @@ void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataRece
*data = buffer->copy();
}
-const ScaledImageFragment* ImageFrameGenerator::decodeAndScale(const SkISize& scaledSize)
+const ScaledImageFragment* ImageFrameGenerator::decodeAndScale(const SkISize& scaledSize, size_t index)
{
// Prevents concurrent decode or scale operations on the same image data.
// Multiple LazyDecodingPixelRefs can call this method at the same time.
@@ -88,35 +89,35 @@ const ScaledImageFragment* ImageFrameGenerator::decodeAndScale(const SkISize& sc
const ScaledImageFragment* cachedImage = 0;
- cachedImage = tryToLockCompleteCache(scaledSize);
+ cachedImage = tryToLockCompleteCache(scaledSize, index);
if (cachedImage)
return cachedImage;
TRACE_EVENT2("webkit", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", static_cast<int>(m_decodeCount));
- cachedImage = tryToScale(0, scaledSize);
+ cachedImage = tryToScale(0, scaledSize, index);
if (cachedImage)
return cachedImage;
- cachedImage = tryToResumeDecodeAndScale(scaledSize);
+ cachedImage = tryToResumeDecodeAndScale(scaledSize, index);
if (cachedImage)
return cachedImage;
- cachedImage = tryToDecodeAndScale(scaledSize);
+ cachedImage = tryToDecodeAndScale(scaledSize, index);
if (cachedImage)
return cachedImage;
return 0;
}
-const ScaledImageFragment* ImageFrameGenerator::tryToLockCompleteCache(const SkISize& scaledSize)
+const ScaledImageFragment* ImageFrameGenerator::tryToLockCompleteCache(const SkISize& scaledSize, size_t index)
{
const ScaledImageFragment* cachedImage = 0;
- if (ImageDecodingStore::instance()->lockCache(this, scaledSize, 0, &cachedImage))
+ if (ImageDecodingStore::instance()->lockCache(this, scaledSize, index, &cachedImage))
return cachedImage;
return 0;
}
-const ScaledImageFragment* ImageFrameGenerator::tryToScale(const ScaledImageFragment* fullSizeImage, const SkISize& scaledSize)
+const ScaledImageFragment* ImageFrameGenerator::tryToScale(const ScaledImageFragment* fullSizeImage, const SkISize& scaledSize, size_t index)
{
TRACE_EVENT0("webkit", "ImageFrameGenerator::tryToScale");
@@ -125,7 +126,7 @@ const ScaledImageFragment* ImageFrameGenerator::tryToScale(const ScaledImageFrag
if (scaledSize == m_fullSize)
return 0;
- if (!fullSizeImage && !ImageDecodingStore::instance()->lockCache(this, m_fullSize, 0, &fullSizeImage))
+ if (!fullSizeImage && !ImageDecodingStore::instance()->lockCache(this, m_fullSize, index, &fullSizeImage))
return 0;
// This call allocates the DiscardablePixelRef and lock/unlocks it
@@ -143,9 +144,9 @@ const ScaledImageFragment* ImageFrameGenerator::tryToScale(const ScaledImageFrag
return ImageDecodingStore::instance()->insertAndLockCache(this, scaledImage.release());
}
-const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const SkISize& scaledSize)
+const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const SkISize& scaledSize, size_t index)
{
- TRACE_EVENT0("webkit", "ImageFrameGenerator::tryToResumeDecodeAndScale");
+ TRACE_EVENT1("webkit", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));
ImageDecoder* cachedDecoder = 0;
@@ -154,27 +155,28 @@ const ScaledImageFragment* ImageFrameGenerator::tryToResumeDecodeAndScale(const
ASSERT(cachedDecoder);
// Always generate a new image and insert it into cache.
- OwnPtr<ScaledImageFragment> fullSizeImage = decode(&cachedDecoder);
+ OwnPtr<ScaledImageFragment> fullSizeImage = decode(index, &cachedDecoder);
const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(this, fullSizeImage.release());
// If the image generated is complete then there is no need to keep
- // the decoder.
- if (cachedImage->isComplete())
+ // the decoder. The exception is multi-frame decoder which can generate
+ // multiple complete frames.
+ if (cachedImage->isComplete() && !m_isMultiFrame)
ImageDecodingStore::instance()->removeDecoder(this, cachedDecoder);
else
ImageDecodingStore::instance()->unlockDecoder(this, cachedDecoder);
if (m_fullSize == scaledSize)
return cachedImage;
- return tryToScale(cachedImage, scaledSize);
+ return tryToScale(cachedImage, scaledSize, index);
}
-const ScaledImageFragment* ImageFrameGenerator::tryToDecodeAndScale(const SkISize& scaledSize)
+const ScaledImageFragment* ImageFrameGenerator::tryToDecodeAndScale(const SkISize& scaledSize, size_t index)
{
- TRACE_EVENT0("webkit", "ImageFrameGenerator::tryToDecodeAndScale");
+ TRACE_EVENT1("webkit", "ImageFrameGenerator::tryToDecodeAndScale", "index", static_cast<int>(index));
ImageDecoder* decoder = 0;
- OwnPtr<ScaledImageFragment> fullSizeImage = decode(&decoder);
+ OwnPtr<ScaledImageFragment> fullSizeImage = decode(index, &decoder);
if (!decoder)
return 0;
@@ -191,16 +193,17 @@ const ScaledImageFragment* ImageFrameGenerator::tryToDecodeAndScale(const SkISiz
const ScaledImageFragment* cachedImage = ImageDecodingStore::instance()->insertAndLockCache(this, fullSizeImage.release());
// If image is complete then decoder is not needed in the future.
- // Otherwise save the decoder for later use.
- if (!cachedImage->isComplete())
+ // Otherwise save the decoder for later use. The exception is
+ // multi-frame decoder which can generate multiple complete frames.
+ if (!cachedImage->isComplete() || m_isMultiFrame)
ImageDecodingStore::instance()->insertDecoder(this, decoderContainer.release(), DiscardablePixelRef::isDiscardable(cachedImage->bitmap().pixelRef()));
if (m_fullSize == scaledSize)
return cachedImage;
- return tryToScale(cachedImage, scaledSize);
+ return tryToScale(cachedImage, scaledSize, index);
}
-PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(ImageDecoder** decoder)
+PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder)
{
TRACE_EVENT2("webkit", "ImageFrameGenerator::decode", "width", m_fullSize.width(), "height", m_fullSize.height());
@@ -222,15 +225,17 @@ PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(ImageDecoder** decod
// 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);
+ if (!m_isMultiFrame)
+ (*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);
+ ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
(*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
+ (*decoder)->clearCacheExceptFrame(index);
if (!frame || frame->status() == ImageFrame::FrameEmpty)
return nullptr;
@@ -244,13 +249,13 @@ PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(ImageDecoder** decod
ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.height() == m_fullSize.height());
if (isComplete)
- return ScaledImageFragment::createComplete(m_fullSize, 0, fullSizeBitmap);
+ return ScaledImageFragment::createComplete(m_fullSize, index, fullSizeBitmap);
// If the image is partial we need to return a copy. This is to avoid future
// decode operations writing to the same bitmap.
SkBitmap copyBitmap;
fullSizeBitmap.copyTo(&copyBitmap, fullSizeBitmap.config(), &m_allocator);
- return ScaledImageFragment::createPartial(m_fullSize, 0, nextGenerationId(), copyBitmap);
+ return ScaledImageFragment::createPartial(m_fullSize, index, nextGenerationId(), copyBitmap);
}
bool ImageFrameGenerator::hasAlpha()

Powered by Google App Engine
This is Rietveld 408576698