diff -r 000000000000 -r 6474c204b198 gfx/layers/ipc/CompositorChild.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/layers/ipc/CompositorChild.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,243 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=2 et 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/. */ + +#include "CompositorChild.h" +#include // for size_t +#include "ClientLayerManager.h" // for ClientLayerManager +#include "base/message_loop.h" // for MessageLoop +#include "base/process_util.h" // for OpenProcessHandle +#include "base/task.h" // for NewRunnableMethod, etc +#include "base/tracked.h" // for FROM_HERE +#include "mozilla/layers/LayerTransactionChild.h" +#include "mozilla/layers/PLayerTransactionChild.h" +#include "mozilla/mozalloc.h" // for operator new, etc +#include "nsDebug.h" // for NS_RUNTIMEABORT +#include "nsIObserver.h" // for nsIObserver +#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc +#include "nsTArray.h" // for nsTArray, nsTArray_Impl +#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop, etc +#include "FrameLayerBuilder.h" +#include "mozilla/dom/TabChild.h" + +using mozilla::layers::LayerTransactionChild; + +namespace mozilla { +namespace layers { + +/*static*/ CompositorChild* CompositorChild::sCompositor; + +Atomic CompositableForwarder::sSerialCounter(0); + +CompositorChild::CompositorChild(ClientLayerManager *aLayerManager) + : mLayerManager(aLayerManager) +{ + MOZ_COUNT_CTOR(CompositorChild); +} + +CompositorChild::~CompositorChild() +{ + MOZ_COUNT_DTOR(CompositorChild); +} + +void +CompositorChild::Destroy() +{ + mLayerManager->Destroy(); + mLayerManager = nullptr; + while (size_t len = ManagedPLayerTransactionChild().Length()) { + LayerTransactionChild* layers = + static_cast(ManagedPLayerTransactionChild()[len - 1]); + layers->Destroy(); + } + SendStop(); +} + +bool +CompositorChild::LookupCompositorFrameMetrics(const FrameMetrics::ViewID aId, + FrameMetrics& aFrame) +{ + SharedFrameMetricsData* data = mFrameMetricsTable.Get(aId); + if (data) { + data->CopyFrameMetrics(&aFrame); + return true; + } + return false; +} + +/*static*/ PCompositorChild* +CompositorChild::Create(Transport* aTransport, ProcessId aOtherProcess) +{ + // There's only one compositor per child process. + MOZ_ASSERT(!sCompositor); + + nsRefPtr child(new CompositorChild(nullptr)); + ProcessHandle handle; + if (!base::OpenProcessHandle(aOtherProcess, &handle)) { + // We can't go on without a compositor. + NS_RUNTIMEABORT("Couldn't OpenProcessHandle() to parent process."); + return nullptr; + } + if (!child->Open(aTransport, handle, XRE_GetIOMessageLoop(), ipc::ChildSide)) { + NS_RUNTIMEABORT("Couldn't Open() Compositor channel."); + return nullptr; + } + // We release this ref in ActorDestroy(). + return sCompositor = child.forget().take(); +} + +/*static*/ CompositorChild* +CompositorChild::Get() +{ + // This is only expected to be used in child processes. + MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default); + return sCompositor; +} + +PLayerTransactionChild* +CompositorChild::AllocPLayerTransactionChild(const nsTArray& aBackendHints, + const uint64_t& aId, + TextureFactoryIdentifier*, + bool*) +{ + LayerTransactionChild* c = new LayerTransactionChild(); + c->AddIPDLReference(); + return c; +} + +bool +CompositorChild::DeallocPLayerTransactionChild(PLayerTransactionChild* actor) +{ + static_cast(actor)->ReleaseIPDLReference(); + return true; +} + +bool +CompositorChild::RecvInvalidateAll() +{ + FrameLayerBuilder::InvalidateAllLayers(mLayerManager); + return true; +} + +bool +CompositorChild::RecvDidComposite(const uint64_t& aId) +{ + if (mLayerManager) { + MOZ_ASSERT(aId == 0); + mLayerManager->DidComposite(); + } else if (aId != 0) { + dom::TabChild *child = dom::TabChild::GetFrom(aId); + if (child) { + child->DidComposite(); + } + } + return true; +} + +void +CompositorChild::ActorDestroy(ActorDestroyReason aWhy) +{ + MOZ_ASSERT(sCompositor == this); + +#ifdef MOZ_B2G + // Due to poor lifetime management of gralloc (and possibly shmems) we will + // crash at some point in the future when we get destroyed due to abnormal + // shutdown. Its better just to crash here. On desktop though, we have a chance + // of recovering. + if (aWhy == AbnormalShutdown) { + NS_RUNTIMEABORT("ActorDestroy by IPC channel failure at CompositorChild"); + } +#endif + if (sCompositor) { + sCompositor->Release(); + sCompositor = nullptr; + } + // We don't want to release the ref to sCompositor here, during + // cleanup, because that will cause it to be deleted while it's + // still being used. So defer the deletion to after it's not in + // use. + MessageLoop::current()->PostTask( + FROM_HERE, + NewRunnableMethod(this, &CompositorChild::Release)); +} + +bool +CompositorChild::RecvSharedCompositorFrameMetrics( + const mozilla::ipc::SharedMemoryBasic::Handle& metrics, + const CrossProcessMutexHandle& handle, + const uint32_t& aAPZCId) +{ + SharedFrameMetricsData* data = new SharedFrameMetricsData(metrics, handle, aAPZCId); + mFrameMetricsTable.Put(data->GetViewID(), data); + return true; +} + +bool +CompositorChild::RecvReleaseSharedCompositorFrameMetrics( + const ViewID& aId, + const uint32_t& aAPZCId) +{ + SharedFrameMetricsData* data = mFrameMetricsTable.Get(aId); + // The SharedFrameMetricsData may have been removed previously if + // a SharedFrameMetricsData with the same ViewID but later APZCId had + // been store and over wrote it. + if (data && (data->GetAPZCId() == aAPZCId)) { + mFrameMetricsTable.Remove(aId); + } + return true; +} + +CompositorChild::SharedFrameMetricsData::SharedFrameMetricsData( + const ipc::SharedMemoryBasic::Handle& metrics, + const CrossProcessMutexHandle& handle, + const uint32_t& aAPZCId) : + mBuffer(nullptr), + mMutex(nullptr), + mAPZCId(aAPZCId) +{ + mBuffer = new ipc::SharedMemoryBasic(metrics); + mBuffer->Map(sizeof(FrameMetrics)); + mMutex = new CrossProcessMutex(handle); + MOZ_COUNT_CTOR(SharedFrameMetricsData); +} + +CompositorChild::SharedFrameMetricsData::~SharedFrameMetricsData() +{ + // When the hash table deletes the class, delete + // the shared memory and mutex. + delete mMutex; + delete mBuffer; + MOZ_COUNT_DTOR(SharedFrameMetricsData); +} + +void +CompositorChild::SharedFrameMetricsData::CopyFrameMetrics(FrameMetrics* aFrame) +{ + FrameMetrics* frame = static_cast(mBuffer->memory()); + MOZ_ASSERT(frame); + mMutex->Lock(); + *aFrame = *frame; + mMutex->Unlock(); +} + +FrameMetrics::ViewID +CompositorChild::SharedFrameMetricsData::GetViewID() +{ + FrameMetrics* frame = static_cast(mBuffer->memory()); + MOZ_ASSERT(frame); + // Not locking to read of mScrollId since it should not change after being + // initially set. + return frame->GetScrollId(); +} + +uint32_t +CompositorChild::SharedFrameMetricsData::GetAPZCId() +{ + return mAPZCId; +} + +} // namespace layers +} // namespace mozilla +