| 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(©Bitmap, fullSizeBitmap.config(), &m_allocator);
|
| - return ScaledImageFragment::createPartial(m_fullSize, 0, nextGenerationId(), copyBitmap);
|
| + return ScaledImageFragment::createPartial(m_fullSize, index, nextGenerationId(), copyBitmap);
|
| }
|
|
|
| bool ImageFrameGenerator::hasAlpha()
|
|
|