Bug 1860677 - Do not create task queue for CanvasTranslator if not using workers. r=gfx-reviewers,lsalzman

The task queue makes NS_DECL_OWNINGEVENTTARGET confusing for single
threaded uses, when the canvas expects it can just dispatch to the
CanvasRenderThread directly.

Differential Revision: https://phabricator.services.mozilla.com/D191697
This commit is contained in:
Andrew Osmond 2023-10-24 12:43:37 +00:00
parent 57a88e0d3d
commit 1735eca794
4 changed files with 56 additions and 28 deletions

View File

@ -205,18 +205,12 @@ already_AddRefed<nsIThread> CanvasRenderThread::GetCanvasRenderThread() {
return thread.forget();
}
/* static */ already_AddRefed<TaskQueue> CanvasRenderThread::CreateTaskQueue(
bool aPreferWorkers) {
if (!sCanvasRenderThread) {
/* static */ already_AddRefed<TaskQueue>
CanvasRenderThread::CreateWorkerTaskQueue() {
if (!sCanvasRenderThread || !sCanvasRenderThread->mWorkers) {
return nullptr;
}
if (!aPreferWorkers || !sCanvasRenderThread->mWorkers) {
return TaskQueue::Create(do_AddRef(sCanvasRenderThread->mThread),
"CanvasWorker")
.forget();
}
return TaskQueue::Create(do_AddRef(sCanvasRenderThread->mWorkers),
"CanvasWorker")
.forget();

View File

@ -51,7 +51,7 @@ class CanvasRenderThread final {
/// Can be called from any thread, may return nullptr late in shutdown.
static already_AddRefed<nsIThread> GetCanvasRenderThread();
static already_AddRefed<TaskQueue> CreateTaskQueue(bool aPreferWorkers);
static already_AddRefed<TaskQueue> CreateWorkerTaskQueue();
static void Dispatch(already_AddRefed<nsIRunnable> aRunnable);

View File

@ -79,6 +79,22 @@ CanvasTranslator::~CanvasTranslator() {
mBaseDT = nullptr;
}
void CanvasTranslator::DispatchToTaskQueue(
already_AddRefed<nsIRunnable> aRunnable) {
if (mTranslationTaskQueue) {
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(std::move(aRunnable)));
} else {
gfx::CanvasRenderThread::Dispatch(std::move(aRunnable));
}
}
bool CanvasTranslator::IsInTaskQueue() const {
if (mTranslationTaskQueue) {
return mTranslationTaskQueue->IsCurrentThreadIn();
}
return gfx::CanvasRenderThread::IsInCanvasRenderThread();
}
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
const TextureType& aTextureType,
ipc::SharedMemoryBasic::Handle&& aReadHandle,
@ -96,39 +112,41 @@ mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
if (!mStream->InitReader(std::move(aReadHandle), std::move(aReaderSem),
std::move(aWriterSem),
MakeUnique<RingBufferReaderServices>(this))) {
mStream = nullptr;
return IPC_FAIL(this, "Failed to initialize ring buffer reader.");
}
#if defined(XP_WIN)
if (!CheckForFreshCanvasDevice(__LINE__)) {
gfxCriticalNote << "GFX: CanvasTranslator failed to get device";
mStream = nullptr;
return IPC_OK();
}
#endif
mTranslationTaskQueue =
gfx::CanvasRenderThread::CreateTaskQueue(!aUseIPDLThread);
if (!aUseIPDLThread) {
mTranslationTaskQueue = gfx::CanvasRenderThread::CreateWorkerTaskQueue();
}
return RecvResumeTranslation();
}
ipc::IPCResult CanvasTranslator::RecvNewBuffer(
ipc::SharedMemoryBasic::Handle&& aReadHandle) {
if (!mTranslationTaskQueue) {
if (!mStream) {
return IPC_FAIL(this, "RecvNewBuffer before RecvInitTranslator.");
}
// We need to set the new buffer on the transaltion queue to be sure that the
// We need to set the new buffer on the translation queue to be sure that the
// drop buffer event has been processed.
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(NS_NewRunnableFunction(
DispatchToTaskQueue(NS_NewRunnableFunction(
"CanvasTranslator SetNewBuffer",
[self = RefPtr(this), readHandle = std::move(aReadHandle)]() mutable {
self->mStream->SetNewBuffer(std::move(readHandle));
})));
}));
return RecvResumeTranslation();
}
ipc::IPCResult CanvasTranslator::RecvResumeTranslation() {
if (!mTranslationTaskQueue) {
if (!mStream) {
return IPC_FAIL(this, "RecvResumeTranslation before RecvInitTranslator.");
}
if (CheckDeactivated()) {
@ -136,10 +154,9 @@ ipc::IPCResult CanvasTranslator::RecvResumeTranslation() {
return IPC_OK();
}
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
NewRunnableMethod("CanvasTranslator::StartTranslation", this,
&CanvasTranslator::StartTranslation)));
DispatchToTaskQueue(NewRunnableMethod("CanvasTranslator::StartTranslation",
this,
&CanvasTranslator::StartTranslation));
return IPC_OK();
}
@ -148,9 +165,9 @@ void CanvasTranslator::StartTranslation() {
"StartTranslation called before buffer has been set.");
if (!TranslateRecording() && CanSend()) {
MOZ_ALWAYS_SUCCEEDS(mTranslationTaskQueue->Dispatch(
NewRunnableMethod("CanvasTranslator::StartTranslation", this,
&CanvasTranslator::StartTranslation)));
DispatchToTaskQueue(NewRunnableMethod("CanvasTranslator::StartTranslation",
this,
&CanvasTranslator::StartTranslation));
}
// If the stream has been marked as bad and the Writer hasn't failed,
@ -166,7 +183,10 @@ void CanvasTranslator::ActorDestroy(ActorDestroyReason why) {
MOZ_ASSERT(gfx::CanvasRenderThread::IsInCanvasRenderThread());
if (!mTranslationTaskQueue) {
return FinishShutdown();
gfx::CanvasRenderThread::Dispatch(
NewRunnableMethod("CanvasTranslator::FinishShutdown", this,
&CanvasTranslator::FinishShutdown));
return;
}
mTranslationTaskQueue->BeginShutdown()->Then(
@ -219,10 +239,11 @@ void CanvasTranslator::Deactivate() {
}
bool CanvasTranslator::TranslateRecording() {
if (!mTranslationTaskQueue) {
MOZ_ASSERT(IsInTaskQueue());
if (!mStream) {
return false;
}
MOZ_ASSERT(mTranslationTaskQueue->IsCurrentThreadIn());
uint8_t eventType = mStream->ReadNextEvent();
while (mStream->good() && eventType != kDropBufferEventType) {

View File

@ -34,6 +34,19 @@ class CanvasTranslator final : public gfx::InlineTranslator,
CanvasTranslator();
/**
* Dispatches a runnable to the preferred task queue or thread.
*
* @param aRunnable the runnable to dispatch
*/
void DispatchToTaskQueue(already_AddRefed<nsIRunnable> aRunnable);
/**
* @returns true if running in the preferred task queue or thread for
* translation.
*/
bool IsInTaskQueue() const;
/**
* Initialize the canvas translator for a particular TextureType and
* CanvasEventRingBuffer.