Bug 1894284. Give image gtests a threadsafe way to wait for decodes in the decode thread pool to finish. r=gfx-reviewers,nical

Differential Revision: https://phabricator.services.mozilla.com/D209510
This commit is contained in:
Timothy Nikkel 2024-05-22 03:29:18 +00:00
parent f5d75759b8
commit 8b707bc1b5
3 changed files with 68 additions and 13 deletions

View File

@ -88,7 +88,7 @@ class MetadataDecodingTask final : public IDecodingTask {
* An IDecodingTask implementation for anonymous decoders - that is, decoders
* with no associated Image object.
*/
class AnonymousDecodingTask final : public IDecodingTask {
class AnonymousDecodingTask : public IDecodingTask {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AnonymousDecodingTask, override)
@ -101,7 +101,7 @@ class AnonymousDecodingTask final : public IDecodingTask {
void Resume() override;
private:
protected:
virtual ~AnonymousDecodingTask() {}
NotNull<RefPtr<Decoder>> mDecoder;

View File

@ -5,6 +5,7 @@
#include "gtest/gtest.h"
#include "Common.h"
#include "mozilla/Monitor.h"
#include "AnimationSurfaceProvider.h"
#include "DecodePool.h"
#include "Decoder.h"
@ -122,6 +123,67 @@ static void CheckDecoderBadBuffer(const ImageTestCase& aTestCase) {
});
}
/**
* AnonymousDecodingTask but with a monitor so we can wait for it to finish
* safely.
*/
class MonitorAnonymousDecodingTask final : public AnonymousDecodingTask {
public:
explicit MonitorAnonymousDecodingTask(NotNull<Decoder*> aDecoder,
bool aResumable);
void Run() override;
void WaitUntilFinished();
private:
virtual ~MonitorAnonymousDecodingTask() = default;
Monitor mMonitor MOZ_UNANNOTATED;
};
MonitorAnonymousDecodingTask::MonitorAnonymousDecodingTask(
NotNull<Decoder*> aDecoder, bool aResumable)
: AnonymousDecodingTask(aDecoder, aResumable),
mMonitor("MonitorAnonymousDecodingTask") {}
void MonitorAnonymousDecodingTask::Run() {
MonitorAutoLock lock(mMonitor);
while (true) {
LexerResult result = mDecoder->Decode(WrapNotNull(this));
if (result.is<TerminalState>()) {
mMonitor.NotifyAll();
return; // We're done.
}
if (result == LexerResult(Yield::NEED_MORE_DATA)) {
// We can't make any more progress right now. Let the caller decide how to
// handle it.
mMonitor.NotifyAll();
return;
}
// Right now we don't do anything special for other kinds of yields, so just
// keep working.
MOZ_ASSERT(result.is<Yield>());
}
}
void MonitorAnonymousDecodingTask::WaitUntilFinished() {
MonitorAutoLock lock(mMonitor);
while (true) {
if (mDecoder->GetDecodeDone()) {
return;
}
// Not done yet, so we'll have to wait.
mMonitor.Wait();
}
}
template <typename Func>
void WithSingleChunkDecode(const ImageTestCase& aTestCase,
const Maybe<IntSize>& aOutputSize,
@ -150,15 +212,13 @@ void WithSingleChunkDecode(const ImageTestCase& aTestCase,
decoderType, sourceBuffer, aOutputSize, decoderFlags,
aTestCase.mSurfaceFlags);
ASSERT_TRUE(decoder != nullptr);
RefPtr<IDecodingTask> task =
new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
RefPtr<MonitorAnonymousDecodingTask> task = new MonitorAnonymousDecodingTask(
WrapNotNull(decoder), /* aResumable */ false);
if (aUseDecodePool) {
DecodePool::Singleton()->AsyncRun(task.get());
while (!decoder->GetDecodeDone()) {
task->Resume();
}
task->WaitUntilFinished();
} else { // Run the full decoder synchronously on the main thread.
task->Run();
}

View File

@ -12,6 +12,7 @@ UNIFIED_SOURCES = [
"TestAnimationFrameBuffer.cpp",
"TestBlendAnimationFilter.cpp",
"TestCopyOnWrite.cpp",
"TestDecoders.cpp",
"TestDecodersPerf.cpp",
"TestDecodeToSurface.cpp",
"TestDeinterlacingFilter.cpp",
@ -28,12 +29,6 @@ UNIFIED_SOURCES = [
"TestSwizzleFilter.cpp",
]
# Bug 1894284 - Fails under TSAN
if not CONFIG["MOZ_TSAN"]:
UNIFIED_SOURCES += [
"TestDecoders.cpp",
]
TEST_HARNESS_FILES.gtest += [
"animated-with-extra-image-sub-blocks.gif",
"blend.avif",