Bug 1314186 - Resync LayerTreeId mappings to the GPU process if it restarts. r=dvander

This commit is contained in:
Matt Woodrow 2016-11-03 09:55:07 +13:00
parent f0a313b11b
commit 9e56f22190
9 changed files with 73 additions and 29 deletions

View File

@ -1778,13 +1778,13 @@ ContentParent::RecvDeallocateLayerTreeId(const uint64_t& aId)
{
GPUProcessManager* gpu = GPUProcessManager::Get();
if (!gpu->IsLayerTreeIdMapped(aId, this->OtherPid()))
if (!gpu->IsLayerTreeIdMapped(aId, OtherPid()))
{
// You can't deallocate layer tree ids that you didn't allocate
KillHard("DeallocateLayerTreeId");
}
gpu->DeallocateLayerTreeId(aId);
gpu->UnmapLayerTreeId(aId, OtherPid());
return true;
}

View File

@ -295,16 +295,19 @@ GPUParent::RecvNewContentVideoDecoderManager(Endpoint<PVideoDecoderManagerParent
}
bool
GPUParent::RecvDeallocateLayerTreeId(const uint64_t& aLayersId)
GPUParent::RecvAddLayerTreeIdMapping(nsTArray<LayerTreeIdMapping>&& aMappings)
{
CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
for (const LayerTreeIdMapping& map : aMappings) {
LayerTreeOwnerTracker::Get()->Map(map.layersId(), map.ownerId());
}
return true;
}
bool
GPUParent::RecvAddLayerTreeIdMapping(const uint64_t& aLayersId, const ProcessId& aOwnerId)
GPUParent::RecvRemoveLayerTreeIdMapping(const LayerTreeIdMapping& aMapping)
{
LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwnerId);
LayerTreeOwnerTracker::Get()->Unmap(aMapping.layersId(), aMapping.ownerId());
CompositorBridgeParent::DeallocateLayerTreeId(aMapping.layersId());
return true;
}

View File

@ -44,9 +44,9 @@ public:
bool RecvNewContentImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint) override;
bool RecvNewContentVRManager(Endpoint<PVRManagerParent>&& aEndpoint) override;
bool RecvNewContentVideoDecoderManager(Endpoint<PVideoDecoderManagerParent>&& aEndpoint) override;
bool RecvDeallocateLayerTreeId(const uint64_t& aLayersId) override;
bool RecvGetDeviceStatus(GPUDeviceData* aOutStatus) override;
bool RecvAddLayerTreeIdMapping(const uint64_t& aLayersId, const ProcessId& aOwnerId) override;
bool RecvAddLayerTreeIdMapping(nsTArray<LayerTreeIdMapping>&& aMappings) override;
bool RecvRemoveLayerTreeIdMapping(const LayerTreeIdMapping& aMapping) override;
bool RecvNotifyGpuObservers(const nsCString& aTopic) override;
void ActorDestroy(ActorDestroyReason aWhy) override;

View File

@ -249,6 +249,12 @@ GPUProcessManager::OnProcessLaunchComplete(GPUProcessHost* aHost)
mVsyncBridge = VsyncBridgeChild::Create(mVsyncIOThread, mProcessToken, Move(vsyncChild));
mGPUChild->SendInitVsyncBridge(Move(vsyncParent));
nsTArray<LayerTreeIdMapping> mappings;
LayerTreeOwnerTracker::Get()->Iterate([&](uint64_t aLayersId, base::ProcessId aProcessId) {
mappings.AppendElement(LayerTreeIdMapping(aLayersId, aProcessId));
});
mGPUChild->SendAddLayerTreeIdMapping(mappings);
}
void
@ -670,12 +676,24 @@ GPUProcessManager::MapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
LayerTreeOwnerTracker::Get()->Map(aLayersId, aOwningId);
if (mGPUChild) {
mGPUChild->SendAddLayerTreeIdMapping(
aLayersId,
aOwningId);
AutoTArray<LayerTreeIdMapping, 1> mappings;
mappings.AppendElement(LayerTreeIdMapping(aLayersId, aOwningId));
mGPUChild->SendAddLayerTreeIdMapping(mappings);
}
}
void
GPUProcessManager::UnmapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId)
{
LayerTreeOwnerTracker::Get()->Unmap(aLayersId, aOwningId);
if (mGPUChild) {
mGPUChild->SendRemoveLayerTreeIdMapping(LayerTreeIdMapping(aLayersId, aOwningId));
return;
}
CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
}
bool
GPUProcessManager::IsLayerTreeIdMapped(uint64_t aLayersId, base::ProcessId aRequestingId)
{
@ -689,16 +707,6 @@ GPUProcessManager::AllocateLayerTreeId()
return ++mNextLayerTreeId;
}
void
GPUProcessManager::DeallocateLayerTreeId(uint64_t aLayersId)
{
if (mGPUChild) {
mGPUChild->SendDeallocateLayerTreeId(aLayersId);
return;
}
CompositorBridgeParent::DeallocateLayerTreeId(aLayersId);
}
void
GPUProcessManager::EnsureVsyncIOThread()
{

View File

@ -104,6 +104,11 @@ public:
// to access aLayersId across process.
void MapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId);
// Release compositor-thread resources referred to by |aID|.
//
// Must run on the content main thread.
void UnmapLayerTreeId(uint64_t aLayersId, base::ProcessId aOwningId);
// Checks to see if aLayersId and aRequestingPID have been mapped by MapLayerTreeId
bool IsLayerTreeIdMapped(uint64_t aLayersId, base::ProcessId aRequestingId);
@ -113,10 +118,6 @@ public:
// Must run on the content main thread.
uint64_t AllocateLayerTreeId();
// Release compositor-thread resources referred to by |aID|.
//
// Must run on the content main thread.
void DeallocateLayerTreeId(uint64_t aLayersId);
void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;

View File

@ -32,6 +32,11 @@ struct GfxPrefSetting {
GfxPrefValue value;
};
struct LayerTreeIdMapping {
uint64_t layersId;
ProcessId ownerId;
};
sync protocol PGPU
{
parent:
@ -61,10 +66,9 @@ parent:
async NewContentVRManager(Endpoint<PVRManagerParent> endpoint);
async NewContentVideoDecoderManager(Endpoint<PVideoDecoderManagerParent> endpoint);
async DeallocateLayerTreeId(uint64_t layersId);
// Called to notify the GPU process of who owns a layersId.
sync AddLayerTreeIdMapping(uint64_t layersId, ProcessId ownerId);
sync AddLayerTreeIdMapping(LayerTreeIdMapping[] mapping);
async RemoveLayerTreeIdMapping(LayerTreeIdMapping mapping);
// Request the current DeviceStatus from the GPU process. This blocks until
// one is available (i.e., Init has completed).

View File

@ -51,6 +51,15 @@ LayerTreeOwnerTracker::Map(uint64_t aLayersId, base::ProcessId aProcessId)
mLayerIds[aLayersId] = aProcessId;
}
void
LayerTreeOwnerTracker::Unmap(uint64_t aLayersId, base::ProcessId aProcessId)
{
MutexAutoLock lock(mLayerIdsLock);
MOZ_ASSERT(mLayerIds[aLayersId] == aProcessId);
mLayerIds.erase(aLayersId);
}
bool
LayerTreeOwnerTracker::IsMapped(uint64_t aLayersId, base::ProcessId aProcessId)
{
@ -60,5 +69,15 @@ LayerTreeOwnerTracker::IsMapped(uint64_t aLayersId, base::ProcessId aProcessId)
return iter != mLayerIds.end() && iter->second == aProcessId;
}
void
LayerTreeOwnerTracker::Iterate(function<void(uint64_t aLayersId, base::ProcessId aProcessId)> aCallback)
{
MutexAutoLock lock(mLayerIdsLock);
for (const auto& iter : mLayerIds) {
aCallback(iter.first, iter.second);
}
}
} // namespace layers
} // namespace mozilla

View File

@ -9,6 +9,7 @@
#include "base/process.h" // for base::ProcessId
#include "mozilla/Mutex.h" // for mozilla::Mutex
#include "mozilla/Function.h"
#include <map>
@ -44,11 +45,19 @@ public:
* can access that layer tree.
*/
void Map(uint64_t aLayersId, base::ProcessId aProcessId);
/**
* Remove an existing mapping.
*/
void Unmap(uint64_t aLayersId, base::ProcessId aProcessId);
/**
* Checks whether it is okay for aProcessId to access aLayersId.
*/
bool IsMapped(uint64_t aLayersId, base::ProcessId aProcessId);
void Iterate(function<void(uint64_t aLayersId, base::ProcessId aProcessId)> aCallback);
private:
LayerTreeOwnerTracker();

View File

@ -225,7 +225,7 @@ RenderFrameParent::ActorDestroy(ActorDestroyReason why)
{
if (mLayersId != 0) {
if (XRE_IsParentProcess()) {
GPUProcessManager::Get()->DeallocateLayerTreeId(mLayersId);
GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, OtherPid());
} else if (XRE_IsContentProcess()) {
ContentChild::GetSingleton()->SendDeallocateLayerTreeId(mLayersId);
}