Bug 1504699 - Part 1. Add signalling for WebRender to let owning process that surface may be recycled. r=nical

When we replace the external image ID an image key points to, the
previous external image ID may still be used by WebRender. We currently
wait until the frame has been rendered to release our hold on said
surface. With this patch, we will communicate the image key and previous
external image ID pairing to the owning process when releasing to let it
know that it can reuse it (e.g. for an animated image). Additionally we
now use the new textures updated checkpoint which should happen sooner
than the frame rendered checkpoint, but guarantee that WebRender is no
longer using the old external image ID.

Differential Revision: https://phabricator.services.mozilla.com/D10897
This commit is contained in:
Andrew Osmond 2018-09-28 15:11:15 -04:00
parent 75b0f36be3
commit c15ceec38e
7 changed files with 53 additions and 10 deletions

View File

@ -23,6 +23,7 @@ using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
using mozilla::wr::BuiltDisplayListDescriptor from "mozilla/webrender/webrender_ffi.h";
using mozilla::wr::IdNamespace from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::MaybeIdNamespace from "mozilla/webrender/WebRenderTypes.h";
using mozilla::wr::ExternalImageKeyPair from "mozilla/webrender/WebRenderTypes.h";
using mozilla::layers::WebRenderScrollData from "mozilla/layers/WebRenderScrollData.h";
using mozilla::layers::FocusTarget from "mozilla/layers/FocusTarget.h";
using mozilla::layers::LayersObserverEpoch from "mozilla/layers/LayersTypes.h";
@ -84,6 +85,7 @@ parent:
sync ShutdownSync();
child:
async WrUpdated(IdNamespace aNewIdNamespace, TextureFactoryIdentifier textureFactoryIdentifier);
async WrReleasedImages(ExternalImageKeyPair[] pairs);
async __delete__();
};

View File

@ -571,6 +571,12 @@ WebRenderBridgeChild::RecvWrUpdated(const wr::IdNamespace& aNewIdNamespace,
return IPC_OK();
}
mozilla::ipc::IPCResult
WebRenderBridgeChild::RecvWrReleasedImages(nsTArray<wr::ExternalImageKeyPair>&& aPairs)
{
return IPC_OK();
}
void
WebRenderBridgeChild::BeginClearCachedResources()
{

View File

@ -211,6 +211,7 @@ private:
mozilla::ipc::IPCResult RecvWrUpdated(const wr::IdNamespace& aNewIdNamespace,
const TextureFactoryIdentifier& textureFactoryIdentifier) override;
mozilla::ipc::IPCResult RecvWrReleasedImages(nsTArray<wr::ExternalImageKeyPair>&& aPairs) override;
void AddIPDLReference() {
MOZ_ASSERT(mIPCOpen == false);

View File

@ -254,23 +254,32 @@ class WebRenderBridgeParent::ScheduleSharedSurfaceRelease final
: public wr::NotificationHandler
{
public:
ScheduleSharedSurfaceRelease()
explicit ScheduleSharedSurfaceRelease(WebRenderBridgeParent* aWrBridge)
: mWrBridge(aWrBridge)
, mSurfaces(20)
{ }
void Add(const wr::ExternalImageId& aId)
void Add(const wr::ImageKey& aKey,
const wr::ExternalImageId& aId)
{
mSurfaces.AppendElement(aId);
mSurfaces.AppendElement(wr::ExternalImageKeyPair { aKey, aId });
}
void Notify(wr::Checkpoint) override
{
for (const auto& id : mSurfaces) {
SharedSurfacesParent::Release(id);
}
CompositorThreadHolder::Loop()->PostTask(
NewRunnableMethod<nsTArray<wr::ExternalImageKeyPair>>(
"ObserveSharedSurfaceRelease",
mWrBridge,
&WebRenderBridgeParent::ObserveSharedSurfaceRelease,
std::move(mSurfaces)
)
);
}
private:
AutoTArray<wr::ExternalImageId, 20> mSurfaces;
RefPtr<WebRenderBridgeParent> mWrBridge;
nsTArray<wr::ExternalImageKeyPair> mSurfaces;
};
class MOZ_STACK_CLASS AutoWebRenderBridgeParentAsyncMessageSender
@ -540,7 +549,8 @@ WebRenderBridgeParent::UpdateResources(const nsTArray<OpUpdateResource>& aResour
}
if (scheduleRelease) {
aUpdates.Notify(wr::Checkpoint::FrameRendered, std::move(scheduleRelease));
aUpdates.Notify(wr::Checkpoint::FrameTexturesUpdated,
std::move(scheduleRelease));
}
return true;
}
@ -695,9 +705,9 @@ WebRenderBridgeParent::UpdateExternalImage(wr::ExternalImageId aExtId,
// previous external image ID. This can happen when an image is animated,
// and it is changing the external image that the animation points to.
if (!aScheduleRelease) {
aScheduleRelease = MakeUnique<ScheduleSharedSurfaceRelease>();
aScheduleRelease = MakeUnique<ScheduleSharedSurfaceRelease>(this);
}
aScheduleRelease->Add(it->second);
aScheduleRelease->Add(aKey, it->second);
it->second = aExtId;
}
@ -725,6 +735,17 @@ WebRenderBridgeParent::UpdateExternalImage(wr::ExternalImageId aExtId,
return true;
}
void
WebRenderBridgeParent::ObserveSharedSurfaceRelease(const nsTArray<wr::ExternalImageKeyPair>& aPairs)
{
if (!mDestroyed) {
Unused << SendWrReleasedImages(aPairs);
}
for (const auto& pair : aPairs) {
SharedSurfacesParent::Release(pair.id);
}
}
mozilla::ipc::IPCResult
WebRenderBridgeParent::RecvUpdateResources(nsTArray<OpUpdateResource>&& aResourceUpdates,
nsTArray<RefCountedShmem>&& aSmallShmems,

View File

@ -255,6 +255,7 @@ private:
const ImageIntRect& aDirtyRect,
wr::TransactionBuilder& aResources,
UniquePtr<ScheduleSharedSurfaceRelease>& aScheduleRelease);
void ObserveSharedSurfaceRelease(const nsTArray<wr::ExternalImageKeyPair>& aPairs);
bool PushExternalImageForTexture(wr::ExternalImageId aExtId,
wr::ImageKey aKey,

View File

@ -189,6 +189,12 @@ struct ParamTraits<mozilla::wr::OpacityType>
{
};
template<>
struct ParamTraits<mozilla::wr::ExternalImageKeyPair>
: public PlainOldDataSerializer<mozilla::wr::ExternalImageKeyPair>
{
};
} // namespace IPC
#endif // GFX_WEBRENDERMESSAGEUTILS_H

View File

@ -50,6 +50,12 @@ typedef Maybe<ExternalImageId> MaybeExternalImageId;
typedef Maybe<FontInstanceOptions> MaybeFontInstanceOptions;
typedef Maybe<FontInstancePlatformOptions> MaybeFontInstancePlatformOptions;
struct ExternalImageKeyPair
{
ImageKey key;
ExternalImageId id;
};
/* Generate a brand new window id and return it. */
WindowId NewWindowId();