Index: Source/platform/graphics/ImageFrameGenerator.cpp |
diff --git a/Source/platform/graphics/ImageFrameGenerator.cpp b/Source/platform/graphics/ImageFrameGenerator.cpp |
index 73c08f1236c6e4b7a7605aade37e30aae9b9e7e4..73189c0232da863ebb9aec06878ee2cde4bec00f 100644 |
--- a/Source/platform/graphics/ImageFrameGenerator.cpp |
+++ b/Source/platform/graphics/ImageFrameGenerator.cpp |
@@ -75,6 +75,7 @@ ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha |
: m_fullSize(fullSize) |
, m_isMultiFrame(isMultiFrame) |
, m_decodeFailedAndEmpty(false) |
+ , m_acceleratedYUVDecoding(false) |
, m_decodeCount(ScaledImageFragment::FirstPartialImage) |
, m_discardableAllocator(adoptPtr(new DiscardablePixelRefAllocator())) |
{ |
@@ -133,7 +134,7 @@ bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, |
ASSERT(m_fullSize == scaledSize); |
if (m_decodeFailedAndEmpty) |
- return 0; |
+ return false; |
TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", static_cast<int>(m_decodeCount)); |
@@ -169,6 +170,40 @@ bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, |
return result; |
} |
+bool ImageFrameGenerator::decodeAndScale(void* planes[3], size_t rowBytes[3]) |
+{ |
+ // This method is called to populate a discardable memory owned by Skia. |
+ |
+ // Prevents concurrent decode or scale operations on the same image data. |
+ MutexLocker lock(m_decodeMutex); |
+ |
+ if (m_decodeFailedAndEmpty) |
+ return false; |
+ |
+ TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", static_cast<int>(m_decodeCount)); |
+ |
+ m_acceleratedYUVDecoding = (0 != planes) && (0 != planes[0]) && (0 != planes[1]) && (0 != planes[2]) && (0 != rowBytes) && (0 != rowBytes[0]) && (0 != rowBytes[1]) && (0 != rowBytes[2]); |
+ if (!m_acceleratedYUVDecoding) { |
+ return false; |
+ } |
+ |
+ DecodingBuffers* decodingBuffers = new DecodingBuffers; |
+ decodingBuffers->set(planes, rowBytes); |
+ m_decodingBuffers = adoptPtr(decodingBuffers); |
+ |
+ ImageDecoder* decoder = 0; |
+ const bool isCached = ImageDecodingStore::instance()->lockDecoder(this, m_fullSize, &decoder); |
+ ASSERT(!isCached || decoder); |
+ |
+ decode(0, &decoder); |
+ |
+ if (isCached) { |
+ ImageDecodingStore::instance()->unlockDecoder(this, decoder); |
+ } |
+ |
+ return m_acceleratedYUVDecoding; |
+} |
+ |
const ScaledImageFragment* ImageFrameGenerator::tryToLockCompleteCache(const SkISize& scaledSize, size_t index) |
{ |
const ScaledImageFragment* cachedImage = 0; |
@@ -262,6 +297,11 @@ PassOwnPtr<ScaledImageFragment> ImageFrameGenerator::decode(size_t index, ImageD |
(*decoder)->setMemoryAllocator(m_discardableAllocator.get()); |
} |
(*decoder)->setData(data, allDataReceived); |
+ if (m_acceleratedYUVDecoding) { |
+ (*decoder)->setDecodingBuffers(m_decodingBuffers); |
+ m_acceleratedYUVDecoding = (*decoder)->doAcceleratedYUVDecoding(); |
+ return nullptr; |
+ } |
// 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 |
@@ -324,4 +364,55 @@ bool ImageFrameGenerator::hasAlpha(size_t index) |
return true; |
} |
+bool ImageFrameGenerator::getComponentSizes(SkISize componentSizes[3]) |
+{ |
+ if (!componentSizes) { |
+ return false; |
+ } |
+ |
+ TRACE_EVENT2("webkit", "ImageFrameGenerator::getImageFormat", "width", m_fullSize.width(), "height", m_fullSize.height()); |
+ |
+ ImageDecoder* decoder = 0; |
Peter Kasting
2014/07/24 18:08:14
Nit: Seems like this block should move down below
|
+ const bool isCached = ImageDecodingStore::instance()->lockDecoder(this, m_fullSize, &decoder); |
+ ASSERT(!isCached || decoder); |
+ |
+ SharedBuffer* data = 0; |
+ bool allDataReceived = false; |
+ m_data.data(&data, &allDataReceived); |
+ |
+ // If the decoder isn't cached, take ownership of it here |
+ OwnPtr<ImageDecoder> decoderContainer; |
+ if (!isCached) |
+ decoderContainer = adoptPtr(decoder); |
+ |
+ if (!decoder) { |
+ if (m_imageDecoderFactory) |
+ decoderContainer = adoptPtr(m_imageDecoderFactory->create().leakPtr()); |
Peter Kasting
2014/07/24 18:08:14
Do we actually have to call leakPtr() explicitly h
|
+ |
+ if (!decoderContainer.get()) |
+ decoderContainer = adoptPtr(ImageDecoder::create(*data, ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileApplied).leakPtr()); |
+ |
+ decoder = decoderContainer.get(); |
+ |
+ if (!decoder) |
+ return false; |
+ } |
+ |
+ decoder->setData(data, allDataReceived); |
+ decoder->setAcceleratedYUVDecoding(true); |
+ bool canComputeSize = decoder->acceleratedYUVDecoding() && decoder->isSizeAvailable(); |
+ if (canComputeSize) { |
+ IntSize size = decoder->decodedSize(0); |
+ componentSizes[0].set(size.width(), size.height()); |
+ size = decoder->decodedSize(1); |
+ componentSizes[1].set(size.width(), size.height()); |
+ size = decoder->decodedSize(2); |
+ componentSizes[2].set(size.width(), size.height()); |
+ } |
+ decoder->setData(0, false); // Unref SharedBuffer from ImageDecoder. |
+ if (isCached) |
+ ImageDecodingStore::instance()->unlockDecoder(this, decoder); |
+ return canComputeSize; |
+} |
+ |
} // namespace |