diff options
Diffstat (limited to 'image')
-rw-r--r-- | image/IDecodingTask.cpp | 15 | ||||
-rw-r--r-- | image/IDecodingTask.h | 8 | ||||
-rw-r--r-- | image/ImageOps.cpp | 2 | ||||
-rw-r--r-- | image/SourceBuffer.cpp | 14 | ||||
-rw-r--r-- | image/SourceBuffer.h | 7 | ||||
-rw-r--r-- | image/decoders/nsWebPDecoder.cpp | 4 |
6 files changed, 40 insertions, 10 deletions
diff --git a/image/IDecodingTask.cpp b/image/IDecodingTask.cpp index a067e7a7d..6e2f039be 100644 --- a/image/IDecodingTask.cpp +++ b/image/IDecodingTask.cpp @@ -142,8 +142,10 @@ MetadataDecodingTask::Run() // AnonymousDecodingTask implementation. /////////////////////////////////////////////////////////////////////////////// -AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder) +AnonymousDecodingTask::AnonymousDecodingTask(NotNull<Decoder*> aDecoder, + bool aResumable) : mDecoder(aDecoder) + , mResumable(aResumable) { } void @@ -168,5 +170,16 @@ AnonymousDecodingTask::Run() } } +void +AnonymousDecodingTask::Resume() +{ + // Anonymous decoders normally get all their data at once. We have some situations + // where they don't. If explicitly requested, resuming should be supported. + if (mResumable) { + RefPtr<AnonymousDecodingTask> self(this); + NS_DispatchToMainThread(NS_NewRunnableFunction([self]() -> void { self->Run(); })); + } +} + } // namespace image } // namespace mozilla diff --git a/image/IDecodingTask.h b/image/IDecodingTask.h index 196ce5fdc..3cbab5006 100644 --- a/image/IDecodingTask.h +++ b/image/IDecodingTask.h @@ -102,22 +102,20 @@ class AnonymousDecodingTask final : public IDecodingTask public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousDecodingTask, override) - explicit AnonymousDecodingTask(NotNull<Decoder*> aDecoder); + explicit AnonymousDecodingTask(NotNull<Decoder*> aDecoder, bool aResumable); void Run() override; bool ShouldPreferSyncRun() const override { return true; } TaskPriority Priority() const override { return TaskPriority::eLow; } - // Anonymous decoders normally get all their data at once. We have tests where - // they don't; in these situations, the test re-runs them manually. So no - // matter what, we don't want to resume by posting a task to the DecodePool. - void Resume() override { } + void Resume() override; private: virtual ~AnonymousDecodingTask() { } NotNull<RefPtr<Decoder>> mDecoder; + bool mResumable; }; } // namespace image diff --git a/image/ImageOps.cpp b/image/ImageOps.cpp index addee7f15..ddd2f200e 100644 --- a/image/ImageOps.cpp +++ b/image/ImageOps.cpp @@ -126,7 +126,7 @@ ImageOps::DecodeToSurface(nsIInputStream* aInputStream, } // Run the decoder synchronously. - RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder)); + RefPtr<IDecodingTask> task = new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false); task->Run(); if (!decoder->GetDecodeDone() || decoder->HasError()) { return nullptr; diff --git a/image/SourceBuffer.cpp b/image/SourceBuffer.cpp index de0719d45..de066e29f 100644 --- a/image/SourceBuffer.cpp +++ b/image/SourceBuffer.cpp @@ -451,10 +451,18 @@ SourceBuffer::AppendFromInputStream(nsIInputStream* aInputStream, uint32_t bytesRead; nsresult rv = aInputStream->ReadSegments(AppendToSourceBuffer, this, aCount, &bytesRead); - if (!NS_WARN_IF(NS_FAILED(rv))) { - MOZ_ASSERT(bytesRead == aCount, - "AppendToSourceBuffer should consume everything"); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (bytesRead == 0) { + // The loading of the image has been canceled. + return NS_ERROR_FAILURE; } + + MOZ_ASSERT(bytesRead == aCount, + "AppendToSourceBuffer should consume everything"); + return rv; } diff --git a/image/SourceBuffer.h b/image/SourceBuffer.h index 64727e65e..6f2c74d33 100644 --- a/image/SourceBuffer.h +++ b/image/SourceBuffer.h @@ -174,6 +174,13 @@ public: return mState == READY ? mData.mIterating.mNextReadLength : 0; } + /// If we're ready to read, returns whether or not everything available thus + /// far has been in the same contiguous buffer. + bool IsContiguous() const { + MOZ_ASSERT(mState == READY, "Calling IsContiguous() in the wrong state"); + return mState == READY ? mData.mIterating.mChunk == 0 : false; + } + /// @return a count of the chunks we've advanced through. uint32_t ChunkCount() const { return mChunkCount; } diff --git a/image/decoders/nsWebPDecoder.cpp b/image/decoders/nsWebPDecoder.cpp index 4f3cc8b2a..3181e3a3a 100644 --- a/image/decoders/nsWebPDecoder.cpp +++ b/image/decoders/nsWebPDecoder.cpp @@ -144,6 +144,10 @@ nsWebPDecoder::UpdateBuffer(SourceBufferIterator& aIterator, switch (aState) { case SourceBufferIterator::READY: + if(!aIterator.IsContiguous()) { + //We need to buffer. This should be rare, but expensive. + break; + } if (!mData) { // For as long as we hold onto an iterator, we know the data pointers // to the chunks cannot change underneath us, so save the pointer to |