Bug 1359833 - Part 2. IDecodingTask should use the event target from ProgressTracker for main thread runnables. r=tnikkel

This commit is contained in:
Andrew Osmond 2017-07-19 14:15:11 -04:00
Родитель 25dd032904
Коммит b37314e6ec
2 изменённых файлов: 63 добавлений и 17 удалений

Просмотреть файл

@ -13,6 +13,8 @@
#include "RasterImage.h"
#include "SurfaceCache.h"
#include "mozilla/SystemGroup.h"
namespace mozilla {
using gfx::IntRect;
@ -23,11 +25,47 @@ namespace image {
// Helpers for sending notifications to the image associated with a decoder.
///////////////////////////////////////////////////////////////////////////////
/* static */ void
void
IDecodingTask::EnsureHasEventTarget(NotNull<RasterImage*> aImage)
{
if (!mEventTarget) {
// We determine the event target as late as possible, at the first dispatch
// time, because the observers bound to an imgRequest will affect it.
// We cache it rather than query for the event target each time because the
// event target can change. We don't want to risk events being executed in
// a different order than they are dispatched, which can happen if we
// selected scheduler groups which have no ordering guarantees relative to
// each other (e.g. it moves from scheduler group A for doc group DA to
// scheduler group B for doc group DB due to changing observers -- if we
// dispatched the first event on A, and the second on B, we don't know which
// will execute first.)
RefPtr<ProgressTracker> tracker = aImage->GetProgressTracker();
if (tracker) {
mEventTarget = tracker->GetEventTarget();
} else {
mEventTarget = SystemGroup::EventTargetFor(TaskCategory::Other);
}
}
}
bool
IDecodingTask::IsOnEventTarget() const
{
// This is essentially equivalent to NS_IsOnMainThread() because all of the
// event targets are for the main thread (although perhaps with a different
// label / scheduler group). The observers in ProgressTracker may have
// different event targets from this, so this is just a best effort guess.
bool current = false;
mEventTarget->IsOnCurrentThread(&current);
return current;
}
void
IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder)
{
MOZ_ASSERT(aDecoder->HasProgress() && !aDecoder->IsMetadataDecode());
EnsureHasEventTarget(aImage);
// 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
@ -42,7 +80,7 @@ IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
// Synchronously notify if we can.
if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
if (IsOnEventTarget() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
aImage->NotifyProgress(progress, invalidRect, frameCount,
decoderFlags, surfaceFlags);
return;
@ -50,20 +88,21 @@ IDecodingTask::NotifyProgress(NotNull<RasterImage*> aImage,
// We're forced to notify asynchronously.
NotNull<RefPtr<RasterImage>> image = aImage;
NS_DispatchToMainThread(NS_NewRunnableFunction(
"IDecodingTask::NotifyProgress",
[=]() -> void {
mEventTarget->Dispatch(NS_NewRunnableFunction(
"IDecodingTask::NotifyProgress",
[=]() -> void {
image->NotifyProgress(progress, invalidRect, frameCount,
decoderFlags, surfaceFlags);
}));
}), NS_DISPATCH_NORMAL);
}
/* static */ void
void
IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder)
{
MOZ_ASSERT(aDecoder->HasError() || !aDecoder->InFrame(),
"Decode complete in the middle of a frame?");
EnsureHasEventTarget(aImage);
// Capture the decoder's state.
DecoderFinalStatus finalStatus = aDecoder->FinalStatus();
@ -76,7 +115,7 @@ IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
SurfaceFlags surfaceFlags = aDecoder->GetSurfaceFlags();
// Synchronously notify if we can.
if (NS_IsMainThread() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
if (IsOnEventTarget() && !(decoderFlags & DecoderFlags::ASYNC_NOTIFY)) {
aImage->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
invalidRect, frameCount, decoderFlags,
surfaceFlags);
@ -85,13 +124,13 @@ IDecodingTask::NotifyDecodeComplete(NotNull<RasterImage*> aImage,
// We're forced to notify asynchronously.
NotNull<RefPtr<RasterImage>> image = aImage;
NS_DispatchToMainThread(NS_NewRunnableFunction(
"IDecodingTask::NotifyDecodeComplete",
[=]() -> void {
mEventTarget->Dispatch(NS_NewRunnableFunction(
"IDecodingTask::NotifyDecodeComplete",
[=]() -> void {
image->NotifyDecodeComplete(finalStatus, metadata, telemetry, progress,
invalidRect, frameCount, decoderFlags,
surfaceFlags);
}));
}), NS_DISPATCH_NORMAL);
}

Просмотреть файл

@ -50,15 +50,22 @@ public:
void Resume() override;
protected:
virtual ~IDecodingTask() { }
/// Notify @aImage of @aDecoder's progress.
static void NotifyProgress(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder);
void NotifyProgress(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder);
/// Notify @aImage that @aDecoder has finished.
static void NotifyDecodeComplete(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder);
void NotifyDecodeComplete(NotNull<RasterImage*> aImage,
NotNull<Decoder*> aDecoder);
virtual ~IDecodingTask() { }
private:
void EnsureHasEventTarget(NotNull<RasterImage*> aImage);
bool IsOnEventTarget() const;
nsCOMPtr<nsIEventTarget> mEventTarget;
};