Bug 1449982 - Implement the WR updater thread registration. r=botond

This lets the APZUpdater know which thread is the actual updater thread.
This is only really used for the thread assertions, but might be useful
for debugging and such as well.

MozReview-Commit-ID: IIDm6Ui3Sh4

--HG--
extra : rebase_source : 575ba6c0c5d56276743e81e738e73e7672e08367
This commit is contained in:
Kartikaya Gupta 2018-04-10 12:29:55 -04:00
Родитель fde6e769ba
Коммит 4bffc1c061
2 изменённых файлов: 87 добавлений и 6 удалений

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

@ -9,6 +9,7 @@
#include <unordered_map>
#include "base/platform_thread.h" // for PlatformThreadId
#include "LayersTypes.h"
#include "mozilla/layers/APZTestData.h"
#include "mozilla/StaticMutex.h"
@ -44,6 +45,14 @@ public:
bool HasTreeManager(const RefPtr<APZCTreeManager>& aApz);
void SetWebRenderWindowId(const wr::WindowId& aWindowId);
/**
* This function is invoked from rust on the scene builder thread when it
* is created. It effectively tells the APZUpdater "the current thread is
* the updater thread for this window id" and allows APZUpdater to remember
* which thread it is.
*/
static void SetUpdaterThread(const wr::WrWindowId& aWindowId);
void ClearTree();
void UpdateFocusState(LayersId aRootLayerTreeId,
LayersId aOriginatingLayersId,
@ -104,6 +113,9 @@ public:
protected:
virtual ~APZUpdater();
bool UsingWebRenderUpdaterThread() const;
static already_AddRefed<APZUpdater> GetUpdater(const wr::WrWindowId& aWindowId);
private:
RefPtr<APZCTreeManager> mApz;
@ -113,6 +125,21 @@ private:
static StaticMutex sWindowIdLock;
static std::unordered_map<uint64_t, APZUpdater*> sWindowIdMap;
Maybe<wr::WrWindowId> mWindowId;
// If WebRender and async scene building are enabled, this holds the thread id
// of the scene builder thread (which is the updater thread) for the
// compositor associated with this APZUpdater instance. It may be populated
// even if async scene building is not enabled, but in that case we don't
// care about the contents.
// This is written to once during init and never cleared, and so reading it
// from multiple threads during normal operation (after initialization)
// without locking should be fine.
Maybe<PlatformThreadId> mUpdaterThreadId;
#ifdef DEBUG
// This flag is used to ensure that we don't ever try to do updater-thread
// stuff before the updater thread has been properly initialized.
mutable bool mUpdaterThreadQueried;
#endif
};
} // namespace layers

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

@ -24,6 +24,9 @@ std::unordered_map<uint64_t, APZUpdater*> APZUpdater::sWindowIdMap;
APZUpdater::APZUpdater(const RefPtr<APZCTreeManager>& aApz)
: mApz(aApz)
#ifdef DEBUG
, mUpdaterThreadQueried(false)
#endif
{
MOZ_ASSERT(aApz);
mApz->SetUpdater(this);
@ -55,6 +58,16 @@ APZUpdater::SetWebRenderWindowId(const wr::WindowId& aWindowId)
sWindowIdMap[wr::AsUint64(aWindowId)] = this;
}
/*static*/ void
APZUpdater::SetUpdaterThread(const wr::WrWindowId& aWindowId)
{
if (RefPtr<APZUpdater> updater = GetUpdater(aWindowId)) {
// Ensure nobody tried to use the updater thread before this point.
MOZ_ASSERT(!updater->mUpdaterThreadQueried);
updater->mUpdaterThreadId = Some(PlatformThread::CurrentId());
}
}
void
APZUpdater::ClearTree()
{
@ -235,23 +248,31 @@ APZUpdater::RunOnUpdaterThread(already_AddRefed<Runnable> aTask)
{
RefPtr<Runnable> task = aTask;
MessageLoop* loop = CompositorThreadHolder::Loop();
if (!loop) {
// Could happen during startup
if (IsUpdaterThread()) {
task->Run();
return;
}
if (UsingWebRenderUpdaterThread()) {
// TODO
NS_WARNING("Dropping task posted to updater thread");
return;
}
if (IsUpdaterThread()) {
task->Run();
} else {
if (MessageLoop* loop = CompositorThreadHolder::Loop()) {
loop->PostTask(task.forget());
} else {
// Could happen during startup
NS_WARNING("Dropping task posted to updater thread");
}
}
bool
APZUpdater::IsUpdaterThread()
{
if (UsingWebRenderUpdaterThread()) {
return PlatformThread::CurrentId() == *mUpdaterThreadId;
}
return CompositorThreadHolder::IsInCompositorThread();
}
@ -266,6 +287,38 @@ APZUpdater::RunOnControllerThread(already_AddRefed<Runnable> aTask)
Move(aTask)));
}
bool
APZUpdater::UsingWebRenderUpdaterThread() const
{
if (!gfxPrefs::WebRenderAsyncSceneBuild()) {
return false;
}
// If mUpdaterThreadId is not set at the point that this is called, then
// that means that either (a) WebRender is not enabled for the compositor
// to which this APZUpdater is attached or (b) we are attempting to do
// something updater-related before WebRender is up and running. In case
// (a) falling back to the compositor thread is correct, and in case (b)
// we should stop doing the updater-related thing so early. We catch this
// case by setting the mUpdaterThreadQueried flag and asserting on WR
// initialization.
#ifdef DEBUG
mUpdaterThreadQueried = true;
#endif
return mUpdaterThreadId.isSome();
}
/*static*/ already_AddRefed<APZUpdater>
APZUpdater::GetUpdater(const wr::WrWindowId& aWindowId)
{
RefPtr<APZUpdater> updater;
StaticMutexAutoLock lock(sWindowIdLock);
auto it = sWindowIdMap.find(wr::AsUint64(aWindowId));
if (it != sWindowIdMap.end()) {
updater = it->second;
}
return updater.forget();
}
} // namespace layers
} // namespace mozilla
@ -274,6 +327,7 @@ APZUpdater::RunOnControllerThread(already_AddRefed<Runnable> aTask)
void
apz_register_updater(mozilla::wr::WrWindowId aWindowId)
{
mozilla::layers::APZUpdater::SetUpdaterThread(aWindowId);
}
void