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

--HG--
extra : rebase_source : 2da1d03abc23bd7852e4b12fe133889bd80cad53
This commit is contained in:
sotaro 2017-08-09 08:46:25 -04:00
parent 8487cf859b
commit 162dcae649
9 changed files with 87 additions and 44 deletions

View File

@ -463,6 +463,9 @@ CompositorBridgeParent::StopAndClearResources()
});
mWrBridge->Destroy();
mWrBridge = nullptr;
mAsyncImageManager->Destroy();
// WebRenderAPI should be already destructed
mAsyncImageManager = nullptr;
}
if (mCompositor) {
@ -1654,8 +1657,9 @@ CompositorBridgeParent::RecvAdoptChild(const uint64_t& child)
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.
@ -1702,8 +1706,8 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipel
*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));
@ -1953,10 +1957,10 @@ CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
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;

View File

@ -65,6 +65,7 @@ namespace layers {
class APZCTreeManager;
class APZCTreeManagerParent;
class AsyncCompositionManager;
class AsyncImagePipelineManager;
class Compositor;
class CompositorAnimationStorage;
class CompositorBridgeParent;
@ -580,6 +581,7 @@ protected:
RefPtr<HostLayerManager> mLayerManager;
RefPtr<Compositor> mCompositor;
RefPtr<AsyncCompositionManager> mCompositionManager;
RefPtr<AsyncImagePipelineManager> mAsyncImageManager;
RefPtr<WebRenderBridgeParent> mWrBridge;
widget::CompositorWidget* mWidget;
TimeStamp mTestTime;

View File

@ -225,7 +225,7 @@ CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::Pipeli
}
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));

View File

@ -23,8 +23,9 @@ AsyncImagePipelineManager::AsyncImagePipeline::AsyncImagePipeline()
, 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)
@ -38,9 +39,11 @@ AsyncImagePipelineManager::~AsyncImagePipelineManager()
}
void
AsyncImagePipelineManager::Destroy(wr::WebRenderAPI* aApi)
AsyncImagePipelineManager::Destroy()
{
DeleteOldAsyncImages(aApi);
MOZ_ASSERT(!mDestroyed);
DeleteOldAsyncImages();
mApi = nullptr;
mDestroyed = true;
}
@ -51,10 +54,11 @@ AsyncImagePipelineManager::HasKeysToDelete()
}
void
AsyncImagePipelineManager::DeleteOldAsyncImages(wr::WebRenderAPI* aApi)
AsyncImagePipelineManager::DeleteOldAsyncImages()
{
MOZ_ASSERT(!mDestroyed);
for (wr::ImageKey key : mKeysToDelete) {
aApi->DeleteImage(key);
mApi->DeleteImage(key);
}
mKeysToDelete.Clear();
}
@ -111,7 +115,7 @@ AsyncImagePipelineManager::AddAsyncImagePipeline(const wr::PipelineId& aPipeline
}
void
AsyncImagePipelineManager::RemoveAsyncImagePipeline(wr::WebRenderAPI* aApi, const wr::PipelineId& aPipelineId)
AsyncImagePipelineManager::RemoveAsyncImagePipeline(const wr::PipelineId& aPipelineId)
{
if (mDestroyed) {
return;
@ -121,9 +125,9 @@ AsyncImagePipelineManager::RemoveAsyncImagePipeline(wr::WebRenderAPI* aApi, cons
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));
@ -155,7 +159,7 @@ AsyncImagePipelineManager::UpdateAsyncImagePipeline(const wr::PipelineId& aPipel
}
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);
@ -166,7 +170,7 @@ AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::WebRenderAPI* aApi
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();
@ -185,15 +189,14 @@ AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::WebRenderAPI* aApi
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)
@ -231,7 +234,7 @@ AsyncImagePipelineManager::UpdateImageKeys(wr::WebRenderAPI* aApi,
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;
@ -239,7 +242,7 @@ AsyncImagePipelineManager::UpdateImageKeys(wr::WebRenderAPI* aApi,
}
void
AsyncImagePipelineManager::ApplyAsyncImages(wr::WebRenderAPI* aApi)
AsyncImagePipelineManager::ApplyAsyncImages()
{
if (mDestroyed || mAsyncImagePipelines.Count() == 0) {
return;
@ -255,8 +258,7 @@ AsyncImagePipelineManager::ApplyAsyncImages(wr::WebRenderAPI* aApi)
nsTArray<wr::ImageKey> keys;
bool useExternalImage = false;
bool updateDisplayList = UpdateImageKeys(aApi,
useExternalImage,
bool updateDisplayList = UpdateImageKeys(useExternalImage,
pipeline,
keys,
keysToDelete);
@ -306,11 +308,11 @@ AsyncImagePipelineManager::ApplyAsyncImages(wr::WebRenderAPI* aApi)
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);
}

View File

@ -12,6 +12,7 @@
#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"
@ -34,13 +35,13 @@ 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);
@ -70,7 +71,7 @@ public:
}
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,
@ -78,7 +79,7 @@ public:
const gfx::MaybeIntSize& aScaleToSize,
const wr::ImageRendering& aFilter,
const wr::MixBlendMode& aMixBlendMode);
void ApplyAsyncImages(wr::WebRenderAPI* aApi);
void ApplyAsyncImages();
void AppendImageCompositeNotification(const ImageCompositeNotificationInfo& aNotification)
{
@ -91,7 +92,7 @@ public:
}
private:
void DeleteOldAsyncImages(wr::WebRenderAPI* aApi);
void DeleteOldAsyncImages();
uint32_t GetNextResourceId() { return ++mResourceId; }
wr::IdNamespace GetNamespace() { return mIdNamespace; }
@ -102,7 +103,7 @@ private:
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)
@ -135,12 +136,12 @@ private:
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;

View File

@ -792,7 +792,7 @@ WebRenderBridgeParent::RecvRemovePipelineIdForCompositable(const wr::PipelineId&
}
wrHost->ClearWrBridge();
mAsyncImageManager->RemoveAsyncImagePipeline(mApi, aPipelineId);
mAsyncImageManager->RemoveAsyncImagePipeline(aPipelineId);
mAsyncCompositables.Remove(wr::AsUint64(aPipelineId));
return IPC_OK();
}
@ -1116,7 +1116,7 @@ WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::In
nsTArray<wr::WrTransformProperty> transformArray;
mAsyncImageManager->SetCompositionTime(TimeStamp::Now());
mAsyncImageManager->ApplyAsyncImages(mApi);
mAsyncImageManager->ApplyAsyncImages();
SampleAnimations(opacityArray, transformArray);
if (!transformArray.IsEmpty() || !opacityArray.IsEmpty()) {
@ -1313,7 +1313,7 @@ WebRenderBridgeParent::ClearResources()
wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
RefPtr<WebRenderImageHost> host = iter.Data();
host->ClearWrBridge();
mAsyncImageManager->RemoveAsyncImagePipeline(mApi, pipelineId);
mAsyncImageManager->RemoveAsyncImagePipeline(pipelineId);
}
mAsyncCompositables.Clear();
@ -1329,6 +1329,7 @@ WebRenderBridgeParent::ClearResources()
}
mAnimStorage = nullptr;
mCompositorScheduler = nullptr;
mAsyncImageManager = nullptr;
mApi = nullptr;
mCompositorBridge = nullptr;
}
@ -1452,6 +1453,9 @@ void
WebRenderBridgeParent::ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications)
{
MOZ_ASSERT(mWidget);
if (mDestroyed) {
return;
}
mAsyncImageManager->FlushImageNotifications(aNotifications);
}

View File

@ -176,6 +176,17 @@ WebRenderAPI::Create(bool aEnableProfiler,
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);
@ -183,10 +194,12 @@ WebRenderAPI::GetNamespace() {
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);
}

View File

@ -47,6 +47,8 @@ public:
RefPtr<widget::CompositorWidget>&& aWidget,
LayoutDeviceIntSize aSize);
already_AddRefed<WebRenderAPI> Clone();
wr::WindowId GetId() const { return mId; }
void UpdateScrollPosition(const wr::WrPipelineId& aPipelineId,
@ -143,6 +145,7 @@ protected:
GLint mMaxTextureSize;
bool mUseANGLE;
layers::SyncHandle mSyncHandle;
RefPtr<wr::WebRenderAPI> mRootApi;
friend class DisplayListBuilder;
friend class layers::WebRenderBridgeParent;

View File

@ -610,12 +610,26 @@ pub extern "C" fn wr_window_new(window_id: WrWindowId,
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]
@ -860,7 +874,7 @@ pub extern "C" fn wr_api_delete_font(dh: &mut DocumentHandle,
#[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: