Bug 1385003 - Use a different WebRenderAPI instance for each WebRenderBridgeParent. r=kats
Previously, the WebRenderBridgeParent for each content layer tree would use the
same WebRenderAPI instance as the top-level WebRenderBridgeParent for that window.
However, in order to make the namespacing changes work we now need to use a
separate WebRenderAPI instance for each WebRenderBridgeParent. The content
WebRenderAPIs are cloned from the parent one, so that they all share the same
backend, but can allocate resource IDs in distinct namespaces.
MozReview-Commit-ID: 7VTFL8F09n7
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -458,16 +458,19 @@ CompositorBridgeParent::StopAndClearReso
if (lts->mWrBridge) {
lts->mWrBridge->Destroy();
lts->mWrBridge = nullptr;
}
lts->mParent = nullptr;
});
mWrBridge->Destroy();
mWrBridge = nullptr;
+ mAsyncImageManager->Destroy();
+ // WebRenderAPI should be already destructed
+ mAsyncImageManager = nullptr;
}
if (mCompositor) {
mCompositor->DetachWidget();
mCompositor->Destroy();
mCompositor = nullptr;
}
@@ -1649,18 +1652,19 @@ CompositorBridgeParent::RecvAdoptChild(c
NotifyChildCreated(child);
if (sIndirectLayerTrees[child].mLayerTree) {
sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager, GetAnimationStorage());
// Trigger composition to handle a case that mLayerTree was not composited yet
// by previous CompositorBridgeParent, since nsRefreshDriver might wait composition complete.
ScheduleComposition();
}
if (mWrBridge && sIndirectLayerTrees[child].mWrBridge) {
+ RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI()->Clone();
sIndirectLayerTrees[child].mWrBridge->UpdateWebRender(mWrBridge->CompositorScheduler(),
- mWrBridge->GetWebRenderAPI(),
+ api,
mWrBridge->AsyncImageManager(),
GetAnimationStorage());
// Pretend we composited, since parent CompositorBridgeParent was replaced.
CrossProcessCompositorBridgeParent* cpcp = sIndirectLayerTrees[child].mCrossProcessParent;
if (cpcp) {
TimeStamp now = TimeStamp::Now();
cpcp->DidCompositeLocked(child, now, now);
}
@@ -1697,18 +1701,18 @@ CompositorBridgeParent::AllocPWebRenderB
gfxPrefs::WebRenderProfilerEnabled(), this, Move(widget), aSize);
if (!api) {
mWrBridge = WebRenderBridgeParent::CreateDestroyed();
mWrBridge.get()->AddRef(); // IPDL reference
*aIdNamespace = mWrBridge->GetIdNamespace();
*aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
return mWrBridge;
}
- RefPtr<AsyncImagePipelineManager> asyncMgr =
- new AsyncImagePipelineManager(api->GetNamespace());
+ mAsyncImageManager = new AsyncImagePipelineManager(api->Clone());
+ RefPtr<AsyncImagePipelineManager> asyncMgr = mAsyncImageManager;
api->SetRootPipeline(aPipelineId);
RefPtr<CompositorAnimationStorage> animStorage = GetAnimationStorage();
mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr, Move(api), Move(asyncMgr), Move(animStorage));
mWrBridge.get()->AddRef(); // IPDL reference
*aIdNamespace = mWrBridge->GetIdNamespace();
mCompositorScheduler = mWrBridge->CompositorScheduler();
MOZ_ASSERT(mCompositorScheduler);
@@ -1948,20 +1952,20 @@ CompositorBridgeParent::DidComposite(Tim
NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
mPendingTransaction = 0;
}
}
void
CompositorBridgeParent::NotifyDidCompositeToPipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
{
- if (!mWrBridge) {
+ if (!mWrBridge || !mAsyncImageManager) {
return;
}
- mWrBridge->AsyncImageManager()->Update(aPipelineId, aEpoch);
+ mAsyncImageManager->Update(aPipelineId, aEpoch);
if (mPaused) {
return;
}
if (mWrBridge->PipelineId() == aPipelineId) {
uint64_t transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
Unused << SendDidComposite(0, transactionId, aCompositeStart, aCompositeEnd);
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -60,16 +60,17 @@ namespace ipc {
class Shmem;
} // namespace ipc
namespace layers {
class APZCTreeManager;
class APZCTreeManagerParent;
class AsyncCompositionManager;
+class AsyncImagePipelineManager;
class Compositor;
class CompositorAnimationStorage;
class CompositorBridgeParent;
class CompositorManagerParent;
class CompositorVsyncScheduler;
class HostLayerManager;
class LayerTransactionParent;
class PAPZParent;
@@ -575,16 +576,17 @@ protected:
// The indirect layer tree lock must be held before calling this function.
// Callback should take (LayerTreeState* aState, const uint64_t& aLayersId)
template <typename Lambda>
inline void ForEachIndirectLayerTree(const Lambda& aCallback);
RefPtr<HostLayerManager> mLayerManager;
RefPtr<Compositor> mCompositor;
RefPtr<AsyncCompositionManager> mCompositionManager;
+ RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
RefPtr<WebRenderBridgeParent> mWrBridge;
widget::CompositorWidget* mWidget;
TimeStamp mTestTime;
CSSToLayoutDeviceScale mScale;
TimeDuration mVsyncRate;
bool mIsTesting;
uint64_t mPendingTransaction;
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -220,17 +220,17 @@ CrossProcessCompositorBridgeParent::Allo
parent = WebRenderBridgeParent::CreateDestroyed();
parent->AddRef(); // IPDL reference
*aIdNamespace = parent->GetIdNamespace();
*aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
return parent;
}
WebRenderBridgeParent* root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWrBridge.get();
- RefPtr<wr::WebRenderAPI> api = root->GetWebRenderAPI();
+ RefPtr<wr::WebRenderAPI> api = root->GetWebRenderAPI()->Clone();
RefPtr<AsyncImagePipelineManager> holder = root->AsyncImageManager();
RefPtr<CompositorAnimationStorage> animStorage = cbp->GetAnimationStorage();
parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, root->CompositorScheduler(), Move(api), Move(holder), Move(animStorage));
parent->AddRef(); // IPDL reference
sIndirectLayerTrees[layersId].mCrossProcessParent = this;
sIndirectLayerTrees[layersId].mWrBridge = parent;
*aTextureFactoryIdentifier = parent->GetTextureFactoryIdentifier();
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -18,48 +18,52 @@ namespace layers {
AsyncImagePipelineManager::AsyncImagePipeline::AsyncImagePipeline()
: mInitialised(false)
, mIsChanged(false)
, mUseExternalImage(false)
, mFilter(wr::ImageRendering::Auto)
, mMixBlendMode(wr::MixBlendMode::Normal)
{}
-AsyncImagePipelineManager::AsyncImagePipelineManager(wr::IdNamespace aIdNamespace)
- : mIdNamespace(aIdNamespace)
+AsyncImagePipelineManager::AsyncImagePipelineManager(already_AddRefed<wr::WebRenderAPI>&& aApi)
+ : mApi(aApi)
+ , mIdNamespace(mApi->GetNamespace())
, mResourceId(0)
, mAsyncImageEpoch(0)
, mDestroyed(false)
{
MOZ_COUNT_CTOR(AsyncImagePipelineManager);
}
AsyncImagePipelineManager::~AsyncImagePipelineManager()
{
MOZ_COUNT_DTOR(AsyncImagePipelineManager);
}
void
-AsyncImagePipelineManager::Destroy(wr::WebRenderAPI* aApi)
+AsyncImagePipelineManager::Destroy()
{
- DeleteOldAsyncImages(aApi);
+ MOZ_ASSERT(!mDestroyed);
+ DeleteOldAsyncImages();
+ mApi = nullptr;
mDestroyed = true;
}
bool
AsyncImagePipelineManager::HasKeysToDelete()
{
return !mKeysToDelete.IsEmpty();
}
void
-AsyncImagePipelineManager::DeleteOldAsyncImages(wr::WebRenderAPI* aApi)
+AsyncImagePipelineManager::DeleteOldAsyncImages()
{
+ MOZ_ASSERT(!mDestroyed);
for (wr::ImageKey key : mKeysToDelete) {
- aApi->DeleteImage(key);
+ mApi->DeleteImage(key);
}
mKeysToDelete.Clear();
}
void
AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId)
{
if (mDestroyed) {
@@ -106,29 +110,29 @@ AsyncImagePipelineManager::AddAsyncImage
MOZ_ASSERT(!mAsyncImagePipelines.Get(id));
AsyncImagePipeline* holder = new AsyncImagePipeline();
holder->mImageHost = aImageHost;
mAsyncImagePipelines.Put(id, holder);
AddPipeline(aPipelineId);
}
void
-AsyncImagePipelineManager::RemoveAsyncImagePipeline(wr::WebRenderAPI* aApi, const wr::PipelineId& aPipelineId)
+AsyncImagePipelineManager::RemoveAsyncImagePipeline(const wr::PipelineId& aPipelineId)
{
if (mDestroyed) {
return;
}
uint64_t id = wr::AsUint64(aPipelineId);
if (auto entry = mAsyncImagePipelines.Lookup(id)) {
AsyncImagePipeline* holder = entry.Data();
++mAsyncImageEpoch; // Update webrender epoch
- aApi->ClearRootDisplayList(wr::NewEpoch(mAsyncImageEpoch), aPipelineId);
+ mApi->ClearRootDisplayList(wr::NewEpoch(mAsyncImageEpoch), aPipelineId);
for (wr::ImageKey key : holder->mKeys) {
- aApi->DeleteImage(key);
+ mApi->DeleteImage(key);
}
entry.Remove();
RemovePipeline(aPipelineId, wr::NewEpoch(mAsyncImageEpoch));
}
}
void
AsyncImagePipelineManager::UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
@@ -150,28 +154,28 @@ AsyncImagePipelineManager::UpdateAsyncIm
pipeline->mScBounds = aScBounds;
pipeline->mScTransform = aScTransform;
pipeline->mScaleToSize = aScaleToSize;
pipeline->mFilter = aFilter;
pipeline->mMixBlendMode = aMixBlendMode;
}
bool
-AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::WebRenderAPI* aApi, TextureHost* aTexture, nsTArray<wr::ImageKey>& aKeys)
+AsyncImagePipelineManager::GenerateImageKeyForTextureHost(TextureHost* aTexture, nsTArray<wr::ImageKey>& aKeys)
{
MOZ_ASSERT(aKeys.IsEmpty());
MOZ_ASSERT(aTexture);
WebRenderTextureHost* wrTexture = aTexture->AsWebRenderTextureHost();
if (!gfxEnv::EnableWebRenderRecording() && wrTexture) {
wrTexture->GetWRImageKeys(aKeys, std::bind(&AsyncImagePipelineManager::GenerateImageKey, this));
MOZ_ASSERT(!aKeys.IsEmpty());
Range<const wr::ImageKey> keys(&aKeys[0], aKeys.Length());
- wrTexture->AddWRImage(aApi, keys, wrTexture->GetExternalImageKey());
+ wrTexture->AddWRImage(mApi, keys, wrTexture->GetExternalImageKey());
return true;
} else {
RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
if (!dSurf) {
NS_ERROR("TextureHost does not return DataSourceSurface");
return false;
}
gfx::DataSourceSurface::MappedSurface map;
@@ -180,25 +184,24 @@ AsyncImagePipelineManager::GenerateImage
return false;
}
gfx::IntSize size = dSurf->GetSize();
wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
wr::ImageKey key = GenerateImageKey();
aKeys.AppendElement(key);
- aApi->AddImage(key, descriptor, slice);
+ mApi->AddImage(key, descriptor, slice);
dSurf->Unmap();
}
return false;
}
bool
-AsyncImagePipelineManager::UpdateImageKeys(wr::WebRenderAPI* aApi,
- bool& aUseExternalImage,
+AsyncImagePipelineManager::UpdateImageKeys(bool& aUseExternalImage,
AsyncImagePipeline* aImageMgr,
nsTArray<wr::ImageKey>& aKeys,
nsTArray<wr::ImageKey>& aKeysToDelete)
{
MOZ_ASSERT(aKeys.IsEmpty());
MOZ_ASSERT(aImageMgr);
TextureHost* texture = aImageMgr->mImageHost->GetAsTextureHostForComposite();
@@ -226,42 +229,41 @@ AsyncImagePipelineManager::UpdateImageKe
aImageMgr->mKeys.Clear();
aImageMgr->mCurrentTexture = nullptr;
// No txture to render
if (!texture) {
return true;
}
- aUseExternalImage = aImageMgr->mUseExternalImage = GenerateImageKeyForTextureHost(aApi, texture, aKeys);
+ aUseExternalImage = aImageMgr->mUseExternalImage = GenerateImageKeyForTextureHost(texture, aKeys);
MOZ_ASSERT(!aKeys.IsEmpty());
aImageMgr->mKeys.AppendElements(aKeys);
aImageMgr->mCurrentTexture = texture;
return true;
}
void
-AsyncImagePipelineManager::ApplyAsyncImages(wr::WebRenderAPI* aApi)
+AsyncImagePipelineManager::ApplyAsyncImages()
{
if (mDestroyed || mAsyncImagePipelines.Count() == 0) {
return;
}
++mAsyncImageEpoch; // Update webrender epoch
wr::Epoch epoch = wr::NewEpoch(mAsyncImageEpoch);
nsTArray<wr::ImageKey> keysToDelete;
for (auto iter = mAsyncImagePipelines.Iter(); !iter.Done(); iter.Next()) {
wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
AsyncImagePipeline* pipeline = iter.Data();
nsTArray<wr::ImageKey> keys;
bool useExternalImage = false;
- bool updateDisplayList = UpdateImageKeys(aApi,
- useExternalImage,
+ bool updateDisplayList = UpdateImageKeys(useExternalImage,
pipeline,
keys,
keysToDelete);
if (!updateDisplayList) {
continue;
}
wr::LayoutSize contentSize { pipeline->mScBounds.width, pipeline->mScBounds.height };
@@ -301,21 +303,21 @@ AsyncImagePipelineManager::ApplyAsyncIma
keys[0]);
}
builder.PopStackingContext();
}
wr::BuiltDisplayList dl;
wr::LayoutSize builderContentSize;
builder.Finalize(builderContentSize, dl);
- aApi->SetRootDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), epoch, LayerSize(pipeline->mScBounds.width, pipeline->mScBounds.height),
+ mApi->SetRootDisplayList(gfx::Color(0.f, 0.f, 0.f, 0.f), epoch, LayerSize(pipeline->mScBounds.width, pipeline->mScBounds.height),
pipelineId, builderContentSize,
dl.dl_desc, dl.dl.inner.data, dl.dl.inner.length);
}
- DeleteOldAsyncImages(aApi);
+ DeleteOldAsyncImages();
mKeysToDelete.SwapElements(keysToDelete);
}
void
AsyncImagePipelineManager::HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture)
{
if (mDestroyed) {
return;
--- a/gfx/layers/wr/AsyncImagePipelineManager.h
+++ b/gfx/layers/wr/AsyncImagePipelineManager.h
@@ -7,16 +7,17 @@
#define MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H
#include <queue>
#include "CompositableHost.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/Maybe.h"
+#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsClassHashtable.h"
namespace mozilla {
namespace wr {
class DisplayListBuilder;
class WebRenderAPI;
@@ -29,23 +30,23 @@ class CompositorVsyncScheduler;
class WebRenderImageHost;
class WebRenderTextureHost;
class AsyncImagePipelineManager final
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncImagePipelineManager)
- explicit AsyncImagePipelineManager(wr::IdNamespace aIdNamespace);
+ explicit AsyncImagePipelineManager(already_AddRefed<wr::WebRenderAPI>&& aApi);
protected:
~AsyncImagePipelineManager();
public:
- void Destroy(wr::WebRenderAPI* aApi);
+ void Destroy();
bool HasKeysToDelete();
void AddPipeline(const wr::PipelineId& aPipelineId);
void RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch);
void HoldExternalImage(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, WebRenderTextureHost* aTexture);
void Update(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch);
@@ -65,49 +66,49 @@ public:
mCompositeUntilTime = aTimeStamp;
}
}
TimeStamp GetCompositeUntilTime() const {
return mCompositeUntilTime;
}
void AddAsyncImagePipeline(const wr::PipelineId& aPipelineId, WebRenderImageHost* aImageHost);
- void RemoveAsyncImagePipeline(wr::WebRenderAPI* aApi, const wr::PipelineId& aPipelineId);
+ void RemoveAsyncImagePipeline(const wr::PipelineId& aPipelineId);
void UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId,
const LayerRect& aScBounds,
const gfx::Matrix4x4& aScTransform,
const gfx::MaybeIntSize& aScaleToSize,
const wr::ImageRendering& aFilter,
const wr::MixBlendMode& aMixBlendMode);
- void ApplyAsyncImages(wr::WebRenderAPI* aApi);
+ void ApplyAsyncImages();
void AppendImageCompositeNotification(const ImageCompositeNotificationInfo& aNotification)
{
mImageCompositeNotifications.AppendElement(aNotification);
}
void FlushImageNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications)
{
aNotifications->AppendElements(Move(mImageCompositeNotifications));
}
private:
- void DeleteOldAsyncImages(wr::WebRenderAPI* aApi);
+ void DeleteOldAsyncImages();
uint32_t GetNextResourceId() { return ++mResourceId; }
wr::IdNamespace GetNamespace() { return mIdNamespace; }
wr::ImageKey GenerateImageKey()
{
wr::ImageKey key;
key.mNamespace = GetNamespace();
key.mHandle = GetNextResourceId();
return key;
}
- bool GenerateImageKeyForTextureHost(wr::WebRenderAPI* aApi, TextureHost* aTexture, nsTArray<wr::ImageKey>& aKeys);
+ bool GenerateImageKeyForTextureHost(TextureHost* aTexture, nsTArray<wr::ImageKey>& aKeys);
struct ForwardingTextureHost {
ForwardingTextureHost(const wr::Epoch& aEpoch, TextureHost* aTexture)
: mEpoch(aEpoch)
, mTexture(aTexture)
{}
wr::Epoch mEpoch;
CompositableTextureHostRef mTexture;
@@ -130,22 +131,22 @@ private:
gfx::MaybeIntSize mScaleToSize;
wr::ImageRendering mFilter;
wr::MixBlendMode mMixBlendMode;
RefPtr<WebRenderImageHost> mImageHost;
CompositableTextureHostRef mCurrentTexture;
nsTArray<wr::ImageKey> mKeys;
};
- bool UpdateImageKeys(wr::WebRenderAPI* aApi,
- bool& aUseExternalImage,
+ bool UpdateImageKeys(bool& aUseExternalImage,
AsyncImagePipeline* aImageMgr,
nsTArray<wr::ImageKey>& aKeys,
nsTArray<wr::ImageKey>& aKeysToDelete);
+ RefPtr<wr::WebRenderAPI> mApi;
wr::IdNamespace mIdNamespace;
uint32_t mResourceId;
nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
uint32_t mAsyncImageEpoch;
nsTArray<wr::ImageKey> mKeysToDelete;
bool mDestroyed;
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -787,17 +787,17 @@ WebRenderBridgeParent::RecvRemovePipelin
}
WebRenderImageHost* wrHost = mAsyncCompositables.Get(wr::AsUint64(aPipelineId)).get();
if (!wrHost) {
return IPC_OK();
}
wrHost->ClearWrBridge();
- mAsyncImageManager->RemoveAsyncImagePipeline(mApi, aPipelineId);
+ mAsyncImageManager->RemoveAsyncImagePipeline(aPipelineId);
mAsyncCompositables.Remove(wr::AsUint64(aPipelineId));
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvAddExternalImageIdForCompositable(const ExternalImageId& aImageId,
const CompositableHandle& aHandle)
{
@@ -1111,17 +1111,17 @@ WebRenderBridgeParent::CompositeToTarget
return;
}
bool scheduleComposite = false;
nsTArray<wr::WrOpacityProperty> opacityArray;
nsTArray<wr::WrTransformProperty> transformArray;
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
- mAsyncImageManager->ApplyAsyncImages(mApi);
+ mAsyncImageManager->ApplyAsyncImages();
SampleAnimations(opacityArray, transformArray);
if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
scheduleComposite = true;
}
if (PushAPZStateToWR(transformArray)) {
scheduleComposite = true;
@@ -1308,32 +1308,33 @@ WebRenderBridgeParent::ClearResources()
for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
iter.Data()->ClearWrBridge();
}
mExternalImageIds.Clear();
for (auto iter = mAsyncCompositables.Iter(); !iter.Done(); iter.Next()) {
wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
RefPtr<WebRenderImageHost> host = iter.Data();
host->ClearWrBridge();
- mAsyncImageManager->RemoveAsyncImagePipeline(mApi, pipelineId);
+ mAsyncImageManager->RemoveAsyncImagePipeline(pipelineId);
}
mAsyncCompositables.Clear();
mAsyncImageManager->RemovePipeline(mPipelineId, wr::NewEpoch(wrEpoch));
for (std::unordered_set<uint64_t>::iterator iter = mActiveAnimations.begin(); iter != mActiveAnimations.end(); iter++) {
mAnimStorage->ClearById(*iter);
}
mActiveAnimations.clear();
if (mWidget) {
mCompositorScheduler->Destroy();
}
mAnimStorage = nullptr;
mCompositorScheduler = nullptr;
+ mAsyncImageManager = nullptr;
mApi = nullptr;
mCompositorBridge = nullptr;
}
bool
WebRenderBridgeParent::ShouldParentObserveEpoch()
{
if (mParentLayerObserverEpoch == mChildLayerObserverEpoch) {
@@ -1447,13 +1448,16 @@ WebRenderBridgeParent::GetNextWrEpoch()
MOZ_RELEASE_ASSERT(mWrEpoch != UINT32_MAX);
return ++mWrEpoch;
}
void
WebRenderBridgeParent::ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications)
{
MOZ_ASSERT(mWidget);
+ if (mDestroyed) {
+ return;
+ }
mAsyncImageManager->FlushImageNotifications(aNotifications);
}
} // namespace layers
} // namespace mozilla
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -171,27 +171,40 @@ WebRenderAPI::Create(bool aEnableProfile
if (!docHandle) {
return nullptr;
}
return RefPtr<WebRenderAPI>(new WebRenderAPI(docHandle, id, maxTextureSize, useANGLE, syncHandle)).forget();
}
+already_AddRefed<WebRenderAPI>
+WebRenderAPI::Clone()
+{
+ wr::DocumentHandle* docHandle = nullptr;
+ wr_api_clone(mDocHandle, &docHandle);
+
+ RefPtr<WebRenderAPI> renderApi = new WebRenderAPI(docHandle, mId, mMaxTextureSize, mUseANGLE, mSyncHandle);
+ renderApi->mRootApi = this; // Hold root api
+ return renderApi.forget();
+}
+
wr::WrIdNamespace
WebRenderAPI::GetNamespace() {
return wr_api_get_namespace(mDocHandle);
}
WebRenderAPI::~WebRenderAPI()
{
- layers::SynchronousTask task("Destroy WebRenderAPI");
- auto event = MakeUnique<RemoveRenderer>(&task);
- RunOnRenderThread(Move(event));
- task.Wait();
+ if (!mRootApi) {
+ layers::SynchronousTask task("Destroy WebRenderAPI");
+ auto event = MakeUnique<RemoveRenderer>(&task);
+ RunOnRenderThread(Move(event));
+ task.Wait();
+ }
wr_api_delete(mDocHandle);
}
void
WebRenderAPI::UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
const layers::FrameMetrics::ViewID& aScrollId,
const wr::LayoutPoint& aScrollPosition)
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -42,16 +42,18 @@ class WebRenderAPI
public:
/// This can be called on the compositor thread only.
static already_AddRefed<WebRenderAPI> Create(bool aEnableProfiler,
layers::CompositorBridgeParentBase* aBridge,
RefPtr<widget::CompositorWidget>&& aWidget,
LayoutDeviceIntSize aSize);
+ already_AddRefed<WebRenderAPI> Clone();
+
wr::WindowId GetId() const { return mId; }
void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
const layers::FrameMetrics::ViewID& aScrollId,
const wr::LayoutPoint& aScrollPosition);
void GenerateFrame();
void GenerateFrame(const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
@@ -138,16 +140,17 @@ protected:
// Should be used only for shutdown handling
void WaitFlushed();
wr::DocumentHandle* mDocHandle;
wr::WindowId mId;
GLint mMaxTextureSize;
bool mUseANGLE;
layers::SyncHandle mSyncHandle;
+ RefPtr<wr::WebRenderAPI> mRootApi;
friend class DisplayListBuilder;
friend class layers::WebRenderBridgeParent;
};
/// This is a simple C++ wrapper around WrState defined in the rust bindings.
/// We may want to turn this into a direct wrapper on top of WebRenderFrameBuilder
/// instead, so the interface may change a bit.
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -605,22 +605,36 @@ pub extern "C" fn wr_window_new(window_i
let window_size = DeviceUintSize::new(window_width, window_height);
*out_handle = Box::into_raw(Box::new(
DocumentHandle::new(sender.create_api(), window_size)));
*out_renderer = Box::into_raw(Box::new(renderer));
return true;
}
+#[no_mangle]
+pub extern "C" fn wr_api_clone(dh: &mut DocumentHandle,
+ out_handle: &mut *mut DocumentHandle) {
+ assert!(unsafe { is_in_compositor_thread() });
+
+ let handle = DocumentHandle {
+ api: dh.api.clone_sender().create_api(),
+ document_id: dh.document_id,
+ };
+ *out_handle = Box::into_raw(Box::new(handle));
+}
+
/// cbindgen:postfix=WR_DESTRUCTOR_SAFE_FUNC
#[no_mangle]
pub unsafe extern "C" fn wr_api_delete(dh: *mut DocumentHandle) {
let handle = Box::from_raw(dh);
- handle.api.delete_document(handle.document_id);
- handle.api.shut_down();
+ if handle.document_id.0 == handle.api.get_namespace_id() {
+ handle.api.delete_document(handle.document_id);
+ handle.api.shut_down();
+ }
}
#[no_mangle]
pub extern "C" fn wr_api_add_image(dh: &mut DocumentHandle,
image_key: WrImageKey,
descriptor: &WrImageDescriptor,
bytes: ByteSlice) {
assert!(unsafe { is_in_compositor_thread() });
@@ -855,17 +869,17 @@ pub extern "C" fn wr_api_add_raw_font(dh
pub extern "C" fn wr_api_delete_font(dh: &mut DocumentHandle,
key: WrFontKey) {
assert!(unsafe { is_in_compositor_thread() });
dh.api.delete_font(key);
}
#[no_mangle]
pub unsafe extern "C" fn wr_api_get_namespace(dh: &mut DocumentHandle) -> WrIdNamespace {
- dh.document_id.0
+ dh.api.get_namespace_id()
}
// RenderThread WIP notes:
// In order to separate the compositor thread (or ipc receiver) and the render
// thread, some of the logic below needs to be rewritten. In particular
// the WrWindowState and Notifier implementations aren't designed to work with
// a separate render thread.
// As part of that I am moving the bindings closer to WebRender's API boundary,