| Index: third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| index b332fd9d54f678d45843a7c906dc1d3ff6805cb7..d41cea4102bc26ebcacac2e82afd9ca11a56cef3 100644
|
| --- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| +++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| @@ -132,9 +132,7 @@ bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index,
|
| // Prevents concurrent decode or scale operations on the same image data.
|
| MutexLocker lock(m_decodeMutex);
|
|
|
| - // This implementation does not support scaling so check the requested size.
|
| - SkISize scaledSize = SkISize::Make(info.width(), info.height());
|
| - ASSERT(m_fullSize == scaledSize);
|
| + SkISize outputSize = SkISize::Make(info.width(), info.height());
|
|
|
| if (m_decodeFailedAndEmpty)
|
| return false;
|
| @@ -143,16 +141,17 @@ bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index,
|
|
|
| m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, rowBytes));
|
|
|
| - SkBitmap bitmap = tryToResumeDecode(scaledSize, index);
|
| - if (bitmap.isNull())
|
| - return false;
|
| + SkBitmap bitmap = tryToResumeDecode(outputSize, index, info.colorType(), rowBytes);
|
|
|
| // Don't keep the allocator because it contains a pointer to memory
|
| // that we do not own.
|
| m_externalAllocator.clear();
|
|
|
| - ASSERT(bitmap.width() == scaledSize.width());
|
| - ASSERT(bitmap.height() == scaledSize.height());
|
| + if (bitmap.isNull())
|
| + return false;
|
| +
|
| + ASSERT(bitmap.width() == outputSize.width());
|
| + ASSERT(bitmap.height() == outputSize.height());
|
|
|
| bool result = true;
|
| SkAutoLockPixels bitmapLock(bitmap);
|
| @@ -205,7 +204,7 @@ bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3]
|
| return yuvDecoded;
|
| }
|
|
|
| -SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_t index)
|
| +SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& outputSize, size_t index, SkColorType outputType, size_t rowBytes)
|
| {
|
| TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));
|
|
|
| @@ -213,8 +212,8 @@ SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_
|
| const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
|
| ASSERT(!resumeDecoding || decoder);
|
|
|
| - SkBitmap fullSizeImage;
|
| - bool complete = decode(index, &decoder, &fullSizeImage);
|
| + SkBitmap image;
|
| + bool complete = decode(index, &decoder, &image, outputType, outputSize, rowBytes);
|
|
|
| if (!decoder)
|
| return SkBitmap();
|
| @@ -229,7 +228,7 @@ SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_
|
| if (!resumeDecoding)
|
| decoderContainer = adoptPtr(decoder);
|
|
|
| - if (fullSizeImage.isNull()) {
|
| + if (image.isNull()) {
|
| // If decode has failed and resulted an empty image we can save work
|
| // in the future by returning early.
|
| m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();
|
| @@ -265,7 +264,7 @@ SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_
|
| } else if (!removeDecoder) {
|
| ImageDecodingStore::instance().insertDecoder(this, decoderContainer.release());
|
| }
|
| - return fullSizeImage;
|
| + return image;
|
| }
|
|
|
| void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha)
|
| @@ -280,19 +279,24 @@ void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha)
|
| m_hasAlpha[index] = hasAlpha;
|
| }
|
|
|
| -bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap)
|
| +bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap, SkColorType outputType, const SkISize& outputSize, size_t rowBytes)
|
| {
|
| TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.width(), "height", m_fullSize.height());
|
|
|
| ASSERT(decoder);
|
| SharedBuffer* data = 0;
|
| bool allDataReceived = false;
|
| - bool newDecoder = false;
|
| m_data.data(&data, &allDataReceived);
|
|
|
| + if (outputSize.width() != m_fullSize.width() || outputSize.height() != m_fullSize.height()) {
|
| + ASSERT(allDataReceived);
|
| + ASSERT(!m_isMultiFrame);
|
| + if (m_isMultiFrame || !allDataReceived)
|
| + return false;
|
| + }
|
| +
|
| // Try to create an ImageDecoder if we are not given one.
|
| if (!*decoder) {
|
| - newDecoder = true;
|
| if (m_imageDecoderFactory)
|
| *decoder = m_imageDecoderFactory->create().leakPtr();
|
|
|
| @@ -303,15 +307,25 @@ bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap*
|
| return false;
|
| }
|
|
|
| - if (!m_isMultiFrame && newDecoder && allDataReceived) {
|
| + if (!m_isMultiFrame && allDataReceived) {
|
| // If we're using an external memory allocator that means we're decoding
|
| // directly into the output memory and we can save one memcpy.
|
| ASSERT(m_externalAllocator.get());
|
| (*decoder)->setMemoryAllocator(m_externalAllocator.get());
|
| + if (outputType != kN32_SkColorType || outputSize.width() != m_fullSize.width() || outputSize.height() != m_fullSize.height()) {
|
| + size_t maxDecodeBytes = outputSize.height() * rowBytes;
|
| + if (!(*decoder)->activateDecodeAndScale(static_cast<ImageFrame::ColorType>(outputType), maxDecodeBytes)) {
|
| + ASSERT(false);
|
| + (*decoder)->setMemoryAllocator(0);
|
| + return false;
|
| + }
|
| + }
|
| }
|
| (*decoder)->setData(data, allDataReceived);
|
| -
|
| ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
|
| + // restore back to default
|
| + (*decoder)->disableDecodeAndScale();
|
| +
|
| // For multi-frame image decoders, we need to know how many frames are
|
| // in that image in order to release the decoder when all frames are
|
| // decoded. frameCount() is reliable only if all data is received and set in
|
| @@ -330,13 +344,13 @@ bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap*
|
| // Or we have received all data. The image might not be fully decoded in
|
| // the latter case.
|
| const bool isDecodeComplete = frame->status() == ImageFrame::FrameComplete || allDataReceived;
|
| - SkBitmap fullSizeBitmap = frame->getSkBitmap();
|
| - if (!fullSizeBitmap.isNull())
|
| + SkBitmap decodedBitmap = frame->getSkBitmap();
|
| + if (!decodedBitmap.isNull())
|
| {
|
| - ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.height() == m_fullSize.height());
|
| - setHasAlpha(index, !fullSizeBitmap.isOpaque());
|
| + ASSERT(decodedBitmap.width() == outputSize.width() && decodedBitmap.height() == outputSize.height());
|
| + setHasAlpha(index, !decodedBitmap.isOpaque());
|
| }
|
| - *bitmap = fullSizeBitmap;
|
| + *bitmap = decodedBitmap;
|
| return isDecodeComplete;
|
| }
|
|
|
| @@ -379,4 +393,30 @@ bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3])
|
| return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder::SizeForMemoryAllocation);
|
| }
|
|
|
| +void ImageFrameGenerator::getAvailableDecodeAndScale(SkColorType* outType, float* scale, float* lowerScale)
|
| +{
|
| + // as the same buffer could be used to store consecutive frames, avoid the complexity
|
| + // since some of consecutive frames could have alpha
|
| + if (m_isMultiFrame) {
|
| + // pass the same content as in default ImageDecoder
|
| + ImageDecoder::defaultDecodeAndScale(reinterpret_cast<ImageFrame::ColorType*>(outType), scale, lowerScale);
|
| + }
|
| +
|
| + // FIXME check how much this cost (decoder creation) and, also for getYUVComponentSizes,
|
| + // cache it in ImageDecodingStore for the real decode
|
| + SharedBuffer* data = 0;
|
| + bool allDataReceived = false;
|
| + m_data.data(&data, &allDataReceived);
|
| +
|
| + // partially received data needs to have alpha and skip downsampling
|
| + if (allDataReceived) {
|
| + OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremultiplied, ImageDecoder::GammaAndColorProfileApplied);
|
| + if (decoder) {
|
| + decoder->getAvailableDecodeAndScale(reinterpret_cast<ImageFrame::ColorType*>(outType), scale, lowerScale);
|
| + return;
|
| + }
|
| + }
|
| + ImageDecoder::defaultDecodeAndScale(reinterpret_cast<ImageFrame::ColorType*>(outType), scale, lowerScale);
|
| +}
|
| +
|
| } // namespace blink
|
|
|