diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 6d874c6f1677..0e4c39a9e5c6 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -1140,3 +1140,6 @@ pref("dom.activities.developer_mode_only", "import-app"); // mulet apparently loads firefox.js as well as b2g.js, so we have to explicitly // disable serviceworkers here to get them disabled in mulet. pref("dom.serviceWorkers.enabled", false); + +// Retain at most 10 processes' layers buffers +pref("layers.compositor-lru-size", 10); diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index cc80fa7c2f47..977fc58db8c9 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -2985,17 +2985,23 @@ TabChild::NotifyPainted() void TabChild::MakeVisible() { - if (mWidget) { - mWidget->Show(true); - } + CompositorChild* compositor = CompositorChild::Get(); + compositor->SendNotifyVisible(mLayersId); + + if (mWidget) { + mWidget->Show(true); + } } void TabChild::MakeHidden() { - if (mWidget) { - mWidget->Show(false); - } + CompositorChild* compositor = CompositorChild::Get(); + compositor->SendNotifyHidden(mLayersId); + + if (mWidget) { + mWidget->Show(false); + } } void @@ -3137,6 +3143,17 @@ TabChild::DidComposite(uint64_t aTransactionId) manager->DidComposite(aTransactionId); } +void +TabChild::ClearCachedResources() +{ + MOZ_ASSERT(mWidget); + MOZ_ASSERT(mWidget->GetLayerManager()); + MOZ_ASSERT(mWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT); + + ClientLayerManager *manager = static_cast(mWidget->GetLayerManager()); + manager->ClearCachedResources(); +} + NS_IMETHODIMP TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText) { diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 93901877fd64..b2c02a8114ed 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -474,6 +474,7 @@ public: static TabChild* GetFrom(uint64_t aLayersId); void DidComposite(uint64_t aTransactionId); + void ClearCachedResources(); static inline TabChild* GetFrom(nsIDOMWindow* aWindow) diff --git a/gfx/layers/ipc/CompositorChild.cpp b/gfx/layers/ipc/CompositorChild.cpp index 02609081c00c..8d6dc049e948 100644 --- a/gfx/layers/ipc/CompositorChild.cpp +++ b/gfx/layers/ipc/CompositorChild.cpp @@ -372,6 +372,16 @@ CompositorChild::AddOverfillObserver(ClientLayerManager* aLayerManager) mOverfillObservers.AppendElement(aLayerManager); } +bool +CompositorChild::RecvClearCachedResources(const uint64_t& aId) +{ + dom::TabChild* child = dom::TabChild::GetFrom(aId); + if (child) { + child->ClearCachedResources(); + } + return true; +} + void CompositorChild::ActorDestroy(ActorDestroyReason aWhy) { @@ -549,6 +559,26 @@ CompositorChild::SendResume() return PCompositorChild::SendResume(); } +bool +CompositorChild::SendNotifyHidden(const uint64_t& id) +{ + MOZ_ASSERT(mCanSend); + if (!mCanSend) { + return true; + } + return PCompositorChild::SendNotifyHidden(id); +} + +bool +CompositorChild::SendNotifyVisible(const uint64_t& id) +{ + MOZ_ASSERT(mCanSend); + if (!mCanSend) { + return true; + } + return PCompositorChild::SendNotifyVisible(id); +} + bool CompositorChild::SendNotifyChildCreated(const uint64_t& id) { diff --git a/gfx/layers/ipc/CompositorChild.h b/gfx/layers/ipc/CompositorChild.h index c5d595646739..77a24279fe11 100644 --- a/gfx/layers/ipc/CompositorChild.h +++ b/gfx/layers/ipc/CompositorChild.h @@ -70,6 +70,9 @@ public: void AddOverfillObserver(ClientLayerManager* aLayerManager); + virtual bool + RecvClearCachedResources(const uint64_t& id) override; + virtual bool RecvDidComposite(const uint64_t& aId, const uint64_t& aTransactionId) override; @@ -106,6 +109,8 @@ public: bool SendWillStop(); bool SendPause(); bool SendResume(); + bool SendNotifyHidden(const uint64_t& id); + bool SendNotifyVisible(const uint64_t& id); bool SendNotifyChildCreated(const uint64_t& id); bool SendAdoptChild(const uint64_t& id); bool SendMakeSnapshot(const SurfaceDescriptor& inSnapshot, const gfx::IntRect& dirtyRect); diff --git a/gfx/layers/ipc/CompositorLRU.cpp b/gfx/layers/ipc/CompositorLRU.cpp new file mode 100644 index 000000000000..ac934a992e3f --- /dev/null +++ b/gfx/layers/ipc/CompositorLRU.cpp @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* 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/. */ + +#include "CompositorLRU.h" + +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/Preferences.h" +#include "mozilla/unused.h" + +#include "CompositorParent.h" + +namespace mozilla { +namespace layers { + +mozilla::StaticRefPtr CompositorLRU::sSingleton; + +void +CompositorLRU::Init() +{ + unused << GetSingleton(); +} + +CompositorLRU* +CompositorLRU::GetSingleton() +{ + if (sSingleton) { + return sSingleton; + } + sSingleton = new CompositorLRU(); + ClearOnShutdown(&sSingleton); + + return sSingleton; +} + +CompositorLRU::CompositorLRU() +{ + mLRUSize = Preferences::GetUint("layers.compositor-lru-size", uint32_t(0)); +} + +CompositorLRU::~CompositorLRU() +{ +} + +void +CompositorLRU::Add(PCompositorParent* aCompositor, const uint64_t& aId) +{ + auto index = mLRU.IndexOf(std::make_pair(aCompositor, aId)); + if (index != nsTArray::NoIndex) { + return; + } + + if (mLRUSize == 0) { + unused << aCompositor->SendClearCachedResources(aId); + return; + } + + if (mLRU.Length() == mLRUSize) { + CompositorLayerPair victim = mLRU.LastElement(); + unused << victim.first->SendClearCachedResources(victim.second); + mLRU.RemoveElement(victim); + } + mLRU.InsertElementAt(0, std::make_pair(aCompositor, aId)); +} + +void +CompositorLRU::Remove(PCompositorParent* aCompositor, const uint64_t& aId) +{ + if (mLRUSize == 0) { + return; + } + + auto index = mLRU.IndexOf(std::make_pair(aCompositor, aId)); + + if (index == nsTArray::NoIndex) { + return; + } + + mLRU.RemoveElementAt(index); +} + +void +CompositorLRU::Remove(PCompositorParent* aCompositor) +{ + if (mLRUSize == 0) { + return; + } + + for (int32_t i = mLRU.Length() - 1; i >= 0; --i) { + if (mLRU[i].first == aCompositor) { + mLRU.RemoveElementAt(i); + } + } +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/layers/ipc/CompositorLRU.h b/gfx/layers/ipc/CompositorLRU.h new file mode 100644 index 000000000000..adb294cf8af7 --- /dev/null +++ b/gfx/layers/ipc/CompositorLRU.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=8 et : + */ +/* 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_CompositorLRU_h +#define mozilla_CompositorLRU_h + +#include "mozilla/StaticPtr.h" + +#include "nsISupportsImpl.h" +#include "nsTArray.h" + +#include + +namespace mozilla { +namespace layers { + +class PCompositorParent; + +class CompositorLRU final +{ + typedef std::pair CompositorLayerPair; +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorLRU) + + static void Init(); + static CompositorLRU* GetSingleton(); + + /** + * Adds the (PCompositorParent, LayerId) pair to the LRU pool. If + * the pool size grows over mLRUSize, the oldest PCompositorParent + * is evicted. + */ + void Add(PCompositorParent* aCompositor, const uint64_t& id); + + /** + * Remove the (PCompositorParent, LayersId) pair from the LRU pool. + */ + void Remove(PCompositorParent* aCompositor, const uint64_t& id); + + /** + * Remove all PCompositorParents from the LRU pool. + */ + void Remove(PCompositorParent* aCompositor); + +private: + static StaticRefPtr sSingleton; + + CompositorLRU(); + ~CompositorLRU(); + uint32_t mLRUSize; + nsTArray mLRU; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_CompositorLRU_h diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 03b269eb6184..787bd0f9cbea 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -34,6 +34,7 @@ #include "mozilla/layers/AsyncCompositionManager.h" #include "mozilla/layers/BasicCompositor.h" // for BasicCompositor #include "mozilla/layers/Compositor.h" // for Compositor +#include "mozilla/layers/CompositorLRU.h" // for CompositorLRU #include "mozilla/layers/CompositorOGL.h" // for CompositorOGL #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/LayerManagerComposite.h" @@ -1686,6 +1687,8 @@ public: virtual bool RecvStop() override { return true; } virtual bool RecvPause() override { return true; } virtual bool RecvResume() override { return true; } + virtual bool RecvNotifyHidden(const uint64_t& id) override; + virtual bool RecvNotifyVisible(const uint64_t& id) override; virtual bool RecvNotifyChildCreated(const uint64_t& child) override; virtual bool RecvAdoptChild(const uint64_t& child) override { return false; } virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot, @@ -1841,6 +1844,22 @@ CompositorParent::GetIndirectShadowTree(uint64_t aId) return &cit->second; } +bool +CrossProcessCompositorParent::RecvNotifyHidden(const uint64_t& id) +{ + nsRefPtr lru = CompositorLRU::GetSingleton(); + lru->Add(this, id); + return true; +} + +bool +CrossProcessCompositorParent::RecvNotifyVisible(const uint64_t& id) +{ + nsRefPtr lru = CompositorLRU::GetSingleton(); + lru->Remove(this, id); + return true; +} + bool CrossProcessCompositorParent::RecvRequestNotifyAfterRemotePaint() { @@ -1851,6 +1870,9 @@ CrossProcessCompositorParent::RecvRequestNotifyAfterRemotePaint() void CrossProcessCompositorParent::ActorDestroy(ActorDestroyReason aWhy) { + nsRefPtr lru = CompositorLRU::GetSingleton(); + lru->Remove(this); + MessageLoop::current()->PostTask( FROM_HERE, NewRunnableMethod(this, &CrossProcessCompositorParent::DeferredDestroy)); diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 3bce283277a3..bedf15d0554c 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -234,6 +234,8 @@ public: virtual bool RecvStop() override; virtual bool RecvPause() override; virtual bool RecvResume() override; + virtual bool RecvNotifyHidden(const uint64_t& id) override { return true; } + virtual bool RecvNotifyVisible(const uint64_t& id) override { return true; } virtual bool RecvNotifyChildCreated(const uint64_t& child) override; virtual bool RecvAdoptChild(const uint64_t& child) override; virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot, diff --git a/gfx/layers/ipc/PCompositor.ipdl b/gfx/layers/ipc/PCompositor.ipdl index ba3620506bec..17f73317f157 100644 --- a/gfx/layers/ipc/PCompositor.ipdl +++ b/gfx/layers/ipc/PCompositor.ipdl @@ -70,6 +70,12 @@ child: */ async UpdatePluginVisibility(uintptr_t[] aVisibleIdList); + /** + * Drop any buffers that might be retained on the child compositor + * side. + */ + async ClearCachedResources(uint64_t id); + parent: // Child sends the parent a request for fill ratio numbers. async RequestOverfill(); @@ -85,6 +91,14 @@ parent: sync Pause(); sync Resume(); + // The child layer tree is hidden. id is the layers id of the child + // layer tree. + async NotifyHidden(uint64_t id); + + // The child layer tree is visible. id is the layers id of the child + // layer tree. + async NotifyVisible(uint64_t id); + async NotifyChildCreated(uint64_t id); async AdoptChild(uint64_t id); diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 22c38f4ba399..e2c41155d69f 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -139,6 +139,7 @@ EXPORTS.mozilla.layers += [ 'ipc/CompositableForwarder.h', 'ipc/CompositableTransactionParent.h', 'ipc/CompositorChild.h', + 'ipc/CompositorLRU.h', 'ipc/CompositorParent.h', 'ipc/FenceUtils.h', 'ipc/ImageBridgeChild.h', @@ -294,6 +295,7 @@ UNIFIED_SOURCES += [ 'ipc/CompositableTransactionParent.cpp', 'ipc/CompositorBench.cpp', 'ipc/CompositorChild.cpp', + 'ipc/CompositorLRU.cpp', 'ipc/CompositorParent.cpp', 'ipc/ImageBridgeChild.cpp', 'ipc/ImageBridgeParent.cpp', diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index f78543a00633..039b72ce5b27 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -139,6 +139,7 @@ using namespace mozilla::system; #include "CameraPreferences.h" #include "TouchManager.h" #include "MediaDecoder.h" +#include "mozilla/layers/CompositorLRU.h" using namespace mozilla; using namespace mozilla::net; @@ -320,6 +321,8 @@ nsLayoutStatics::Initialize() PromiseDebugging::Init(); + layers::CompositorLRU::Init(); + return NS_OK; } diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 3f2d373b3b62..d5e95e3eb0c3 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4148,6 +4148,9 @@ pref("layers.force-active", false); // platform and are the optimal surface type. pref("layers.gralloc.disable", false); +// Don't use compositor-lru on this platform +pref("layers.compositor-lru-size", 0); + // Enable/Disable the geolocation API for content pref("geo.enabled", true);