зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
fde6e769ba
Коммит
4bffc1c061
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче