Bug 1343754 - Add a function for replacing event target for actor and label PTexture; r?bevistseng, nical, billm
MozReview-Commit-ID: KGVBWsexkqC
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -876,36 +876,51 @@ TextureClient::InitIPDLActor(Compositabl
if (currentTexFwd && currentTexFwd != aForwarder->GetTextureForwarder()) {
gfxCriticalError() << "Attempt to move a texture to a different channel CF.";
return false;
}
if (currentFwd && currentFwd->GetCompositorBackendType() != aForwarder->GetCompositorBackendType()) {
gfxCriticalError() << "Attempt to move a texture to different compositor backend.";
return false;
}
+ if (ShadowLayerForwarder* forwarder = aForwarder->AsLayerForwarder()) {
+ // Do the DOM labeling.
+ if (nsIEventTarget* target = forwarder->GetEventTarget()) {
+ forwarder->GetCompositorBridgeChild()->ReplaceEventTargetForActor(
+ mActor, target);
+ }
+ }
mActor->mCompositableForwarder = aForwarder;
}
return true;
}
MOZ_ASSERT(!mActor || mActor->mDestroyed, "Cannot use a texture on several IPC channels.");
SurfaceDescriptor desc;
if (!ToSurfaceDescriptor(desc)) {
return false;
}
// Try external image id allocation.
mExternalImageId = aForwarder->GetTextureForwarder()->GetNextExternalImageId();
+ nsIEventTarget* target = nullptr;
+ // Get the layers id if the forwarder is a ShadowLayerForwarder.
+ if (ShadowLayerForwarder* forwarder = aForwarder->AsLayerForwarder()) {
+ target = forwarder->GetEventTarget();
+ }
+
PTextureChild* actor = aForwarder->GetTextureForwarder()->CreateTexture(
desc,
aForwarder->GetCompositorBackendType(),
GetFlags(),
mSerial,
- mExternalImageId);
+ mExternalImageId,
+ target);
+
if (!actor) {
gfxCriticalNote << static_cast<int32_t>(desc.type()) << ", "
<< static_cast<int32_t>(aForwarder->GetCompositorBackendType()) << ", "
<< static_cast<uint32_t>(GetFlags())
<< ", " << mSerial;
return false;
}
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -111,16 +111,18 @@ public:
virtual bool InForwarderThread() = 0;
void AssertInForwarderThread() {
MOZ_ASSERT(InForwarderThread());
}
static uint32_t GetMaxFileDescriptorsPerMessage();
+ virtual ShadowLayerForwarder* AsLayerForwarder() { return nullptr; }
+
protected:
nsTArray<RefPtr<TextureClient> > mTexturesToRemove;
nsTArray<RefPtr<CompositableClient>> mCompositableClientsToRemove;
};
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -14,16 +14,17 @@
#include "gfxPrefs.h"
#include "mozilla/dom/TabGroup.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/APZChild.h"
#include "mozilla/layers/IAPZCTreeManager.h"
#include "mozilla/layers/APZCTreeManagerChild.h"
#include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/PLayerTransactionChild.h"
+#include "mozilla/layers/PTextureChild.h"
#include "mozilla/layers/TextureClient.h"// for TextureClient
#include "mozilla/layers/TextureClientPool.h"// for TextureClientPool
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/mozalloc.h" // for operator new, etc
#include "nsAutoPtr.h"
@@ -1046,25 +1047,34 @@ CompositorBridgeChild::GetTileLockAlloca
}
if (!mSectionAllocator) {
mSectionAllocator = new FixedSizeSmallShmemSectionAllocator(this);
}
return mSectionAllocator;
}
-
PTextureChild*
CompositorBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId)
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget)
{
- return PCompositorBridgeChild::SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, 0 /* FIXME? */, aSerial, aExternalImageId);
+ PTextureChild* textureChild = AllocPTextureChild(
+ aSharedData, aLayersBackend, aFlags, 0 /* FIXME */, aSerial, aExternalImageId);
+
+ // Do the DOM labeling.
+ if (aTarget) {
+ SetEventTargetForActor(textureChild, aTarget);
+ }
+
+ return SendPTextureConstructor(
+ textureChild, aSharedData, aLayersBackend, aFlags, 0 /* FIXME? */, aSerial, aExternalImageId);
}
bool
CompositorBridgeChild::AllocUnsafeShmem(size_t aSize,
ipc::SharedMemory::SharedMemoryType aType,
ipc::Shmem* aShmem)
{
ShmemAllocated(this);
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -129,17 +129,18 @@ public:
virtual bool DeallocPTextureChild(PTextureChild* actor) override;
virtual mozilla::ipc::IPCResult
RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId) override;
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget) override;
virtual void HandleFatalError(const char* aName, const char* aMsg) const override;
/**
* Request that the parent tell us when graphics are ready on GPU.
* When we get that message, we bounce it to the TabParent via
* the TabChild
* @param tabChild The object to bounce the note to. Non-NULL.
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -1041,17 +1041,18 @@ ImageBridgeChild::RecvDidComposite(Infal
return IPC_OK();
}
PTextureChild*
ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId)
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget)
{
MOZ_ASSERT(CanSend());
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial, aExternalImageId);
}
static bool
IBCAddOpDestroy(CompositableTransaction* aTxn, const OpDestroy& op)
{
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -323,21 +323,23 @@ public:
/**
* See ISurfaceAllocator.h
* Can be used from any thread.
* If used outside the ImageBridgeChild thread, it will proxy a synchronous
* call on the ImageBridgeChild thread.
*/
virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
- virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
- LayersBackend aLayersBackend,
- TextureFlags aFlags,
- uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId) override;
+ virtual PTextureChild* CreateTexture(
+ const SurfaceDescriptor& aSharedData,
+ LayersBackend aLayersBackend,
+ TextureFlags aFlags,
+ uint64_t aSerial,
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget = nullptr) override;
virtual bool IsSameProcess() const override;
virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; }
virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; }
bool InForwarderThread() override {
return InImageBridgeChildThread();
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -390,16 +390,18 @@ public:
bool InForwarderThread() override {
return NS_IsMainThread();
}
PaintTiming& GetPaintTiming() {
return mPaintTiming;
}
+ ShadowLayerForwarder* AsLayerForwarder() override { return this; }
+
// Returns true if aSurface wraps a Shmem.
static bool IsShmem(SurfaceDescriptor* aSurface);
/**
* Sends a synchronous ping to the compsoitor.
*
* This is bad for performance and should only be called as a last resort if the
* compositor may be blocked for a long period of time, to avoid that the content
@@ -407,33 +409,36 @@ public:
* and releasing.
*/
void SyncWithCompositor();
TextureForwarder* GetTextureForwarder() override { return GetCompositorBridgeChild(); }
LayersIPCActor* GetLayersIPCActor() override { return this; }
ActiveResourceTracker& GetActiveResourceTracker() { return *mActiveResourceTracker.get(); }
+
+ CompositorBridgeChild* GetCompositorBridgeChild();
+
+ nsIEventTarget* GetEventTarget() { return mEventTarget; };
+
protected:
virtual ~ShadowLayerForwarder();
explicit ShadowLayerForwarder(ClientLayerManager* aClientLayerManager);
#ifdef DEBUG
void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const;
#else
void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const {}
#endif
RefPtr<CompositableClient> FindCompositable(const CompositableHandle& aHandle);
bool InWorkerThread();
- CompositorBridgeChild* GetCompositorBridgeChild();
-
RefPtr<LayerTransactionChild> mShadowManager;
RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
private:
ClientLayerManager* mClientLayerManager;
Transaction* mTxn;
MessageLoop* mMessageLoop;
--- a/gfx/layers/ipc/TextureForwarder.h
+++ b/gfx/layers/ipc/TextureForwarder.h
@@ -67,15 +67,16 @@ public:
/**
* Create a TextureChild/Parent pair as as well as the TextureHost on the parent side.
*/
virtual PTextureChild* CreateTexture(
const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId) = 0;
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget = nullptr) = 0;
};
} // namespace layers
} // namespace mozilla
#endif
--- a/gfx/layers/ipc/VideoBridgeChild.cpp
+++ b/gfx/layers/ipc/VideoBridgeChild.cpp
@@ -103,17 +103,18 @@ VideoBridgeChild::DeallocPVideoBridgeChi
mIPDLSelfRef = nullptr;
}
PTextureChild*
VideoBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId)
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget)
{
MOZ_ASSERT(CanSend());
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
}
bool VideoBridgeChild::IsSameProcess() const
{
return OtherPid() == base::GetCurrentProcId();
--- a/gfx/layers/ipc/VideoBridgeChild.h
+++ b/gfx/layers/ipc/VideoBridgeChild.h
@@ -44,17 +44,18 @@ public:
mozilla::ipc::Shmem* aShmem) override;
bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
// TextureForwarder
PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId) override;
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget = nullptr) override;
// ClientIPCAllocator
base::ProcessId GetParentPid() const override { return OtherPid(); }
MessageLoop * GetMessageLoop() const override { return mMessageLoop; }
void CancelWaitForRecycle(uint64_t aTextureId) override { MOZ_ASSERT(false, "NO RECYCLING HERE"); }
// ISurfaceAllocator
bool IsSameProcess() const override;
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -348,17 +348,18 @@ VRManagerChild::RecvParentAsyncMessages(
return IPC_OK();
}
PTextureChild*
VRManagerChild::CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags,
uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId)
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget)
{
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
}
void
VRManagerChild::CancelWaitForRecycle(uint64_t aTextureId)
{
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -59,21 +59,23 @@ public:
static void InitSameProcess();
static void InitWithGPUProcess(Endpoint<PVRManagerChild>&& aEndpoint);
static bool InitForContent(Endpoint<PVRManagerChild>&& aEndpoint);
static bool ReinitForContent(Endpoint<PVRManagerChild>&& aEndpoint);
static void ShutDown();
static bool IsCreated();
- virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
- layers::LayersBackend aLayersBackend,
- TextureFlags aFlags,
- uint64_t aSerial,
- wr::MaybeExternalImageId& aExternalImageId) override;
+ virtual PTextureChild* CreateTexture(
+ const SurfaceDescriptor& aSharedData,
+ layers::LayersBackend aLayersBackend,
+ TextureFlags aFlags,
+ uint64_t aSerial,
+ wr::MaybeExternalImageId& aExternalImageId,
+ nsIEventTarget* aTarget = nullptr) override;
virtual void CancelWaitForRecycle(uint64_t aTextureId) override;
PVRLayerChild* CreateVRLayer(uint32_t aDisplayID,
const Rect& aLeftEyeRect,
const Rect& aRightEyeRect,
nsIEventTarget* aTarget);
static void IdentifyTextureHost(const layers::TextureFactoryIdentifier& aIdentifier);
--- a/ipc/chromium/src/base/id_map.h
+++ b/ipc/chromium/src/base/id_map.h
@@ -72,16 +72,21 @@ class IDMap {
void RemoveIfPresent(int32_t id) {
iterator i = data_.find(id);
if (i != data_.end()) {
data_.erase(i);
}
}
+ void ReplaceWithID(const T& data, int32_t id) {
+ DCHECK(data_.find(id) != data_.end()) << "item doesn't exist";
+ data_[id] = data;
+ }
+
bool IsEmpty() const {
return data_.empty();
}
void Clear() {
data_.clear();
}
--- a/ipc/glue/ProtocolUtils.cpp
+++ b/ipc/glue/ProtocolUtils.cpp
@@ -542,22 +542,38 @@ void
IProtocol::SetEventTargetForActor(IProtocol* aActor, nsIEventTarget* aEventTarget)
{
// Make sure we have a manager for the internal method to access.
aActor->SetManager(this);
SetEventTargetForActorInternal(aActor, aEventTarget);
}
void
+IProtocol::ReplaceEventTargetForActor(IProtocol* aActor,
+ nsIEventTarget* aEventTarget)
+{
+ // Ensure the actor has been registered.
+ MOZ_ASSERT(aActor->Manager());
+ ReplaceEventTargetForActorInternal(aActor, aEventTarget);
+}
+
+void
IProtocol::SetEventTargetForActorInternal(IProtocol* aActor,
nsIEventTarget* aEventTarget)
{
Manager()->SetEventTargetForActorInternal(aActor, aEventTarget);
}
+void
+IProtocol::ReplaceEventTargetForActorInternal(IProtocol* aActor,
+ nsIEventTarget* aEventTarget)
+{
+ Manager()->ReplaceEventTargetForActorInternal(aActor, aEventTarget);
+}
+
nsIEventTarget*
IProtocol::GetActorEventTarget()
{
// We should only call this function when this actor has been registered and
// is not unregistered yet.
MOZ_RELEASE_ASSERT(mId != kNullActorId && mId != kFreedActorId);
RefPtr<nsIEventTarget> target = Manager()->GetActorEventTargetInternal(this);
return target;
@@ -871,10 +887,26 @@ IToplevelProtocol::SetEventTargetForActo
// ID.
int32_t id = Register(aActor);
aActor->SetId(id);
MutexAutoLock lock(mEventTargetMutex);
mEventTargetMap.AddWithID(aEventTarget, id);
}
+void
+IToplevelProtocol::ReplaceEventTargetForActorInternal(
+ IProtocol* aActor,
+ nsIEventTarget* aEventTarget)
+{
+ // The EventTarget of a ToplevelProtocol shall never be set.
+ MOZ_RELEASE_ASSERT(aActor != this);
+
+ int32_t id = aActor->Id();
+ // The ID of the actor should have existed.
+ MOZ_RELEASE_ASSERT(id!= kNullActorId && id!= kFreedActorId);
+
+ MutexAutoLock lock(mEventTargetMutex);
+ mEventTargetMap.ReplaceWithID(aEventTarget, id);
+}
+
} // namespace ipc
} // namespace mozilla
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -186,27 +186,36 @@ public:
// Sets an event target to which all messages for aActor will be
// dispatched. This method must be called before right before the SendPFoo
// message for aActor is sent. And SendPFoo *must* be called if
// SetEventTargetForActor is called. The receiver when calling
// SetEventTargetForActor must be the actor that will be the manager for
// aActor.
void SetEventTargetForActor(IProtocol* aActor, nsIEventTarget* aEventTarget);
+ // Replace the event target for the messages of aActor. There must not be
+ // any messages of aActor in the task queue, or we might run into some
+ // unexpected behavior.
+ void ReplaceEventTargetForActor(IProtocol* aActor,
+ nsIEventTarget* aEventTarget);
+
// Returns the event target set by SetEventTargetForActor() if available.
virtual nsIEventTarget* GetActorEventTarget();
protected:
friend class IToplevelProtocol;
void SetId(int32_t aId) { mId = aId; }
void SetManager(IProtocol* aManager);
void SetIPCChannel(MessageChannel* aChannel) { mChannel = aChannel; }
virtual void SetEventTargetForActorInternal(IProtocol* aActor, nsIEventTarget* aEventTarget);
+ virtual void ReplaceEventTargetForActorInternal(
+ IProtocol* aActor,
+ nsIEventTarget* aEventTarget);
virtual already_AddRefed<nsIEventTarget>
GetActorEventTargetInternal(IProtocol* aActor);
static const int32_t kNullActorId = 0;
static const int32_t kFreedActorId = 1;
private:
@@ -383,16 +392,19 @@ protected:
GetConstructedEventTarget(const Message& aMsg) { return nullptr; }
// Override this method in top-level protocols to change the event target
// for specific messages.
virtual already_AddRefed<nsIEventTarget>
GetSpecificMessageEventTarget(const Message& aMsg) { return nullptr; }
virtual void SetEventTargetForActorInternal(IProtocol* aActor, nsIEventTarget* aEventTarget);
+ virtual void ReplaceEventTargetForActorInternal(
+ IProtocol* aActor,
+ nsIEventTarget* aEventTarget);
virtual already_AddRefed<nsIEventTarget>
GetActorEventTargetInternal(IProtocol* aActor);
private:
ProtocolId mProtocolId;
UniquePtr<Transport> mTrans;
base::ProcessId mOtherPid;