Bug 1000525 - Defer Fence release until IPC delivery complete r=nical

This commit is contained in:
Sotaro Ikeda 2014-05-05 18:56:40 -07:00
parent e65a2a6b8a
commit 0990a75026
25 changed files with 625 additions and 52 deletions

View File

@ -53,6 +53,14 @@ ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
ClientLayerManager::~ClientLayerManager()
{
ClearCachedResources();
// Stop receiveing AsyncParentMessage at Forwarder.
// After the call, the message is directly handled by LayerTransactionChild.
// Basically this function should be called in ShadowLayerForwarder's
// destructor. But when the destructor is triggered by
// CompositorChild::Destroy(), the destructor can not handle it correctly.
// See Bug 1000525.
mForwarder->StopReceiveAsyncParentMessge();
mRoot = nullptr;
MOZ_COUNT_DTOR(ClientLayerManager);
@ -266,9 +274,7 @@ ClientLayerManager::GetRemoteRenderer()
void
ClientLayerManager::Composite()
{
if (LayerTransactionChild* manager = mForwarder->GetShadowManager()) {
manager->SendForceComposite();
}
mForwarder->Composite();
}
void
@ -428,6 +434,7 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
}
mForwarder->RemoveTexturesIfNecessary();
mForwarder->SendPendingAsyncMessge();
mPhase = PHASE_NONE;
// this may result in Layers being deleted, which results in
@ -498,9 +505,7 @@ void
ClientLayerManager::ClearCachedResources(Layer* aSubtree)
{
MOZ_ASSERT(!HasShadowManager() || !aSubtree);
if (LayerTransactionChild* manager = mForwarder->GetShadowManager()) {
manager->SendClearCachedResources();
}
mForwarder->ClearCachedResources();
if (aSubtree) {
ClearLayer(aSubtree);
} else if (mRoot) {

View File

@ -90,17 +90,9 @@ public:
bool Recv__delete__() MOZ_OVERRIDE;
bool RecvCompositorRecycle(const MaybeFenceHandle& aFence)
bool RecvCompositorRecycle()
{
RECYCLE_LOG("Receive recycle %p (%p)\n", mTextureClient, mWaitForRecycle.get());
if (aFence.type() != aFence.Tnull_t) {
FenceHandle fence = aFence.get_FenceHandle();
if (fence.IsValid() && mTextureClient) {
mTextureClient->SetReleaseFenceHandle(aFence);
// HWC might not provide Fence.
// In this case, HWC implicitly handles buffer's fence.
}
}
mWaitForRecycle = nullptr;
return true;
}

View File

@ -9,6 +9,8 @@
#include "gfx2DGlue.h" // for ToIntSize
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
#include "mozilla/ipc/Shmem.h" // for Shmem
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
#include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
#include "mozilla/layers/ImageDataSerializer.h"
@ -36,6 +38,36 @@ struct nsIntPoint;
namespace mozilla {
namespace layers {
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
// FenceDeliveryTracker puts off releasing a Fence until a transaction complete.
class FenceDeliveryTracker : public AsyncTransactionTracker {
public:
FenceDeliveryTracker(const android::sp<android::Fence>& aFence)
: mFence(aFence)
{
MOZ_COUNT_CTOR(FenceDeliveryTracker);
}
~FenceDeliveryTracker()
{
MOZ_COUNT_DTOR(FenceDeliveryTracker);
}
virtual void Complete() MOZ_OVERRIDE
{
mFence = nullptr;
}
virtual void Cancel() MOZ_OVERRIDE
{
mFence = nullptr;
}
private:
android::sp<android::Fence> mFence;
};
#endif
/**
* TextureParent is the host-side IPDL glue between TextureClient and TextureHost.
* It is an IPDL actor just like LayerParent, CompositableParent, etc.
@ -43,7 +75,7 @@ namespace layers {
class TextureParent : public PTextureParent
{
public:
TextureParent(ISurfaceAllocator* aAllocator);
TextureParent(CompositableParentManager* aManager);
~TextureParent();
@ -61,24 +93,24 @@ public:
void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
ISurfaceAllocator* mAllocator;
CompositableParentManager* mCompositableManager;
RefPtr<TextureHost> mWaitForClientRecycle;
RefPtr<TextureHost> mTextureHost;
};
// static
PTextureParent*
TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator,
TextureHost::CreateIPDLActor(CompositableParentManager* aManager,
const SurfaceDescriptor& aSharedData,
TextureFlags aFlags)
{
if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorMemory &&
!aAllocator->IsSameProcess())
!aManager->IsSameProcess())
{
NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
return nullptr;
}
TextureParent* actor = new TextureParent(aAllocator);
TextureParent* actor = new TextureParent(aManager);
if (!actor->Init(aSharedData, aFlags)) {
delete actor;
return nullptr;
@ -604,8 +636,8 @@ size_t MemoryTextureHost::GetBufferSize()
return std::numeric_limits<size_t>::max();
}
TextureParent::TextureParent(ISurfaceAllocator* aAllocator)
: mAllocator(aAllocator)
TextureParent::TextureParent(CompositableParentManager* aCompositableManager)
: mCompositableManager(aCompositableManager)
{
MOZ_COUNT_CTOR(TextureParent);
}
@ -628,23 +660,25 @@ TextureParent::CompositorRecycle()
{
mTextureHost->ClearRecycleCallback();
MaybeFenceHandle handle = null_t();
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if (mTextureHost) {
TextureHostOGL* hostOGL = mTextureHost->AsHostOGL();
android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
if (fence.get() && fence->isValid()) {
handle = FenceHandle(fence);
// HWC might not provide Fence.
// In this case, HWC implicitly handles buffer's fence.
FenceHandle handle = FenceHandle(fence);
RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
mCompositableManager->SendFenceHandle(tracker, this, handle);
}
}
#endif
mozilla::unused << SendCompositorRecycle(handle);
// Don't forget to prepare for the next reycle
// if TextureClient request it.
if (mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
mozilla::unused << SendCompositorRecycle();
// Don't forget to prepare for the next reycle
// if TextureClient request it.
mWaitForClientRecycle = mTextureHost;
}
}
@ -667,7 +701,7 @@ TextureParent::Init(const SurfaceDescriptor& aSharedData,
const TextureFlags& aFlags)
{
mTextureHost = TextureHost::Create(aSharedData,
mAllocator,
mCompositableManager,
aFlags);
if (mTextureHost) {
mTextureHost->mActor = this;

View File

@ -41,6 +41,7 @@ namespace layers {
class Compositor;
class CompositableHost;
class CompositableBackendSpecificData;
class CompositableParentManager;
class SurfaceDescriptor;
class ISurfaceAllocator;
class TextureHostOGL;
@ -392,7 +393,7 @@ public:
* are for use with the managing IPDL protocols only (so that they can
* implement AllocPTextureParent and DeallocPTextureParent).
*/
static PTextureParent* CreateIPDLActor(ISurfaceAllocator* aAllocator,
static PTextureParent* CreateIPDLActor(CompositableParentManager* aManager,
const SurfaceDescriptor& aSharedData,
TextureFlags aFlags);
static bool DestroyIPDLActor(PTextureParent* actor);

View File

@ -0,0 +1,129 @@
/* -*- 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 "AsyncTransactionTracker.h"
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
namespace mozilla {
namespace layers {
uint64_t AsyncTransactionTracker::sSerialCounter(0);
Mutex* AsyncTransactionTracker::sLock = nullptr;
AsyncTransactionTracker::AsyncTransactionTracker()
: mSerial(GetNextSerial())
, mCompletedMonitor("AsyncTransactionTracker.mCompleted")
, mCompleted(false)
{
}
AsyncTransactionTracker::~AsyncTransactionTracker()
{
}
void
AsyncTransactionTracker::WaitComplete()
{
MOZ_ASSERT(!InImageBridgeChildThread());
MonitorAutoLock mon(mCompletedMonitor);
int count = 0;
while (!mCompleted) {
if (!NS_SUCCEEDED(mCompletedMonitor.Wait(PR_MillisecondsToInterval(10000)))) {
NS_WARNING("Failed to wait Monitor");
return;
}
if (count > 1) {
NS_WARNING("Waiting async transaction complete.");
}
count++;
}
}
void
AsyncTransactionTracker::NotifyComplete()
{
MonitorAutoLock mon(mCompletedMonitor);
MOZ_ASSERT(!mCompleted);
mCompleted = true;
Complete();
mCompletedMonitor.Notify();
}
void
AsyncTransactionTracker::NotifyCancel()
{
MonitorAutoLock mon(mCompletedMonitor);
MOZ_ASSERT(!mCompleted);
mCompleted = true;
Cancel();
mCompletedMonitor.Notify();
}
AsyncTransactionTrackersHolder::AsyncTransactionTrackersHolder()
: mIsTrackersHolderDestroyed(false)
{
MOZ_COUNT_CTOR(AsyncTransactionTrackersHolder);
}
AsyncTransactionTrackersHolder::~AsyncTransactionTrackersHolder()
{
if (!mIsTrackersHolderDestroyed) {
DestroyAsyncTransactionTrackersHolder();
}
MOZ_COUNT_DTOR(AsyncTransactionTrackersHolder);
}
void
AsyncTransactionTrackersHolder::HoldUntilComplete(AsyncTransactionTracker* aTransactionTracker)
{
if (!aTransactionTracker) {
return;
}
if (mIsTrackersHolderDestroyed && aTransactionTracker) {
aTransactionTracker->NotifyComplete();
return;
}
if (aTransactionTracker) {
mAsyncTransactionTrackeres[aTransactionTracker->GetId()] = aTransactionTracker;
}
}
void
AsyncTransactionTrackersHolder::TransactionCompleteted(uint64_t aTransactionId)
{
std::map<uint64_t, RefPtr<AsyncTransactionTracker> >::iterator it
= mAsyncTransactionTrackeres.find(aTransactionId);
if (it != mAsyncTransactionTrackeres.end()) {
it->second->NotifyCancel();
mAsyncTransactionTrackeres.erase(it);
}
}
void
AsyncTransactionTrackersHolder::ClearAllAsyncTransactionTrackers()
{
std::map<uint64_t, RefPtr<AsyncTransactionTracker> >::iterator it;
for (it = mAsyncTransactionTrackeres.begin();
it != mAsyncTransactionTrackeres.end(); it++) {
it->second->NotifyCancel();
}
mAsyncTransactionTrackeres.clear();
}
void
AsyncTransactionTrackersHolder::DestroyAsyncTransactionTrackersHolder() {
mIsTrackersHolderDestroyed = true;
ClearAllAsyncTransactionTrackers();
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,134 @@
/* -*- 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_layers_AsyncTransactionTracker_h
#define mozilla_layers_AsyncTransactionTracker_h
#include "mozilla/Atomics.h"
#include "mozilla/layers/TextureClient.h" // for TextureClient
#include "mozilla/Monitor.h" // for Monitor
#include "mozilla/RefPtr.h" // for AtomicRefCounted
namespace mozilla {
namespace layers {
/**
* AsyncTransactionTracker tracks asynchronous transaction.
* It is typically used for asynchronous layer transaction handling.
*/
class AsyncTransactionTracker
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncTransactionTracker)
AsyncTransactionTracker();
static void Initialize()
{
if (!sLock) {
sLock = new Mutex("AsyncTransactionTracker::sLock");
}
}
static void Finalize()
{
if (sLock) {
delete sLock;
sLock = nullptr;
}
}
Monitor& GetReentrantMonitor()
{
return mCompletedMonitor;
}
/**
* Wait until asynchronous transaction complete.
*/
void WaitComplete();
/**
* Notify async transaction complete.
*/
void NotifyComplete();
/**
* Notify async transaction cancel.
*/
void NotifyCancel();
uint64_t GetId()
{
return mSerial;
}
/**
* Called when asynchronous transaction complete.
*/
virtual void Complete()= 0;
/**
* Called when asynchronous transaction is cancelled.
* The cancel typically happens when IPC is disconnected
*/
virtual void Cancel()= 0;
virtual void SetTextureClient(TextureClient* aTextureClient) {}
protected:
virtual ~AsyncTransactionTracker();
static uint64_t GetNextSerial()
{
MOZ_ASSERT(sLock);
if(sLock) {
sLock->Lock();
}
++sSerialCounter;
if(sLock) {
sLock->Unlock();
}
return sSerialCounter;
}
uint64_t mSerial;
Monitor mCompletedMonitor;
bool mCompleted;
/**
* gecko does not provide atomic operation for uint64_t.
* Ensure atomicity by using Mutex.
*/
static uint64_t sSerialCounter;
static Mutex* sLock;
};
class AsyncTransactionTrackersHolder
{
public:
AsyncTransactionTrackersHolder();
virtual ~AsyncTransactionTrackersHolder();
void HoldUntilComplete(AsyncTransactionTracker* aTransactionTracker);
void TransactionCompleteted(uint64_t aTransactionId);
protected:
void ClearAllAsyncTransactionTrackers();
void DestroyAsyncTransactionTrackersHolder();
bool mIsTrackersHolderDestroyed;
std::map<uint64_t, RefPtr<AsyncTransactionTracker> > mAsyncTransactionTrackeres;
};
} // namespace layers
} // namespace mozilla
#endif // mozilla_layers_AsyncTransactionTracker_h

View File

@ -139,6 +139,16 @@ public:
mTexturesToRemove.Clear();
}
virtual void HoldTransactionsToRespond(uint64_t aTransactionId)
{
mTransactionsToRespond.push_back(aTransactionId);
}
virtual void ClearTransactionsToRespond()
{
mTransactionsToRespond.clear();
}
/**
* Tell the CompositableHost on the compositor side what texture to use for
* the next composition.
@ -196,6 +206,7 @@ public:
protected:
TextureFactoryIdentifier mTextureFactoryIdentifier;
nsTArray<RefPtr<TextureClient> > mTexturesToRemove;
std::vector<uint64_t> mTransactionsToRespond;
const int32_t mSerial;
static mozilla::Atomic<int32_t> sSerialCounter;
};

View File

@ -24,6 +24,7 @@
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
#include "mozilla/layers/ThebesLayerComposite.h"
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/unused.h"
#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
#include "nsRegion.h" // for nsIntRegion

View File

@ -10,6 +10,7 @@
#include <vector> // for vector
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
#include "mozilla/layers/LayersMessages.h" // for EditReply, etc
@ -17,6 +18,7 @@ namespace mozilla {
namespace layers {
class CompositableHost;
class PTextureChild;
typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
@ -25,7 +27,13 @@ typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
// so both manager protocols implement this and we keep a reference to them
// through this interface.
class CompositableParentManager : public ISurfaceAllocator
, public AsyncTransactionTrackersHolder
{
public:
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence) = 0;
protected:
/**
* Handle the IPDL messages that affect PCompositable actors.

View File

@ -474,6 +474,7 @@ ImageBridgeChild::EndTransaction()
NS_RUNTIMEABORT("not reached");
}
}
SendPendingAsyncMessge();
}
@ -751,6 +752,29 @@ ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
return TextureClient::DestroyIPDLActor(actor);
}
bool
ImageBridgeChild::RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage)
{
switch (aMessage.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = aMessage.get_OpDeliverFence();
FenceHandle fence = op.fence();
PTextureChild* child = op.textureChild();
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
if (texture) {
texture->SetReleaseFenceHandle(fence);
}
HoldTransactionsToRespond(op.transactionId());
break;
}
default:
NS_ERROR("unknown AsyncParentMessageData type");
return false;
}
return true;
}
PTextureChild*
ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
TextureFlags aFlags)
@ -809,5 +833,21 @@ bool ImageBridgeChild::IsSameProcess() const
return OtherProcess() == ipc::kInvalidProcessHandle;
}
void ImageBridgeChild::SendPendingAsyncMessge()
{
if (!IsCreated() ||
mTransactionsToRespond.empty()) {
return;
}
// Send OpReplyDeliverFence messages
InfallibleTArray<AsyncChildMessageData> replies;
replies.SetCapacity(mTransactionsToRespond.size());
for (size_t i = 0; i < mTransactionsToRespond.size(); i++) {
replies.AppendElement(OpReplyDeliverFence(mTransactionsToRespond[i]));
}
mTransactionsToRespond.clear();
SendChildAsyncMessages(replies);
}
} // layers
} // mozilla

View File

@ -192,6 +192,9 @@ public:
virtual bool
DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
virtual bool
RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage) MOZ_OVERRIDE;
TemporaryRef<ImageClient> CreateImageClient(CompositableType aType);
TemporaryRef<ImageClient> CreateImageClientNow(CompositableType aType);
@ -302,6 +305,8 @@ public:
virtual bool IsSameProcess() const MOZ_OVERRIDE;
void SendPendingAsyncMessge();
protected:
ImageBridgeChild();
bool DispatchAllocShmemInternal(size_t aSize,

View File

@ -25,6 +25,7 @@
#include "mozilla/layers/PImageBridgeParent.h"
#include "mozilla/layers/Compositor.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "mozilla/unused.h"
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsDebug.h" // for NS_RUNTIMEABORT, etc
#include "nsISupportsImpl.h" // for ImageBridgeParent::Release, etc
@ -186,6 +187,37 @@ ImageBridgeParent::DeallocPTextureParent(PTextureParent* actor)
return TextureHost::DestroyIPDLActor(actor);
}
void
ImageBridgeParent::SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence)
{
HoldUntilComplete(aTracker);
mozilla::unused << SendParentAsyncMessage(OpDeliverFence(aTracker->GetId(),
aTexture, nullptr,
aFence));
}
bool
ImageBridgeParent::RecvChildAsyncMessages(const InfallibleTArray<AsyncChildMessageData>& aMessages)
{
for (AsyncChildMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncChildMessageData& message = aMessages[i];
switch (message.type()) {
case AsyncChildMessageData::TOpReplyDeliverFence: {
const OpReplyDeliverFence& op = message.get_OpReplyDeliverFence();
TransactionCompleteted(op.transactionId());
break;
}
default:
NS_ERROR("unknown AsyncChildMessageData type");
return false;
}
}
return true;
}
MessageLoop * ImageBridgeParent::GetMessageLoop() {
return mMessageLoop;
}

View File

@ -42,6 +42,7 @@ class ImageBridgeParent : public PImageBridgeParent,
public:
typedef InfallibleTArray<CompositableOperation> EditArray;
typedef InfallibleTArray<EditReply> EditReplyArray;
typedef InfallibleTArray<AsyncChildMessageData> AsyncChildMessageArray;
ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport);
~ImageBridgeParent();
@ -53,6 +54,11 @@ public:
static PImageBridgeParent*
Create(Transport* aTransport, ProcessId aOtherProcess);
// CompositableParentManager
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence) MOZ_OVERRIDE;
// PImageBridge
virtual bool RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply) MOZ_OVERRIDE;
virtual bool RecvUpdateNoSwap(const EditArray& aEdits) MOZ_OVERRIDE;
@ -67,6 +73,9 @@ public:
const TextureFlags& aFlags) MOZ_OVERRIDE;
virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
virtual bool
RecvChildAsyncMessages(const InfallibleTArray<AsyncChildMessageData>& aMessages) MOZ_OVERRIDE;
bool RecvStop() MOZ_OVERRIDE;
MessageLoop * GetMessageLoop();

View File

@ -9,6 +9,7 @@
#include "mozilla/layers/CompositableClient.h" // for CompositableChild
#include "mozilla/layers/PCompositableChild.h" // for PCompositableChild
#include "mozilla/layers/PLayerChild.h" // for PLayerChild
#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsDebug.h" // for NS_RUNTIMEABORT, etc
#include "nsTArray.h" // for nsTArray
@ -55,6 +56,36 @@ LayerTransactionChild::DeallocPCompositableChild(PCompositableChild* actor)
return CompositableClient::DestroyIPDLActor(actor);
}
bool
LayerTransactionChild::RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage)
{
switch (aMessage.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = aMessage.get_OpDeliverFence();
FenceHandle fence = op.fence();
PTextureChild* child = op.textureChild();
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
if (texture) {
texture->SetReleaseFenceHandle(fence);
}
if (mForwarder) {
mForwarder->HoldTransactionsToRespond(op.transactionId());
} else {
// Send back a response.
InfallibleTArray<AsyncChildMessageData> replies;
replies.AppendElement(OpReplyDeliverFence(op.transactionId()));
SendChildAsyncMessages(replies);
}
break;
}
default:
NS_ERROR("unknown AsyncParentMessageData type");
return false;
}
return true;
}
void
LayerTransactionChild::ActorDestroy(ActorDestroyReason why)
{

View File

@ -18,6 +18,7 @@ namespace mozilla {
namespace layout {
class RenderFrameChild;
class ShadowLayerForwarder;
}
namespace layers {
@ -37,6 +38,11 @@ public:
bool IPCOpen() const { return mIPCOpen; }
void SetForwarder(ShadowLayerForwarder* aForwarder)
{
mForwarder = aForwarder;
}
protected:
LayerTransactionChild()
: mIPCOpen(false)
@ -53,6 +59,9 @@ protected:
const TextureFlags& aFlags) MOZ_OVERRIDE;
virtual bool DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
virtual bool
RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
void AddIPDLReference() {
@ -69,6 +78,7 @@ protected:
friend class layout::RenderFrameChild;
bool mIPCOpen;
ShadowLayerForwarder* mForwarder;
};
} // namespace layers

View File

@ -29,6 +29,7 @@
#include "mozilla/layers/PLayerParent.h" // for PLayerParent
#include "mozilla/layers/ThebesLayerComposite.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "mozilla/unused.h"
#include "nsCoord.h" // for NSAppUnitsToFloatPixels
#include "nsDebug.h" // for NS_RUNTIMEABORT
#include "nsDeviceContext.h" // for AppUnitsPerCSSPixel
@ -174,13 +175,6 @@ LayerTransactionParent::GetCompositorBackendType() const
return mLayerManager->GetBackendType();
}
/* virtual */
void
LayerTransactionParent::ActorDestroy(ActorDestroyReason aWhy)
{
// Implement me! Bug 1005171
}
bool
LayerTransactionParent::RecvUpdateNoSwap(const InfallibleTArray<Edit>& cset,
const TargetConfig& targetConfig,
@ -784,10 +778,47 @@ LayerTransactionParent::DeallocPTextureParent(PTextureParent* actor)
return TextureHost::DestroyIPDLActor(actor);
}
bool
LayerTransactionParent::RecvChildAsyncMessages(const InfallibleTArray<AsyncChildMessageData>& aMessages)
{
for (AsyncChildMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncChildMessageData& message = aMessages[i];
switch (message.type()) {
case AsyncChildMessageData::TOpReplyDeliverFence: {
const OpReplyDeliverFence& op = message.get_OpReplyDeliverFence();
TransactionCompleteted(op.transactionId());
break;
}
default:
NS_ERROR("unknown AsyncChildMessageData type");
return false;
}
}
return true;
}
void
LayerTransactionParent::ActorDestroy(ActorDestroyReason why)
{
DestroyAsyncTransactionTrackersHolder();
}
bool LayerTransactionParent::IsSameProcess() const
{
return OtherProcess() == ipc::kInvalidProcessHandle;
}
void
LayerTransactionParent::SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence)
{
HoldUntilComplete(aTracker);
mozilla::unused << SendParentAsyncMessage(OpDeliverFence(aTracker->GetId(),
aTexture, nullptr,
aFence));
}
} // namespace layers
} // namespace mozilla

View File

@ -43,6 +43,7 @@ class LayerTransactionParent : public PLayerTransactionParent,
typedef mozilla::layout::RenderFrameParent RenderFrameParent;
typedef InfallibleTArray<Edit> EditArray;
typedef InfallibleTArray<EditReply> EditReplyArray;
typedef InfallibleTArray<AsyncChildMessageData> AsyncChildMessageArray;
public:
LayerTransactionParent(LayerManagerComposite* aManager,
@ -79,9 +80,11 @@ public:
virtual bool IsSameProcess() const MOZ_OVERRIDE;
// CompositableParentManager
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence) MOZ_OVERRIDE;
protected:
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual bool RecvUpdate(const EditArray& cset,
const TargetConfig& targetConfig,
const bool& isFirstPaint,
@ -115,6 +118,11 @@ protected:
const TextureFlags& aFlags) MOZ_OVERRIDE;
virtual bool DeallocPTextureParent(PTextureParent* actor) MOZ_OVERRIDE;
virtual bool
RecvChildAsyncMessages(const InfallibleTArray<AsyncChildMessageData>& aMessages) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
bool Attach(ShadowLayerParent* aLayerParent,
CompositableHost* aCompositable,
bool aIsAsyncVideo);

View File

@ -357,6 +357,16 @@ struct OpUpdateTexture {
MaybeRegion region;
};
struct OpDeliverFence {
uint64_t transactionId;
PTexture texture;
FenceHandle fence;
};
struct OpReplyDeliverFence {
uint64_t transactionId;
};
union CompositableOperation {
OpUpdatePictureRect;
@ -428,5 +438,13 @@ union EditReply {
ReturnReleaseFence;
};
union AsyncParentMessageData {
OpDeliverFence;
};
union AsyncChildMessageData {
OpReplyDeliverFence;
};
} // namespace
} // namespace

View File

@ -28,6 +28,9 @@ intr protocol PImageBridge
manages PCompositable;
manages PTexture;
child:
async ParentAsyncMessage(AsyncParentMessageData aMessage);
parent:
sync Update(CompositableOperation[] ops) returns (EditReply[] reply);
@ -44,6 +47,8 @@ parent:
sync PCompositable(TextureInfo aInfo) returns (uint64_t id);
async PTexture(SurfaceDescriptor aSharedData, TextureFlags aTextureFlags);
async ChildAsyncMessages(AsyncChildMessageData[] aMessages);
};

View File

@ -41,6 +41,9 @@ sync protocol PLayerTransaction {
manages PCompositable;
manages PTexture;
child:
async ParentAsyncMessage(AsyncParentMessageData aMessage);
parent:
async PLayer();
async PCompositable(TextureInfo aTextureInfo);
@ -84,6 +87,8 @@ parent:
// Schedule a composite if one isn't already scheduled.
async ForceComposite();
async ChildAsyncMessages(AsyncChildMessageData[] aMessages);
async __delete__();
};

View File

@ -11,16 +11,10 @@ include protocol PImageBridge;
include "mozilla/GfxMessageUtils.h";
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
using struct mozilla::layers::FenceHandle from "mozilla/layers/FenceUtils.h";
namespace mozilla {
namespace layers {
union MaybeFenceHandle {
FenceHandle;
null_t;
};
/**
* PTexture is the IPDL glue between a TextureClient and a TextureHost.
*/
@ -30,7 +24,7 @@ sync protocol PTexture {
child:
async __delete__();
async CompositorRecycle(MaybeFenceHandle aFence);
async CompositorRecycle();
parent:

View File

@ -177,6 +177,9 @@ ShadowLayerForwarder::~ShadowLayerForwarder()
{
NS_ABORT_IF_FALSE(mTxn->Finished(), "unfinished transaction?");
delete mTxn;
if (mShadowManager) {
mShadowManager->SetForwarder(nullptr);
}
}
void
@ -572,7 +575,8 @@ ShadowLayerForwarder::AllocShmem(size_t aSize,
ipc::Shmem* aShmem)
{
NS_ABORT_IF_FALSE(HasShadowManager(), "no shadow manager");
if (!mShadowManager->IPCOpen()) {
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return false;
}
return mShadowManager->AllocShmem(aSize, aType, aShmem);
@ -583,7 +587,8 @@ ShadowLayerForwarder::AllocUnsafeShmem(size_t aSize,
ipc::Shmem* aShmem)
{
NS_ABORT_IF_FALSE(HasShadowManager(), "no shadow manager");
if (!mShadowManager->IPCOpen()) {
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return false;
}
return mShadowManager->AllocUnsafeShmem(aSize, aType, aShmem);
@ -592,7 +597,8 @@ void
ShadowLayerForwarder::DeallocShmem(ipc::Shmem& aShmem)
{
NS_ABORT_IF_FALSE(HasShadowManager(), "no shadow manager");
if (!mShadowManager->IPCOpen()) {
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return;
}
mShadowManager->DeallocShmem(aShmem);
@ -622,7 +628,8 @@ PLayerChild*
ShadowLayerForwarder::ConstructShadowFor(ShadowableLayer* aLayer)
{
NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
if (!mShadowManager->IPCOpen()) {
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return nullptr;
}
return mShadowManager->SendPLayerConstructor(new ShadowLayerChild(aLayer));
@ -645,7 +652,8 @@ ShadowLayerForwarder::Connect(CompositableClient* aCompositable)
#endif
MOZ_ASSERT(aCompositable);
MOZ_ASSERT(mShadowManager);
if (!mShadowManager->IPCOpen()) {
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return;
}
PCompositableChild* actor =
@ -687,7 +695,8 @@ PTextureChild*
ShadowLayerForwarder::CreateTexture(const SurfaceDescriptor& aSharedData,
TextureFlags aFlags)
{
if (!mShadowManager->IPCOpen()) {
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return nullptr;
}
return mShadowManager->SendPTextureConstructor(aSharedData, aFlags);
@ -697,8 +706,54 @@ ShadowLayerForwarder::CreateTexture(const SurfaceDescriptor& aSharedData,
void ShadowLayerForwarder::SetShadowManager(PLayerTransactionChild* aShadowManager)
{
mShadowManager = static_cast<LayerTransactionChild*>(aShadowManager);
mShadowManager->SetForwarder(this);
}
void ShadowLayerForwarder::StopReceiveAsyncParentMessge()
{
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return;
}
SendPendingAsyncMessge();
mShadowManager->SetForwarder(nullptr);
}
void ShadowLayerForwarder::ClearCachedResources()
{
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return;
}
SendPendingAsyncMessge();
mShadowManager->SendClearCachedResources();
}
void ShadowLayerForwarder::Composite()
{
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
return;
}
mShadowManager->SendForceComposite();
}
void ShadowLayerForwarder::SendPendingAsyncMessge()
{
if (!HasShadowManager() ||
!mShadowManager->IPCOpen() ||
mTransactionsToRespond.empty()) {
return;
}
// Send OpReplyDeliverFence messages
InfallibleTArray<AsyncChildMessageData> replies;
replies.SetCapacity(mTransactionsToRespond.size());
for (size_t i = 0; i < mTransactionsToRespond.size(); i++) {
replies.AppendElement(OpReplyDeliverFence(mTransactionsToRespond[i]));
}
mTransactionsToRespond.clear();
mShadowManager->SendChildAsyncMessages(replies);
}
} // namespace layers
} // namespace mozilla

View File

@ -299,6 +299,14 @@ public:
*/
void SetShadowManager(PLayerTransactionChild* aShadowManager);
void StopReceiveAsyncParentMessge();
void ClearCachedResources();
void Composite();
void SendPendingAsyncMessge();
/**
* True if this is forwarding to a LayerManagerComposite.
*/

View File

@ -135,6 +135,7 @@ EXPORTS.mozilla.layers += [
'D3D9SurfaceImage.h',
'Effects.h',
'ImageDataSerializer.h',
'ipc/AsyncTransactionTracker.h',
'ipc/CompositableForwarder.h',
'ipc/CompositableTransactionParent.h',
'ipc/CompositorChild.h',
@ -273,6 +274,7 @@ UNIFIED_SOURCES += [
'Effects.cpp',
'ImageDataSerializer.cpp',
'ImageLayers.cpp',
'ipc/AsyncTransactionTracker.cpp',
'ipc/CompositableTransactionParent.cpp',
'ipc/CompositorChild.cpp',
'ipc/CompositorParent.cpp',

View File

@ -7,6 +7,7 @@
#define FORCE_PR_LOG /* Allow logging in the release build */
#endif
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layers/ImageBridgeChild.h"
@ -335,6 +336,8 @@ gfxPlatform::Init()
gGfxPlatformPrefsLock = new Mutex("gfxPlatform::gGfxPlatformPrefsLock");
AsyncTransactionTracker::Initialize();
/* Initialize the GfxInfo service.
* Note: we can't call functions on GfxInfo that depend
* on gPlatform until after it has been initialized
@ -505,6 +508,8 @@ gfxPlatform::Shutdown()
#endif
CompositorParent::ShutDown();
AsyncTransactionTracker::Finalize();
delete gGfxPlatformPrefsLock;
gfxPrefs::DestroySingleton();