Bug 1449982 - Maintain a map from WrWindowId to APZUpdater. r?botond
This will allow callbacks from rust code to get a handle to the
necessary APZUpdater instance on which to invoke functions.
MozReview-Commit-ID: 13XdzZrrtI5
--- a/gfx/layers/apz/public/APZUpdater.h
+++ b/gfx/layers/apz/public/APZUpdater.h
@@ -2,22 +2,30 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_layers_APZUpdater_h
#define mozilla_layers_APZUpdater_h
+#include <unordered_map>
+
#include "LayersTypes.h"
#include "mozilla/layers/APZTestData.h"
+#include "mozilla/StaticMutex.h"
#include "nsThreadUtils.h"
#include "Units.h"
namespace mozilla {
+
+namespace wr {
+struct WrWindowId;
+} // namespace wr
+
namespace layers {
class APZCTreeManager;
class FocusTarget;
class Layer;
class WebRenderScrollData;
/**
@@ -29,16 +37,17 @@ class WebRenderScrollData;
*/
class APZUpdater {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZUpdater)
public:
explicit APZUpdater(const RefPtr<APZCTreeManager>& aApz);
bool HasTreeManager(const RefPtr<APZCTreeManager>& aApz);
+ void SetWebRenderWindowId(const wr::WindowId& aWindowId);
void ClearTree();
void UpdateFocusState(LayersId aRootLayerTreeId,
LayersId aOriginatingLayersId,
const FocusTarget& aFocusTarget);
void UpdateHitTestingTree(LayersId aRootLayerTreeId,
Layer* aRoot,
bool aIsFirstPaint,
@@ -92,14 +101,21 @@ public:
*/
void RunOnControllerThread(already_AddRefed<Runnable> aTask);
protected:
virtual ~APZUpdater();
private:
RefPtr<APZCTreeManager> mApz;
+
+ // Used to manage the mapping from a WR window id to APZUpdater. These are only
+ // used if WebRender is enabled. Both sWindowIdMap and mWindowId should only
+ // be used while holding the sWindowIdLock.
+ static StaticMutex sWindowIdLock;
+ static std::unordered_map<uint64_t, APZUpdater*> sWindowIdMap;
+ Maybe<wr::WrWindowId> mWindowId;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_APZUpdater_h
--- a/gfx/layers/apz/src/APZUpdater.cpp
+++ b/gfx/layers/apz/src/APZUpdater.cpp
@@ -8,46 +8,78 @@
#include "APZCTreeManager.h"
#include "AsyncPanZoomController.h"
#include "base/task.h"
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/SynchronousTask.h"
#include "mozilla/layers/WebRenderScrollData.h"
+#include "mozilla/webrender/WebRenderTypes.h"
namespace mozilla {
namespace layers {
+StaticMutex APZUpdater::sWindowIdLock;
+std::unordered_map<uint64_t, APZUpdater*> APZUpdater::sWindowIdMap;
+
+
APZUpdater::APZUpdater(const RefPtr<APZCTreeManager>& aApz)
: mApz(aApz)
{
MOZ_ASSERT(aApz);
mApz->SetUpdater(this);
}
APZUpdater::~APZUpdater()
{
mApz->SetUpdater(nullptr);
+
+ StaticMutexAutoLock lock(sWindowIdLock);
+ if (mWindowId) {
+ // Ensure that ClearTree was called and the task got run
+ MOZ_ASSERT(sWindowIdMap.find(wr::AsUint64(*mWindowId)) == sWindowIdMap.end());
+ }
}
bool
APZUpdater::HasTreeManager(const RefPtr<APZCTreeManager>& aApz)
{
return aApz.get() == mApz.get();
}
void
+APZUpdater::SetWebRenderWindowId(const wr::WindowId& aWindowId)
+{
+ StaticMutexAutoLock lock(sWindowIdLock);
+ MOZ_ASSERT(!mWindowId);
+ mWindowId = Some(aWindowId);
+ sWindowIdMap[wr::AsUint64(aWindowId)] = this;
+}
+
+void
APZUpdater::ClearTree()
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
- RunOnUpdaterThread(NewRunnableMethod(
- "APZUpdater::ClearTree",
- mApz,
- &APZCTreeManager::ClearTree));
+ RefPtr<APZUpdater> self = this;
+ RunOnUpdaterThread(NS_NewRunnableFunction(
+ "APZUpdater::ClearTree",
+ [=]() {
+ self->mApz->ClearTree();
+
+ // Once ClearTree is called on the APZCTreeManager, we are in a shutdown
+ // phase. After this point it's ok if WebRender cannot get a hold of the
+ // updater via the window id, and it's a good point to remove the mapping
+ // and avoid leaving a dangling pointer to this object.
+ StaticMutexAutoLock lock(sWindowIdLock);
+ if (self->mWindowId) {
+ sWindowIdMap.erase(wr::AsUint64(*(self->mWindowId)));
+ }
+ }
+ ));
}
void
APZUpdater::UpdateFocusState(LayersId aRootLayerTreeId,
LayersId aOriginatingLayersId,
const FocusTarget& aFocusTarget)
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1762,16 +1762,22 @@ CompositorBridgeParent::AllocPWebRenderB
MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
MOZ_ASSERT(!mWrBridge);
MOZ_ASSERT(!mCompositor);
MOZ_ASSERT(!mCompositorScheduler);
MOZ_ASSERT(mWidget);
RefPtr<widget::CompositorWidget> widget = mWidget;
wr::WrWindowId windowId = wr::NewWindowId();
+ if (mApzUpdater) {
+ // If APZ is enabled, we need to register the APZ updater with the window id
+ // before the updater thread is created in WebRenderAPI::Create, so
+ // that the callback from the updater thread can find the right APZUpdater.
+ mApzUpdater->SetWebRenderWindowId(windowId);
+ }
RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(this, Move(widget), windowId, aSize);
if (!api) {
mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
mWrBridge.get()->AddRef(); // IPDL reference
*aIdNamespace = mWrBridge->GetIdNamespace();
*aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
return mWrBridge;
}