зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1359833 - Part 2. IDecodingTask should use the event target from ProgressTracker for main thread runnables. r=tnikkel
This commit is contained in:
Родитель
25dd032904
Коммит
b37314e6ec
|
@ -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(¤t);
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче