Bug 1428558 - Part 1. Streamline mappings between an ImageKey and an ExternalImageId for shared surfaces. r=nical

Async animated images need a single ImageKey which can point to any
frame represented by its own external image ID. Additionally a frame
could be referenced again directly (e.g. something shows/uses the first
frame of the animated image).

Before this patch, the ownership between an ImageKey and an external
image ID for a shared surface was not clearly expressed. This resulted
in a special command to release the reference to the external image
separately from deleting the image key.

This patch makes the strong reference to an external image ID and an
ImageKey directly related. Not only does this facilitate multiple
ImageKeys owning the same surface, it also simplifies the ownership
semantics.

Differential Revision: https://phabricator.services.mozilla.com/D7520
This commit is contained in:
Andrew Osmond 2018-10-02 13:27:52 -04:00
parent 1395b7eef1
commit 83a52f66de
6 changed files with 52 additions and 59 deletions

View File

@ -422,14 +422,8 @@ SharedSurfacesChild::Unshare(const wr::ExternalImageId& aId,
MOZ_ASSERT(NS_IsMainThread());
for (const auto& entry : aKeys) {
if (entry.mManager->IsDestroyed()) {
continue;
}
entry.mManager->AddImageKeyForDiscard(entry.mImageKey);
WebRenderBridgeChild* wrBridge = entry.mManager->WrBridge();
if (wrBridge) {
wrBridge->DeallocExternalImageId(aId);
if (!entry.mManager->IsDestroyed()) {
entry.mManager->AddImageKeyForDiscard(entry.mImageKey);
}
}

View File

@ -73,10 +73,6 @@ struct OpRemovePipelineIdForCompositable {
PipelineId pipelineId;
};
struct OpRemoveExternalImageId {
ExternalImageId externalImageId;
};
struct OpReleaseTextureOfImage {
ImageKey key;
};
@ -97,7 +93,6 @@ struct OpUpdatedAsyncImagePipeline {
union WebRenderParentCommand {
OpAddPipelineIdForCompositable;
OpRemovePipelineIdForCompositable;
OpRemoveExternalImageId;
OpReleaseTextureOfImage;
OpUpdateAsyncImagePipeline;
OpUpdatedAsyncImagePipeline;

View File

@ -222,13 +222,6 @@ WebRenderBridgeChild::GetNextExternalImageId()
return id.value();
}
void
WebRenderBridgeChild::DeallocExternalImageId(const wr::ExternalImageId& aImageId)
{
AddWebRenderParentCommand(
OpRemoveExternalImageId(aImageId));
}
void
WebRenderBridgeChild::ReleaseTextureOfImage(const wr::ImageKey& aKey)
{

View File

@ -101,8 +101,6 @@ public:
const CompositableHandle& aHandlee);
void RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId);
void DeallocExternalImageId(const wr::ExternalImageId& aImageId);
/// Release TextureClient that is bounded to ImageKey.
/// It is used for recycling TextureClient.
void ReleaseTextureOfImage(const wr::ImageKey& aKey);

View File

@ -426,7 +426,7 @@ WebRenderBridgeParent::UpdateResources(const nsTArray<OpUpdateResource>& aResour
}
case OpUpdateResource::TOpDeleteImage: {
const auto& op = cmd.get_OpDeleteImage();
aUpdates.DeleteImage(op.key());
DeleteImage(op.key(), aUpdates);
break;
}
case OpUpdateResource::TOpDeleteFont: {
@ -456,29 +456,30 @@ WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey
return true;
}
RefPtr<DataSourceSurface> dSurf = SharedSurfacesParent::Acquire(aExtId);
if (dSurf) {
auto it = mSharedSurfaceIds.emplace(wr::AsUint64(aExtId));
if (!it.second) {
// We already have a mapping for this image, so decrement the ownership
// counter just increased unnecessarily. This can happen when an image is
// slow to decode and we need to invalidate it by updating its image key.
SharedSurfacesParent::Release(aExtId);
}
auto key = wr::AsUint64(aKey);
auto it = mSharedSurfaceIds.find(key);
if (it != mSharedSurfaceIds.end()) {
gfxCriticalNote << "Readding known shared surface: " << key;
return false;
}
if (!gfxEnv::EnableWebRenderRecording()) {
wr::ImageDescriptor descriptor(dSurf->GetSize(), dSurf->Stride(),
dSurf->GetFormat());
aResources.AddExternalImage(aKey, descriptor, aExtId,
wr::WrExternalImageBufferType::ExternalBuffer,
0);
return true;
}
} else {
RefPtr<DataSourceSurface> dSurf = SharedSurfacesParent::Acquire(aExtId);
if (!dSurf) {
gfxCriticalNote << "DataSourceSurface of SharedSurfaces does not exist for extId:" << wr::AsUint64(aExtId);
return false;
}
mSharedSurfaceIds.insert(std::make_pair(key, aExtId));
if (!gfxEnv::EnableWebRenderRecording()) {
wr::ImageDescriptor descriptor(dSurf->GetSize(), dSurf->Stride(),
dSurf->GetFormat());
aResources.AddExternalImage(aKey, descriptor, aExtId,
wr::WrExternalImageBufferType::ExternalBuffer,
0);
return true;
}
DataSourceSurface::MappedSurface map;
if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
gfxCriticalNote << "DataSourceSurface failed to map for Image for extId:" << wr::AsUint64(aExtId);
@ -570,18 +571,32 @@ WebRenderBridgeParent::UpdateExternalImage(wr::ExternalImageId aExtId,
return true;
}
uint64_t imageId = wr::AsUint64(aExtId);
if (mSharedSurfaceIds.find(imageId) == mSharedSurfaceIds.end()) {
gfxCriticalNote << "Updating unknown shared surface: " << wr::AsUint64(aExtId);
auto key = wr::AsUint64(aKey);
auto it = mSharedSurfaceIds.find(key);
if (it == mSharedSurfaceIds.end()) {
gfxCriticalNote << "Updating unknown shared surface: " << key;
return false;
}
RefPtr<DataSourceSurface> dSurf = SharedSurfacesParent::Get(aExtId);
RefPtr<DataSourceSurface> dSurf;
if (it->second == aExtId) {
dSurf = SharedSurfacesParent::Get(aExtId);
} else {
dSurf = SharedSurfacesParent::Acquire(aExtId);
}
if (!dSurf) {
gfxCriticalNote << "Shared surface does not exist for extId:" << wr::AsUint64(aExtId);
return false;
}
if (!(it->second == aExtId)) {
// We already have a mapping for this image key, so ensure we release the
// previous external image ID.
mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, it->second);
it->second = aExtId;
}
if (!gfxEnv::EnableWebRenderRecording()) {
wr::ImageDescriptor descriptor(dSurf->GetSize(), dSurf->Stride(),
dSurf->GetFormat());
@ -1036,11 +1051,6 @@ WebRenderBridgeParent::ProcessWebRenderParentCommands(const InfallibleTArray<Web
RemovePipelineIdForCompositable(op.pipelineId(), aTxn);
break;
}
case WebRenderParentCommand::TOpRemoveExternalImageId: {
const OpRemoveExternalImageId& op = cmd.get_OpRemoveExternalImageId();
RemoveExternalImageId(op.externalImageId());
break;
}
case WebRenderParentCommand::TOpReleaseTextureOfImage: {
const OpReleaseTextureOfImage& op = cmd.get_OpReleaseTextureOfImage();
ReleaseTextureOfImage(op.key());
@ -1274,17 +1284,20 @@ WebRenderBridgeParent::RemovePipelineIdForCompositable(const wr::PipelineId& aPi
}
void
WebRenderBridgeParent::RemoveExternalImageId(const ExternalImageId& aImageId)
WebRenderBridgeParent::DeleteImage(const ImageKey& aKey,
wr::TransactionBuilder& aUpdates)
{
if (mDestroyed) {
return;
}
uint64_t imageId = wr::AsUint64(aImageId);
if (mSharedSurfaceIds.find(imageId) != mSharedSurfaceIds.end()) {
mSharedSurfaceIds.erase(imageId);
mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, aImageId);
auto it = mSharedSurfaceIds.find(wr::AsUint64(aKey));
if (it != mSharedSurfaceIds.end()) {
mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, it->second);
mSharedSurfaceIds.erase(it);
}
aUpdates.DeleteImage(aKey);
}
void
@ -1858,8 +1871,7 @@ WebRenderBridgeParent::ClearResources()
}
mAsyncCompositables.clear();
for (const auto& entry : mSharedSurfaceIds) {
wr::ExternalImageId id = wr::ToExternalImageId(entry);
mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, id);
mAsyncImageManager->HoldExternalImage(mPipelineId, mWrEpoch, entry.second);
}
mSharedSurfaceIds.clear();

View File

@ -249,7 +249,8 @@ private:
void RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId,
wr::TransactionBuilder& aTxn);
void RemoveExternalImageId(const ExternalImageId& aImageId);
void DeleteImage(const wr::ImageKey& aKey,
wr::TransactionBuilder& aUpdates);
void ReleaseTextureOfImage(const wr::ImageKey& aKey);
LayersId GetLayersId() const;
@ -335,7 +336,7 @@ private:
std::unordered_set<uint64_t> mActiveAnimations;
std::unordered_map<uint64_t, RefPtr<WebRenderImageHost>> mAsyncCompositables;
std::unordered_map<uint64_t, CompositableTextureHostRef> mTextureHosts;
std::unordered_set<uint64_t> mSharedSurfaceIds;
std::unordered_map<uint64_t, wr::ExternalImageId> mSharedSurfaceIds;
TimeDuration mVsyncRate;
TimeStamp mPreviousFrameTimeStamp;