Chromium Code Reviews| 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..2f0da222bf1e9fd1b4dd4a7272945605e2b3478f 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp |
| @@ -99,6 +99,7 @@ static bool updateYUVComponentSizes(ImageDecoder* decoder, SkISize componentSize |
| ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<SharedBuffer> data, bool allDataReceived, bool isMultiFrame) |
| : m_fullSize(fullSize) |
| + , m_data(new ThreadSafeDataTransport()) |
| , m_isMultiFrame(isMultiFrame) |
| , m_decodeFailedAndEmpty(false) |
| , m_decodeCount(0) |
| @@ -114,15 +115,50 @@ ImageFrameGenerator::~ImageFrameGenerator() |
| void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived) |
| { |
| - m_data.setData(data.get(), allDataReceived); |
| + m_data->setData(data.get(), allDataReceived); |
| } |
| -void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataReceived) |
| +static void sharedBufSkDataReleaseProc(const void* addr, void* ctx) |
| { |
| + ThreadSafeDataTransport* someonesMData = static_cast<ThreadSafeDataTransport*>(ctx); |
| + ASSERT(someonesMData); |
| + // Deref m_data now. |
| + someonesMData->deref(); |
| +} |
| + |
| +SkData* ImageFrameGenerator::refSkData() |
| +{ |
| + // Every SkData instance and SharedBuffer need to keep buffer->data() refcounted. |
| + // Both SkData and m_data.m_readBuffer are having separate ref counting implementations. |
| + // |
| + // SkData's SkData::NewWithProc is designed with similar use case in mind, |
| + // unmapping wrapped shmem data once all SkData instances are disposed. |
| + // in this case, sharedBufSkDataReleaseProc would just need to deref (since m_data.m_readBuffer |
| + // might still hold a reference) and that is happening in sharedBufSkDataReleaseProc. |
| + // |
| + // Preventing m_data disposal if ImageFrameGenerator is thread safe - SkData could get disposed |
| + // in any thread, and SkData would still need to hold the ref to SharedBuffer if ImageFrameGenerator |
| + // is deleted. This is why full m_data (ThreadSafeRefCounted) is passed to client - to hold the |
| + // reference to SharedBuffer (accompanying returned SkData). By contract in Skia's SkData, |
| + // client needs to call SkData unref that would end up in sharedBufSkDataReleaseProc |
| + // releasing the ref to ThreadSafeDataTransport (in thread safe way) and underlying SharedBuffer. |
| + // |
| + // A note about allDataReceived: |
| + // Client side use case is valid only for full image (encoded) data downloaded, |
| + // but, incidentally, this is in line with current Chromium implementation, where |
| + // DeferredImageDecoder::setData is called only once with allDataReceived and after |
| + // that m_data.m_readBuffer.data() is not changed. For the sake of not leaving loose ends, |
| + // ThreadSafeDataTransport::data is checking if there is new data added after AllDataReceived |
| + // was set to true. |
| SharedBuffer* buffer = 0; |
| - m_data.data(&buffer, allDataReceived); |
| - if (buffer) |
| - *data = buffer->copy(); |
| + bool allDataReceived = false; |
| + m_data->data(&buffer, &allDataReceived); |
| + if (!allDataReceived) |
| + return nullptr; |
| + |
| + // While SkData is holding reference to underlying data, prevent disposing m_data and it's content. |
|
scroggo_chromium
2015/12/02 20:15:02
its*
|
| + m_data->ref(); |
| + return SkData::NewWithProc(buffer->data(), buffer->size(), sharedBufSkDataReleaseProc, m_data.get()); |
|
scroggo_chromium
2015/12/02 20:15:02
What happens if the SharedBuffer's internal Vector
|
| } |
| bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes) |
| @@ -182,7 +218,7 @@ bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3] |
| SharedBuffer* data = 0; |
| bool allDataReceived = false; |
| - m_data.data(&data, &allDataReceived); |
| + m_data->data(&data, &allDataReceived); |
| // FIXME: YUV decoding does not currently support progressive decoding. |
| ASSERT(allDataReceived); |
| @@ -288,7 +324,7 @@ bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* |
| SharedBuffer* data = 0; |
| bool allDataReceived = false; |
| bool newDecoder = false; |
| - m_data.data(&data, &allDataReceived); |
| + m_data->data(&data, &allDataReceived); |
| // Try to create an ImageDecoder if we are not given one. |
| if (!*decoder) { |
| @@ -356,7 +392,7 @@ bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3]) |
| SharedBuffer* data = 0; |
| bool allDataReceived = false; |
| - m_data.data(&data, &allDataReceived); |
| + m_data->data(&data, &allDataReceived); |
| // FIXME: YUV decoding does not currently support progressive decoding. |
| if (!allDataReceived) |