Bug 950079 - Add release Fence handling to SurfaceStream on gonk

This commit is contained in:
Sotaro Ikeda 2014-05-14 15:40:15 -07:00
parent 669a2aaf0c
commit 12f85ecb9a
19 changed files with 213 additions and 94 deletions

View File

@ -80,6 +80,10 @@ public:
virtual void Fence() = 0;
virtual bool WaitSync() = 0;
// This function waits until the buffer is no longer being used.
// To optimize the performance, some implementaions recycle SharedSurfaces
// even when its buffer is still being used.
virtual void WaitForBufferOwnership() {}
SharedSurfaceType Type() const {
return mType;

View File

@ -152,3 +152,9 @@ SharedSurface_Gralloc::WaitSync()
{
return true;
}
void
SharedSurface_Gralloc::WaitForBufferOwnership()
{
mTextureClient->WaitReleaseFence();
}

View File

@ -68,6 +68,8 @@ public:
virtual void Fence() MOZ_OVERRIDE;
virtual bool WaitSync() MOZ_OVERRIDE;
virtual void WaitForBufferOwnership() MOZ_OVERRIDE;
virtual void LockProdImpl() MOZ_OVERRIDE {}
virtual void UnlockProdImpl() MOZ_OVERRIDE {}

View File

@ -80,8 +80,12 @@ SurfaceStream::New(SurfaceFactory* factory, const gfx::IntSize& size,
MOZ_ASSERT(!surf);
surf = factory->NewSharedSurface(size);
if (surf)
if (surf) {
// Before next use, wait until SharedSurface's buffer
// is no longer being used.
surf->WaitForBufferOwnership();
mSurfaces.insert(surf);
}
}
void

View File

@ -9,7 +9,6 @@
#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
@ -38,36 +37,6 @@ 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.

View File

@ -8,14 +8,17 @@
#ifndef mozilla_layers_AsyncTransactionTracker_h
#define mozilla_layers_AsyncTransactionTracker_h
#include <map>
#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 {
class TextureClient;
/**
* AsyncTransactionTracker tracks asynchronous transaction.
* It is typically used for asynchronous layer transaction handling.

View File

@ -114,7 +114,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
RenderTraceInvalidateEnd(thebes, "FF00FF");
// return texure data to client if necessary
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
ReturnTextureDataIfNecessary(compositable);
break;
}
case CompositableOperation::TOpPaintTextureIncremental: {
@ -160,7 +160,13 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
MOZ_ASSERT(tex.get());
compositable->RemoveTextureHost(tex);
// return texure data to client if necessary
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
if (IsAsync()) {
DeprecatedReturnTextureDataIfNecessary(compositable,
replyv,
op.compositableParent());
} else {
ReturnTextureDataIfNecessary(compositable);
}
break;
}
case CompositableOperation::TOpRemoveTextureAsync: {
@ -195,7 +201,13 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
}
}
// return texure data to client if necessary
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
if (IsAsync()) {
DeprecatedReturnTextureDataIfNecessary(compositable,
replyv,
op.compositableParent());
} else {
ReturnTextureDataIfNecessary(compositable);
}
break;
}
case CompositableOperation::TOpUseComponentAlphaTextures: {
@ -211,7 +223,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
ScheduleComposition(op);
}
// return texure data to client if necessary
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
ReturnTextureDataIfNecessary(compositable);
break;
}
case CompositableOperation::TOpUpdateTexture: {
@ -235,9 +247,52 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
void
CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
EditReplyVector& replyv,
PCompositableParent* aParent)
CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable)
{
if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
return;
}
static const uint32_t MAX_FENCE_COUNT_PER_MESSAGE = 4;
const std::vector< RefPtr<TextureHost> > textureList =
aCompositable->GetCompositableBackendSpecificData()->GetPendingReleaseFenceTextureList();
InfallibleTArray<AsyncParentMessageData> messages;
messages.SetCapacity(MAX_FENCE_COUNT_PER_MESSAGE);
// Send Fences to child side
for (size_t i = 0; i < textureList.size(); i++) {
TextureHostOGL* hostOGL = textureList[i]->AsHostOGL();
PTextureParent* actor = textureList[i]->GetIPDLActor();
if (!hostOGL || !actor) {
continue;
}
android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
if (fence.get() && fence->isValid()) {
RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
FenceHandle handle = FenceHandle(fence);
HoldUntilComplete(tracker);
messages.AppendElement(OpDeliverFence(tracker->GetId(),
actor, nullptr,
handle));
if (messages.Length() >= MAX_FENCE_COUNT_PER_MESSAGE) {
SendAsyncMessage(messages);
messages.Clear();
}
}
}
if (messages.Length() > 0) {
SendAsyncMessage(messages);
messages.Clear();
}
aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList();
}
void
CompositableParentManager::DeprecatedReturnTextureDataIfNecessary(CompositableHost* aCompositable,
EditReplyVector& replyv,
PCompositableParent* aParent)
{
if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
return;
@ -267,11 +322,21 @@ CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompo
}
aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList();
}
#else
void
CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
EditReplyVector& replyv,
PCompositableParent* aParent)
CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable)
{
if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
return;
}
aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList();
}
void
CompositableParentManager::DeprecatedReturnTextureDataIfNecessary(CompositableHost* aCompositable,
EditReplyVector& replyv,
PCompositableParent* aParent)
{
if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
return;
@ -281,7 +346,7 @@ CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompo
#endif
void
CompositableParentManager::ClearPrevFenceHandles()
CompositableParentManager::DeprecatedClearPrevFenceHandles()
{
mPrevFenceHandles.clear();
}

View File

@ -34,6 +34,8 @@ public:
PTextureParent* aTexture,
const FenceHandle& aFence) = 0;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) = 0;
protected:
/**
* Handle the IPDL messages that affect PCompositable actors.
@ -48,10 +50,12 @@ protected:
*/
virtual bool IsAsync() const { return false; }
void ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
EditReplyVector& replyv,
PCompositableParent* aParent);
void ClearPrevFenceHandles();
void ReturnTextureDataIfNecessary(CompositableHost* aCompositable);
void DeprecatedReturnTextureDataIfNecessary(CompositableHost* aCompositable,
EditReplyVector& replyv,
PCompositableParent* aParent);
void DeprecatedClearPrevFenceHandles();
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) {}

View File

@ -12,6 +12,7 @@
#include <ui/Fence.h>
#include "ipc/IPCMessageUtils.h"
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
namespace mozilla {
namespace layers {
@ -35,6 +36,34 @@ struct FenceHandle {
android::sp<Fence> mFence;
};
// 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;
};
} // namespace layers
} // namespace mozilla

View File

@ -739,30 +739,34 @@ ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
}
bool
ImageBridgeChild::RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage)
ImageBridgeChild::RecvParentAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessages)
{
switch (aMessage.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = aMessage.get_OpDeliverFence();
FenceHandle fence = op.fence();
PTextureChild* child = op.textureChild();
for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncParentMessageData& message = aMessages[i];
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
if (texture) {
texture->SetReleaseFenceHandle(fence);
switch (message.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = message.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;
}
HoldTransactionsToRespond(op.transactionId());
break;
}
case AsyncParentMessageData::TOpReplyRemoveTexture: {
const OpReplyRemoveTexture& op = aMessage.get_OpReplyRemoveTexture();
const OpReplyRemoveTexture& op = message.get_OpReplyRemoveTexture();
CompositableClient::TransactionCompleteted(op.compositableChild(), op.transactionId());
break;
}
default:
NS_ERROR("unknown AsyncParentMessageData type");
return false;
default:
NS_ERROR("unknown AsyncParentMessageData type");
return false;
}
}
return true;
}

View File

@ -103,6 +103,7 @@ class ImageBridgeChild : public PImageBridgeChild
, public CompositableForwarder
{
friend class ImageContainer;
typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
public:
/**
@ -194,7 +195,7 @@ public:
DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
virtual bool
RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage) MOZ_OVERRIDE;
RecvParentAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessages) MOZ_OVERRIDE;
TemporaryRef<ImageClient> CreateImageClient(CompositableType aType);
TemporaryRef<ImageClient> CreateImageClientNow(CompositableType aType);

View File

@ -82,7 +82,7 @@ ImageBridgeParent::RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply)
}
// Clear fence handles used in previsou transaction.
ClearPrevFenceHandles();
DeprecatedClearPrevFenceHandles();
EditReplyVector replyv;
for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) {
@ -193,9 +193,17 @@ ImageBridgeParent::SendFenceHandle(AsyncTransactionTracker* aTracker,
const FenceHandle& aFence)
{
HoldUntilComplete(aTracker);
mozilla::unused << SendParentAsyncMessage(OpDeliverFence(aTracker->GetId(),
InfallibleTArray<AsyncParentMessageData> messages;
messages.AppendElement(OpDeliverFence(aTracker->GetId(),
aTexture, nullptr,
aFence));
mozilla::unused << SendParentAsyncMessage(messages);
}
void
ImageBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
{
mozilla::unused << SendParentAsyncMessage(aMessage);
}
bool
@ -276,7 +284,9 @@ bool ImageBridgeParent::IsSameProcess() const
void
ImageBridgeParent::ReplyRemoveTexture(const OpReplyRemoveTexture& aReply)
{
mozilla::unused << SendParentAsyncMessage(aReply);
InfallibleTArray<AsyncParentMessageData> messages;
messages.AppendElement(aReply);
mozilla::unused << SendParentAsyncMessage(messages);
}
} // layers

View File

@ -59,6 +59,8 @@ public:
PTextureParent* aTexture,
const FenceHandle& aFence) MOZ_OVERRIDE;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) MOZ_OVERRIDE;
// PImageBridge
virtual bool RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply) MOZ_OVERRIDE;
virtual bool RecvUpdateNoSwap(const EditArray& aEdits) MOZ_OVERRIDE;

View File

@ -66,31 +66,35 @@ LayerTransactionChild::DeallocPCompositableChild(PCompositableChild* actor)
}
bool
LayerTransactionChild::RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage)
LayerTransactionChild::RecvParentAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessages)
{
switch (aMessage.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = aMessage.get_OpDeliverFence();
FenceHandle fence = op.fence();
PTextureChild* child = op.textureChild();
for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncParentMessageData& message = aMessages[i];
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
if (texture) {
texture->SetReleaseFenceHandle(fence);
switch (message.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = message.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;
}
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;
}
default:
NS_ERROR("unknown AsyncParentMessageData type");
return false;
}
return true;
}

View File

@ -25,6 +25,7 @@ namespace layers {
class LayerTransactionChild : public PLayerTransactionChild
{
typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LayerTransactionChild)
/**
@ -62,7 +63,7 @@ protected:
virtual bool DeallocPTextureChild(PTextureChild* actor) MOZ_OVERRIDE;
virtual bool
RecvParentAsyncMessage(const mozilla::layers::AsyncParentMessageData& aMessage) MOZ_OVERRIDE;
RecvParentAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessages) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;

View File

@ -209,7 +209,7 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
}
// Clear fence handles used in previsou transaction.
ClearPrevFenceHandles();
DeprecatedClearPrevFenceHandles();
EditReplyVector replyv;
@ -817,9 +817,17 @@ LayerTransactionParent::SendFenceHandle(AsyncTransactionTracker* aTracker,
const FenceHandle& aFence)
{
HoldUntilComplete(aTracker);
mozilla::unused << SendParentAsyncMessage(OpDeliverFence(aTracker->GetId(),
InfallibleTArray<AsyncParentMessageData> messages;
messages.AppendElement(OpDeliverFence(aTracker->GetId(),
aTexture, nullptr,
aFence));
mozilla::unused << SendParentAsyncMessage(messages);
}
void
LayerTransactionParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
{
mozilla::unused << SendParentAsyncMessage(aMessage);
}
} // namespace layers

View File

@ -84,6 +84,9 @@ public:
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence) MOZ_OVERRIDE;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) MOZ_OVERRIDE;
protected:
virtual bool RecvUpdate(const EditArray& cset,
const TargetConfig& targetConfig,

View File

@ -29,7 +29,7 @@ intr protocol PImageBridge
manages PTexture;
child:
async ParentAsyncMessage(AsyncParentMessageData aMessage);
async ParentAsyncMessage(AsyncParentMessageData[] aMessages);
parent:

View File

@ -42,7 +42,7 @@ sync protocol PLayerTransaction {
manages PTexture;
child:
async ParentAsyncMessage(AsyncParentMessageData aMessage);
async ParentAsyncMessage(AsyncParentMessageData[] aMessages);
parent:
async PLayer();