--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -8,16 +8,17 @@
#include "Units.h" // for ScreenPoint
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/RefPtr.h" // for TemporaryRef, RefCounted
#include "mozilla/gfx/Point.h" // for IntSize, Point
#include "mozilla/gfx/Rect.h" // for Rect, IntRect
#include "mozilla/gfx/Types.h" // for Float
#include "mozilla/layers/CompositorTypes.h" // for DiagnosticTypes, etc
+#include "mozilla/layers/FenceUtils.h" // for FenceHandle
#include "mozilla/layers/LayersTypes.h" // for LayersBackend
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
#include "nsRegion.h"
#include <vector>
#include "mozilla/WidgetUtils.h"
/**
* Different elements of a web pages are rendered into separate "layers" before
@@ -348,16 +349,21 @@ public:
/**
* Flush the current frame to the screen and tidy up.
*/
virtual void EndFrame() = 0;
virtual void SetFBAcquireFence(Layer* aLayer) {}
+ virtual FenceHandle GetReleaseFence()
+ {
+ return FenceHandle();
+ }
+
/**
* Post-rendering stuff if the rendering is done outside of this Compositor
* e.g., by Composer2D.
* aTransform is the transform from user space to window space.
*/
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
/**
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -353,17 +353,17 @@ public:
* If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the destruction
* will be synchronously coordinated with the compositor side, otherwise it
* will be done asynchronously.
*/
void ForceRemove();
virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
{
- mReleaseFenceHandle = aReleaseFenceHandle;
+ mReleaseFenceHandle.Merge(aReleaseFenceHandle);
}
const FenceHandle& GetReleaseFenceHandle() const
{
return mReleaseFenceHandle;
}
virtual void SetAcquireFenceHandle(FenceHandle aAcquireFenceHandle)
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -75,18 +75,16 @@ public:
~TextureParent();
bool Init(const SurfaceDescriptor& aSharedData,
const TextureFlags& aFlags);
void CompositorRecycle();
- void SendFenceHandleIfPresent();
-
virtual bool RecvClientRecycle() MOZ_OVERRIDE;
virtual bool RecvClearTextureHostSync() MOZ_OVERRIDE;
virtual bool RecvRemoveTexture() MOZ_OVERRIDE;
TextureHost* GetTextureHost() { return mTextureHost; }
@@ -142,24 +140,16 @@ TextureHost::AsTextureHost(PTextureParen
}
PTextureParent*
TextureHost::GetIPDLActor()
{
return mActor;
}
-// static
-void
-TextureHost::SendFenceHandleIfPresent(PTextureParent* actor)
-{
- TextureParent* parent = static_cast<TextureParent*>(actor);
- parent->SendFenceHandleIfPresent();
-}
-
FenceHandle
TextureHost::GetAndResetReleaseFenceHandle()
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
TextureHostOGL* hostOGL = this->AsHostOGL();
if (!hostOGL) {
return FenceHandle();
}
@@ -709,48 +699,25 @@ static void RecycleCallback(TextureHost*
TextureParent* tp = reinterpret_cast<TextureParent*>(aClosure);
tp->CompositorRecycle();
}
void
TextureParent::CompositorRecycle()
{
mTextureHost->ClearRecycleCallback();
- SendFenceHandleIfPresent();
if (mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
mozilla::unused << SendCompositorRecycle();
// Don't forget to prepare for the next reycle
// if TextureClient request it.
mWaitForClientRecycle = mTextureHost;
}
}
-void
-TextureParent::SendFenceHandleIfPresent()
-{
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
- if (mTextureHost) {
- TextureHostOGL* hostOGL = mTextureHost->AsHostOGL();
- if (!hostOGL) {
- return;
- }
- android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
- if (fence.get() && fence->isValid()) {
- // HWC might not provide Fence.
- // In this case, HWC implicitly handles buffer's fence.
-
- FenceHandle handle = FenceHandle(fence);
- RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(handle);
- mCompositableManager->SendFenceHandle(tracker, this, handle);
- }
- }
-#endif
-}
-
bool
TextureParent::RecvClientRecycle()
{
// This will allow the RecycleCallback to be called once the compositor
// releases any external references to TextureHost.
mTextureHost->SetRecycleCallback(RecycleCallback, this);
if (!mWaitForClientRecycle) {
RECYCLE_LOG("Not a recycable tile");
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -416,18 +416,16 @@ public:
/**
* Return a pointer to the IPDLActor.
*
* This is to be used with IPDL messages only. Do not store the returned
* pointer.
*/
PTextureParent* GetIPDLActor();
- static void SendFenceHandleIfPresent(PTextureParent* actor);
-
FenceHandle GetAndResetReleaseFenceHandle();
/**
* Specific to B2G's Composer2D
* XXX - more doc here
*/
virtual LayerRenderState GetRenderState()
{
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -157,45 +157,46 @@ CompositableParentManager::ReceiveCompos
case CompositableOperation::TOpRemoveTexture: {
const OpRemoveTexture& op = aEdit.get_OpRemoveTexture();
CompositableHost* compositable = AsCompositable(op);
RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
MOZ_ASSERT(tex.get());
compositable->RemoveTextureHost(tex);
// send FenceHandle if present.
- TextureHost::SendFenceHandleIfPresent(op.textureParent());
+ SendFenceHandleIfPresent(op.textureParent(), compositable);
break;
}
case CompositableOperation::TOpRemoveTextureAsync: {
const OpRemoveTextureAsync& op = aEdit.get_OpRemoveTextureAsync();
CompositableHost* compositable = AsCompositable(op);
RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
MOZ_ASSERT(tex.get());
compositable->RemoveTextureHost(tex);
if (!IsAsync() && GetChildProcessId()) {
// send FenceHandle if present via ImageBridge.
ImageBridgeParent::SendFenceHandleToTrackerIfPresent(
GetChildProcessId(),
op.holderId(),
op.transactionId(),
- op.textureParent());
+ op.textureParent(),
+ compositable);
// If the message is recievied via PLayerTransaction,
// Send message back via PImageBridge.
ImageBridgeParent::ReplyRemoveTexture(
GetChildProcessId(),
OpReplyRemoveTexture(true, // isMain
op.holderId(),
op.transactionId()));
} else {
// send FenceHandle if present.
- TextureHost::SendFenceHandleIfPresent(op.textureParent());
+ SendFenceHandleIfPresent(op.textureParent(), compositable);
ReplyRemoveTexture(OpReplyRemoveTexture(false, // isMain
op.holderId(),
op.transactionId()));
}
break;
}
case CompositableOperation::TOpUseTexture: {
@@ -253,11 +254,47 @@ CompositableParentManager::ReceiveCompos
default: {
MOZ_ASSERT(false, "bad type");
}
}
return true;
}
+void
+CompositableParentManager::SendPendingAsyncMessges()
+{
+ if (mPendingAsyncMessage.empty()) {
+ return;
+ }
+
+ // Some type of AsyncParentMessageData message could have
+ // one file descriptor (e.g. OpDeliverFence).
+ // A number of file descriptors per gecko ipc message have a limitation
+ // on OS_POSIX (MACOSX or LINUX).
+#if defined(OS_POSIX)
+ static const uint32_t kMaxMessageNumber = FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE;
+#else
+ // default number that works everywhere else
+ static const uint32_t kMaxMessageNumber = 250;
+#endif
+
+ InfallibleTArray<AsyncParentMessageData> messages;
+ messages.SetCapacity(mPendingAsyncMessage.size());
+ for (size_t i = 0; i < mPendingAsyncMessage.size(); i++) {
+ messages.AppendElement(mPendingAsyncMessage[i]);
+ // Limit maximum number of messages.
+ if (messages.Length() >= kMaxMessageNumber) {
+ SendAsyncMessage(messages);
+ // Initialize Messages.
+ messages.Clear();
+ }
+ }
+
+ if (messages.Length() > 0) {
+ SendAsyncMessage(messages);
+ }
+ mPendingAsyncMessage.clear();
+}
+
} // namespace
} // namespace
--- a/gfx/layers/ipc/CompositableTransactionParent.h
+++ b/gfx/layers/ipc/CompositableTransactionParent.h
@@ -25,22 +25,27 @@ typedef std::vector<mozilla::layers::Edi
// Since PCompositble has two potential manager protocols, we can't just call
// the Manager() method usually generated when there's one manager protocol,
// 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 SendFenceHandleIfPresent(PTextureParent* aTexture,
+ CompositableHost* aCompositableHost) = 0;
+
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence) = 0;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) = 0;
+ void SendPendingAsyncMessges();
+
/**
* Get child side's process Id.
*/
virtual base::ProcessId GetChildProcessId() = 0;
protected:
/**
* Handle the IPDL messages that affect PCompositable actors.
@@ -52,14 +57,15 @@ protected:
/**
* Return true if this protocol is asynchronous with respect to the content
* thread (ImageBridge for instance).
*/
virtual bool IsAsync() const { return false; }
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) {}
+ std::vector<AsyncParentMessageData> mPendingAsyncMessage;
};
} // namespace
} // namespace
#endif
--- a/gfx/layers/ipc/FenceUtils.h
+++ b/gfx/layers/ipc/FenceUtils.h
@@ -21,16 +21,17 @@ namespace layers {
struct FenceHandleFromChild;
struct FenceHandle {
FenceHandle() {}
explicit FenceHandle(const FenceHandleFromChild& aFenceHandle) {}
bool operator==(const FenceHandle&) const { return false; }
bool IsValid() const { return false; }
+ void Merge(const FenceHandle& aFenceHandle) {}
};
struct FenceHandleFromChild {
FenceHandleFromChild() {}
explicit FenceHandleFromChild(const FenceHandle& aFence) {}
bool operator==(const FenceHandle&) const { return false; }
bool operator==(const FenceHandleFromChild&) const { return false; }
bool IsValid() const { return false; }
--- a/gfx/layers/ipc/FenceUtilsGonk.cpp
+++ b/gfx/layers/ipc/FenceUtilsGonk.cpp
@@ -44,38 +44,45 @@ ParamTraits<FenceHandle>::Write(Message*
// which returned by getFlattenedSize() and getFdCount() are not changed.
// So we change nbytes and nfds back by call corresponding calls.
nbytes = flattenable->getFlattenedSize();
nfds = flattenable->getFdCount();
#else
flattenable->flatten(data, nbytes, fds, nfds);
#endif
aMsg->WriteSize(nbytes);
+ aMsg->WriteSize(nfds);
aMsg->WriteBytes(data, nbytes);
for (size_t n = 0; n < nfds; ++n) {
// These buffers can't die in transit because they're created
// synchonously and the parent-side buffer can only be dropped if
// there's a crash.
aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
}
}
bool
ParamTraits<FenceHandle>::Read(const Message* aMsg,
void** aIter, paramType* aResult)
{
size_t nbytes;
+ size_t nfds;
const char* data;
if (!aMsg->ReadSize(aIter, &nbytes) ||
+ !aMsg->ReadSize(aIter, &nfds) ||
!aMsg->ReadBytes(aIter, &data, nbytes)) {
return false;
}
- size_t nfds = aMsg->num_fds();
+ // Check if nfds is correct.
+ // aMsg->num_fds() could include fds of another ParamTraits<>s.
+ if (nfds > aMsg->num_fds()) {
+ return false;
+ }
int fds[nfds];
for (size_t n = 0; n < nfds; ++n) {
FileDescriptor fd;
if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
return false;
}
// If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
@@ -133,16 +140,17 @@ ParamTraits<FenceHandleFromChild>::Write
// which returned by getFlattenedSize() and getFdCount() are not changed.
// So we change nbytes and nfds back by call corresponding calls.
nbytes = flattenable->getFlattenedSize();
nfds = flattenable->getFdCount();
#else
flattenable->flatten(data, nbytes, fds, nfds);
#endif
aMsg->WriteSize(nbytes);
+ aMsg->WriteSize(nfds);
aMsg->WriteBytes(data, nbytes);
for (size_t n = 0; n < nfds; ++n) {
// If the Fence was shared cross-process, SCM_RIGHTS does
// the right thing and dup's the fd. If it's shared cross-thread,
// SCM_RIGHTS doesn't dup the fd. That's surprising, but we just
// deal with it here. NB: only the "default" (master) process can
// alloc gralloc buffers.
bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default);
@@ -156,24 +164,30 @@ ParamTraits<FenceHandleFromChild>::Write
}
}
bool
ParamTraits<FenceHandleFromChild>::Read(const Message* aMsg,
void** aIter, paramType* aResult)
{
size_t nbytes;
+ size_t nfds;
const char* data;
if (!aMsg->ReadSize(aIter, &nbytes) ||
+ !aMsg->ReadSize(aIter, &nfds) ||
!aMsg->ReadBytes(aIter, &data, nbytes)) {
return false;
}
- size_t nfds = aMsg->num_fds();
+ // Check if nfds is correct.
+ // aMsg->num_fds() could include fds of another ParamTraits<>s.
+ if (nfds > aMsg->num_fds()) {
+ return false;
+ }
int fds[nfds];
for (size_t n = 0; n < nfds; ++n) {
FileDescriptor fd;
if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
return false;
}
fds[n] = fd.fd;
@@ -206,15 +220,39 @@ FenceHandle::FenceHandle(const sp<Fence>
: mFence(aFence)
{
}
FenceHandle::FenceHandle(const FenceHandleFromChild& aFenceHandle) {
mFence = aFenceHandle.mFence;
}
+void
+FenceHandle::Merge(const FenceHandle& aFenceHandle)
+{
+ if (!aFenceHandle.IsValid()) {
+ return;
+ }
+
+ if (!IsValid()) {
+ mFence = aFenceHandle.mFence;
+ } else {
+ android::sp<android::Fence> mergedFence = android::Fence::merge(
+ android::String8::format("FenceHandle"),
+ mFence, aFenceHandle.mFence);
+ if (!mergedFence.get()) {
+ // synchronization is broken, the best we can do is hope fences
+ // signal in order so the new fence will act like a union.
+ // This error handling is same as android::ConsumerBase does.
+ mFence = aFenceHandle.mFence;
+ return;
+ }
+ mFence = mergedFence;
+ }
+}
+
FenceHandleFromChild::FenceHandleFromChild(const sp<Fence>& aFence)
: mFence(aFence)
{
}
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/ipc/FenceUtilsGonk.h
+++ b/gfx/layers/ipc/FenceUtilsGonk.h
@@ -18,40 +18,42 @@ namespace layers {
struct FenceHandleFromChild;
struct FenceHandle {
typedef android::Fence Fence;
FenceHandle()
{ }
- FenceHandle(const android::sp<Fence>& aFence);
+ explicit FenceHandle(const android::sp<Fence>& aFence);
- FenceHandle(const FenceHandleFromChild& aFenceHandle);
+ explicit FenceHandle(const FenceHandleFromChild& aFenceHandle);
bool operator==(const FenceHandle& aOther) const {
return mFence.get() == aOther.mFence.get();
}
bool IsValid() const
{
return mFence.get() && mFence->isValid();
}
+ void Merge(const FenceHandle& aFenceHandle);
+
android::sp<Fence> mFence;
};
struct FenceHandleFromChild {
typedef android::Fence Fence;
FenceHandleFromChild()
{ }
- FenceHandleFromChild(const android::sp<Fence>& aFence);
+ explicit FenceHandleFromChild(const android::sp<Fence>& aFence);
- FenceHandleFromChild(const FenceHandle& aFence) {
+ explicit FenceHandleFromChild(const FenceHandle& aFence) {
mFence = aFence.mFence;
}
bool operator==(const FenceHandle& aOther) const {
return mFence.get() == aOther.mFence.get();
}
bool operator==(const FenceHandleFromChild& aOther) const {
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -91,19 +91,35 @@ ImageBridgeParent::GetCompositorBackendT
void
ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
{
MessageLoop::current()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ImageBridgeParent::DeferredDestroy));
}
+class MOZ_STACK_CLASS AutoImageBridgeParentAsyncMessageSender
+{
+public:
+ explicit AutoImageBridgeParentAsyncMessageSender(ImageBridgeParent* aImageBridge)
+ : mImageBridge(aImageBridge) {}
+
+ ~AutoImageBridgeParentAsyncMessageSender()
+ {
+ mImageBridge->SendPendingAsyncMessges();
+ }
+private:
+ ImageBridgeParent* mImageBridge;
+};
+
bool
ImageBridgeParent::RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply)
{
+ AutoImageBridgeParentAsyncMessageSender autoAsyncMessageSender(this);
+
// If we don't actually have a compositor, then don't bother
// creating any textures.
if (Compositor::GetBackend() == LayersBackend::LAYERS_NONE) {
return true;
}
EditReplyVector replyv;
for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) {
@@ -331,66 +347,121 @@ ImageBridgeParent::CloneToplevel(const I
bool ImageBridgeParent::IsSameProcess() const
{
return OtherProcess() == ipc::kInvalidProcessHandle;
}
void
ImageBridgeParent::ReplyRemoveTexture(const OpReplyRemoveTexture& aReply)
{
- InfallibleTArray<AsyncParentMessageData> messages;
- messages.AppendElement(aReply);
- mozilla::unused << SendParentAsyncMessages(messages);
+ mPendingAsyncMessage.push_back(aReply);
}
/*static*/ void
ImageBridgeParent::ReplyRemoveTexture(base::ProcessId aChildProcessId,
const OpReplyRemoveTexture& aReply)
{
ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
if (!imageBridge) {
return;
}
imageBridge->ReplyRemoveTexture(aReply);
}
-/*static*/ void
-ImageBridgeParent::SendFenceHandleToTrackerIfPresent(uint64_t aDestHolderId,
- uint64_t aTransactionId,
- PTextureParent* aTexture)
+void
+ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture,
+ CompositableHost* aCompositableHost)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
return;
}
+
+ // Send a ReleaseFence of CompositorOGL.
+ if (aCompositableHost && aCompositableHost->GetCompositor()) {
+ FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
+ if (fence.IsValid()) {
+ RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+ HoldUntilComplete(tracker);
+ mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+ aTexture, nullptr,
+ fence));
+ }
+ }
+
+ // Send a ReleaseFence that is set by HwcComposer2D.
FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
- if (!fence.IsValid()) {
+ if (fence.IsValid()) {
+ RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+ HoldUntilComplete(tracker);
+ mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+ aTexture, nullptr,
+ fence));
+ }
+}
+
+void
+ImageBridgeParent::SendFenceHandleToTrackerIfPresent(uint64_t aDestHolderId,
+ uint64_t aTransactionId,
+ PTextureParent* aTexture,
+ CompositableHost* aCompositableHost)
+{
+ RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
+ if (!texture) {
return;
}
- RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
- HoldUntilComplete(tracker);
- InfallibleTArray<AsyncParentMessageData> messages;
- messages.AppendElement(OpDeliverFenceToTracker(tracker->GetId(),
- aDestHolderId,
- aTransactionId,
- fence));
- mozilla::unused << SendParentAsyncMessages(messages);
+ // Send a ReleaseFence of CompositorOGL.
+ if (aCompositableHost && aCompositableHost->GetCompositor()) {
+ FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
+ if (fence.IsValid()) {
+ RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+ HoldUntilComplete(tracker);
+ mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(tracker->GetId(),
+ aDestHolderId,
+ aTransactionId,
+ fence));
+ }
+ }
+
+ // Send a ReleaseFence that is set by HwcComposer2D.
+ FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
+ if (fence.IsValid()) {
+ RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+ HoldUntilComplete(tracker);
+ mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(tracker->GetId(),
+ aDestHolderId,
+ aTransactionId,
+ fence));
+ }
}
/*static*/ void
ImageBridgeParent::SendFenceHandleToTrackerIfPresent(base::ProcessId aChildProcessId,
uint64_t aDestHolderId,
uint64_t aTransactionId,
- PTextureParent* aTexture)
+ PTextureParent* aTexture,
+ CompositableHost* aCompositableHost)
{
ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
if (!imageBridge) {
return;
}
imageBridge->SendFenceHandleToTrackerIfPresent(aDestHolderId,
aTransactionId,
- aTexture);
+ aTexture,
+ aCompositableHost);
}
+/*static*/ void
+ImageBridgeParent::SendPendingAsyncMessges(base::ProcessId aChildProcessId)
+{
+#ifdef MOZ_WIDGET_GONK
+ ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
+ if (!imageBridge) {
+ return;
+ }
+ imageBridge->SendPendingAsyncMessges();
+#endif
+}
} // layers
} // mozilla
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -51,16 +51,19 @@ public:
virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
static PImageBridgeParent*
Create(Transport* aTransport, ProcessId aChildProcessId);
// CompositableParentManager
+ virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
+ CompositableHost* aCompositableHost) MOZ_OVERRIDE;
+
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence) MOZ_OVERRIDE;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) MOZ_OVERRIDE;
virtual base::ProcessId GetChildProcessId() MOZ_OVERRIDE
{
@@ -117,22 +120,27 @@ public:
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) MOZ_OVERRIDE;
static void ReplyRemoveTexture(base::ProcessId aChildProcessId,
const OpReplyRemoveTexture& aReply);
void SendFenceHandleToTrackerIfPresent(uint64_t aDestHolderId,
uint64_t aTransactionId,
- PTextureParent* aTexture);
+ PTextureParent* aTexture,
+ CompositableHost* aCompositableHost);
static void SendFenceHandleToTrackerIfPresent(base::ProcessId aChildProcessId,
uint64_t aDestHolderId,
uint64_t aTransactionId,
- PTextureParent* aTexture);
+ PTextureParent* aTexture,
+ CompositableHost* aCompositableHost);
+
+ using CompositableParentManager::SendPendingAsyncMessges;
+ static void SendPendingAsyncMessges(base::ProcessId aChildProcessId);
static ImageBridgeParent* GetInstance(ProcessId aId);
// Overriden from IToplevelProtocol
IToplevelProtocol*
CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
base::ProcessHandle aPeerProcess,
mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -13,16 +13,17 @@
#include "ShadowLayerParent.h" // for ShadowLayerParent
#include "CompositableTransactionParent.h" // for EditReplyVector
#include "ShadowLayersManager.h" // for ShadowLayersManager
#include "mozilla/gfx/BasePoint3D.h" // for BasePoint3D
#include "mozilla/layers/CanvasLayerComposite.h"
#include "mozilla/layers/ColorLayerComposite.h"
#include "mozilla/layers/Compositor.h" // for Compositor
#include "mozilla/layers/ContainerLayerComposite.h"
+#include "mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent
#include "mozilla/layers/ImageLayerComposite.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/layers/LayersMessages.h" // for EditReply, etc
#include "mozilla/layers/LayersSurfaces.h" // for PGrallocBufferParent
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
#include "mozilla/layers/PCompositableParent.h"
#include "mozilla/layers/PLayerParent.h" // for PLayerParent
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
@@ -187,16 +188,31 @@ LayerTransactionParent::RecvUpdateNoSwap
const bool& isRepeatTransaction,
const mozilla::TimeStamp& aTransactionStart)
{
return RecvUpdate(cset, aTransactionId, targetConfig, isFirstPaint,
scheduleComposite, paintSequenceNumber, isRepeatTransaction,
aTransactionStart, nullptr);
}
+class MOZ_STACK_CLASS AutoLayerTransactionParentAsyncMessageSender
+{
+public:
+ explicit AutoLayerTransactionParentAsyncMessageSender(LayerTransactionParent* aLayerTransaction)
+ : mLayerTransaction(aLayerTransaction) {}
+
+ ~AutoLayerTransactionParentAsyncMessageSender()
+ {
+ mLayerTransaction->SendPendingAsyncMessges();
+ ImageBridgeParent::SendPendingAsyncMessges(mLayerTransaction->GetChildProcessId());
+ }
+private:
+ LayerTransactionParent* mLayerTransaction;
+};
+
bool
LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
const uint64_t& aTransactionId,
const TargetConfig& targetConfig,
const bool& isFirstPaint,
const bool& scheduleComposite,
const uint32_t& paintSequenceNumber,
const bool& isRepeatTransaction,
@@ -218,16 +234,17 @@ LayerTransactionParent::RecvUpdate(const
}
if (mLayerManager && mLayerManager->GetCompositor() &&
!targetConfig.naturalBounds().IsEmpty()) {
mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation());
}
EditReplyVector replyv;
+ AutoLayerTransactionParentAsyncMessageSender autoAsyncMessageSender(this);
{
AutoResolveRefLayers resolve(mShadowLayersManager->GetCompositionManager(this));
layer_manager()->BeginTransaction();
}
for (EditArray::index_type i = 0; i < cset.Length(); ++i) {
const Edit& edit = cset[i];
@@ -886,16 +903,48 @@ LayerTransactionParent::ActorDestroy(Act
}
bool LayerTransactionParent::IsSameProcess() const
{
return OtherProcess() == ipc::kInvalidProcessHandle;
}
void
+LayerTransactionParent::SendFenceHandleIfPresent(PTextureParent* aTexture,
+ CompositableHost* aCompositableHost)
+{
+ RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
+ if (!texture) {
+ return;
+ }
+
+ // Send a ReleaseFence of CompositorOGL.
+ if (aCompositableHost && aCompositableHost->GetCompositor()) {
+ FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
+ if (fence.IsValid()) {
+ RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+ HoldUntilComplete(tracker);
+ mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+ aTexture, nullptr,
+ fence));
+ }
+ }
+
+ // Send a ReleaseFence that is set by HwcComposer2D.
+ FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
+ if (fence.IsValid()) {
+ RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+ HoldUntilComplete(tracker);
+ mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+ aTexture, nullptr,
+ fence));
+ }
+}
+
+void
LayerTransactionParent::SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence)
{
HoldUntilComplete(aTracker);
InfallibleTArray<AsyncParentMessageData> messages;
messages.AppendElement(OpDeliverFence(aTracker->GetId(),
aTexture, nullptr,
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -81,16 +81,19 @@ public:
virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE;
virtual bool IsSameProcess() const MOZ_OVERRIDE;
const uint64_t& GetPendingTransactionId() { return mPendingTransaction; }
void SetPendingTransactionId(uint64_t aId) { mPendingTransaction = aId; }
// CompositableParentManager
+ virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
+ CompositableHost* aCompositableHost) MOZ_OVERRIDE;
+
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureParent* aTexture,
const FenceHandle& aFence) MOZ_OVERRIDE;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) MOZ_OVERRIDE;
virtual base::ProcessId GetChildProcessId() MOZ_OVERRIDE
{
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -1393,59 +1393,43 @@ CompositorOGL::SetFBAcquireFence(Layer*
// FBAcquireFence is FramebufferSurface's AcquireFence.
// AcquireFence will be signaled when a buffer's content is available.
// See Bug 974152.
if (!aLayer) {
return;
}
- const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
- if (visibleRegion.IsEmpty()) {
- return;
+ android::sp<android::Fence> fence = new android::Fence(GetGonkDisplay()->GetPrevFBAcquireFd());
+ if (fence.get() && fence->isValid()) {
+ FenceHandle handle = FenceHandle(fence);
+ mReleaseFenceHandle.Merge(handle);
}
-
- // Set FBAcquireFence on ContainerLayer's childs
- ContainerLayer* container = aLayer->AsContainerLayer();
- if (container) {
- for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
- SetFBAcquireFence(child);
- }
- return;
- }
+}
- // Set FBAcquireFence as tiles' ReleaseFence on TiledLayerComposer.
- TiledLayerComposer* composer = nullptr;
- LayerComposite* shadow = aLayer->AsLayerComposite();
- // Only ask for the composer if we have a compositable host. Timing
- // may make it so that we don't - see bug 1000634.
- if (shadow && shadow->GetCompositableHost()) {
- composer = shadow->GetTiledLayerComposer();
- if (composer) {
- composer->SetReleaseFence(new android::Fence(GetGonkDisplay()->GetPrevFBAcquireFd()));
- return;
- }
+FenceHandle
+CompositorOGL::GetReleaseFence()
+{
+ if (!mReleaseFenceHandle.IsValid()) {
+ return FenceHandle();
}
+ return FenceHandle(new android::Fence(mReleaseFenceHandle.mFence->dup()));
+}
- // Set FBAcquireFence as layer buffer's ReleaseFence
- LayerRenderState state = aLayer->GetRenderState();
- if (!state.mTexture) {
- return;
- }
- TextureHostOGL* texture = state.mTexture->AsHostOGL();
- if (!texture) {
- return;
- }
- texture->SetReleaseFence(new android::Fence(GetGonkDisplay()->GetPrevFBAcquireFd()));
-}
#else
void
CompositorOGL::SetFBAcquireFence(Layer* aLayer)
{
}
+
+FenceHandle
+CompositorOGL::GetReleaseFence()
+{
+ return FenceHandle();
+}
#endif
void
CompositorOGL::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
{
// This lets us reftest and screenshot content rendered externally
if (mTarget) {
MakeCurrent();
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -204,16 +204,17 @@ public:
virtual void DrawQuad(const gfx::Rect& aRect,
const gfx::Rect& aClipRect,
const EffectChain &aEffectChain,
gfx::Float aOpacity,
const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE;
virtual void EndFrame() MOZ_OVERRIDE;
virtual void SetFBAcquireFence(Layer* aLayer) MOZ_OVERRIDE;
+ virtual FenceHandle GetReleaseFence() MOZ_OVERRIDE;
virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) MOZ_OVERRIDE;
virtual void AbortFrame() MOZ_OVERRIDE;
virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE;
virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE
{
if (!mGLContext)
@@ -388,14 +389,16 @@ private:
bool mDestroyed;
/**
* Height of the OpenGL context's primary framebuffer in pixels. Used by
* FlipY for the y-flipping calculation.
*/
GLint mHeight;
+
+ FenceHandle mReleaseFenceHandle;
};
}
}
#endif /* MOZILLA_GFX_COMPOSITOROGL_H */