/* static */ void IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage, NotNull<Decoder*> aDecoder) { MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(), "Decode complete in the middle of a frame?"); // Capture the decoder's state. DecoderFinalStatus finalStatus = aDecoder->FinalStatus(); ImageMetadata metadata = aDecoder->GetImageMetadata(); DecoderTelemetry telemetry = aDecoder->Telemetry(); Progress progress = aDecoder->TakeProgress(); IntRect invalidRect = aDecoder->TakeInvalidRect(); Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount(); SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags(); // Synchronously notify if we can. if (NS_IsMainThread() && !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) { aImage->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress, invalidRect, frameCount, surfaceFlags); return; } // We're forced to notify asynchronously. NotNull<RefPtr<RasterImage>> image = aImage; NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void { image->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress, invalidRect, frameCount, surfaceFlags); })); }
/* static */ void IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage, NotNull<Decoder*> aDecoder) { MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode()); // Capture the decoder's state. If we need to notify asynchronously, it's // important that we don't wait until the lambda actually runs to capture the // state that we're going to notify. That would both introduce data races on // the decoder's state and cause inconsistencies between the NotifyProgress() // calls we make off-main-thread and the notifications that RasterImage // actually receives, which would cause bugs. Progress progress = aDecoder->TakeProgress(); IntRect invalidRect = aDecoder->TakeInvalidRect(); Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount(); SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags(); // Synchronously notify if we can. if (NS_IsMainThread() && !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) { aImage->NotifyProgress(progress, invalidRect, frameCount, surfaceFlags); return; } // We're forced to notify asynchronously. NotNull<RefPtr<RasterImage>> image = aImage; NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void { image->NotifyProgress(progress, invalidRect, frameCount, surfaceFlags); })); }
static void NotifyProgress(NotNull<Decoder*> aDecoder) { MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode()); Progress progress = aDecoder->TakeProgress(); IntRect invalidRect = aDecoder->TakeInvalidRect(); Maybe<uint32_t> frameCount = aDecoder->TakeCompleteFrameCount(); SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags(); // Synchronously notify if we can. if (NS_IsMainThread() && !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) { aDecoder->GetImage()->NotifyProgress(progress, invalidRect, frameCount, surfaceFlags); return; } // We're forced to notify asynchronously. NotNull<RefPtr<Decoder>> decoder = aDecoder; NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void { decoder->GetImage()->NotifyProgress(progress, invalidRect, frameCount, surfaceFlags); })); }
/* static */ already_AddRefed<Decoder> DecoderFactory::CreateDecoderForICOResource(DecoderType aType, SourceBufferIterator&& aIterator, NotNull<nsICODecoder*> aICODecoder, bool aIsMetadataDecode, const Maybe<IntSize>& aExpectedSize, const Maybe<uint32_t>& aDataOffset /* = Nothing() */) { // Create the decoder. RefPtr<Decoder> decoder; switch (aType) { case DecoderType::BMP: MOZ_ASSERT(aDataOffset); decoder = new nsBMPDecoder(aICODecoder->GetImageMaybeNull(), *aDataOffset); break; case DecoderType::PNG: MOZ_ASSERT(!aDataOffset); decoder = new nsPNGDecoder(aICODecoder->GetImageMaybeNull()); break; default: MOZ_ASSERT_UNREACHABLE("Invalid ICO resource decoder type"); return nullptr; } MOZ_ASSERT(decoder); // Initialize the decoder, copying settings from @aICODecoder. decoder->SetMetadataDecode(aIsMetadataDecode); decoder->SetIterator(Forward<SourceBufferIterator>(aIterator)); if (!aIsMetadataDecode) { decoder->SetOutputSize(aICODecoder->OutputSize()); } if (aExpectedSize) { decoder->SetExpectedSize(*aExpectedSize); } decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags()); decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags()); decoder->SetFinalizeFrames(false); if (NS_FAILED(decoder->Init())) { return nullptr; } return decoder.forget(); }
static void NotifyDecodeComplete(NotNull<Decoder*> aDecoder) { // Synchronously notify if we can. if (NS_IsMainThread() && !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) { aDecoder->GetImage()->FinalizeDecoder(aDecoder); return; } // We're forced to notify asynchronously. NotNull<RefPtr<Decoder>> decoder = aDecoder; NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void { decoder->GetImage()->FinalizeDecoder(decoder.get()); })); }
/* static */ void IDecodingTask::NotifyProgress(NotNull<Decoder*> aDecoder) { MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode()); // Synchronously notify if we can. if (NS_IsMainThread() && !(aDecoder->GetDecoderFlags() & DecoderFlags::ASYNC_NOTIFY)) { aDecoder->GetImage()->NotifyProgress(aDecoder->TakeProgress(), aDecoder->TakeInvalidRect(), aDecoder->GetSurfaceFlags()); return; } // We're forced to notify asynchronously. NotNull<RefPtr<Decoder>> decoder = aDecoder; NS_DispatchToMainThread(NS_NewRunnableFunction([=]() -> void { decoder->GetImage()->NotifyProgress(decoder->TakeProgress(), decoder->TakeInvalidRect(), decoder->GetSurfaceFlags()); })); }