Bug 1504699 - Part 5. Stop sharing code between SharedUserData and SharedSurfacesAnimation. r=nical

Originally it made sense to share the code, but now the latter has
become too specialized to reuse it. Fork it off here and update it later
parts in this series.

Differential Revision: https://phabricator.services.mozilla.com/D10901
This commit is contained in:
Andrew Osmond 2018-10-03 08:19:14 -04:00
Родитель 01269d4189
Коммит 918b734a20
4 изменённых файлов: 96 добавлений и 15 удалений

Просмотреть файл

@ -245,6 +245,9 @@ ImageContainer::~ImageContainer()
imageBridge->ForgetImageContainer(mAsyncContainerHandle);
}
}
if (mSharedAnimation) {
mSharedAnimation->Destroy();
}
}
RefPtr<PlanarYCbCrImage>

Просмотреть файл

@ -709,7 +709,7 @@ private:
// asynchronusly using the ImageBridge IPDL protocol.
RefPtr<ImageClient> mImageClient;
nsAutoPtr<SharedSurfacesAnimation> mSharedAnimation;
RefPtr<SharedSurfacesAnimation> mSharedAnimation;
bool mIsAsync;
CompositableHandle mAsyncContainerHandle;

Просмотреть файл

@ -475,6 +475,34 @@ SharedSurfacesChild::UpdateAnimation(ImageContainer* aContainer,
return anim->SetCurrentFrame(aSurface, sharedSurface, aDirtyRect);
}
SharedSurfacesAnimation::~SharedSurfacesAnimation()
{
MOZ_ASSERT(mKeys.IsEmpty());
}
void
SharedSurfacesAnimation::Destroy()
{
if (!NS_IsMainThread()) {
nsCOMPtr<nsIRunnable> task =
NewRunnableMethod("SharedSurfacesAnimation::Destroy",
this, &SharedSurfacesAnimation::Destroy);
SystemGroup::Dispatch(TaskCategory::Other, task.forget());
return;
}
if (mKeys.IsEmpty()) {
return;
}
for (const auto& entry : mKeys) {
MOZ_ASSERT(!entry.mManager->IsDestroyed());
entry.mManager->AddImageKeyForDiscard(entry.mImageKey);
}
mKeys.Clear();
}
nsresult
SharedSurfacesAnimation::SetCurrentFrame(SourceSurface* aParentSurface,
SourceSurfaceSharedData* aSurface,
@ -482,7 +510,7 @@ SharedSurfacesAnimation::SetCurrentFrame(SourceSurface* aParentSurface,
{
MOZ_ASSERT(aSurface);
SharedUserData* data = nullptr;
SharedSurfacesChild::SharedUserData* data = nullptr;
nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data);
if (NS_FAILED(rv)) {
return rv;
@ -494,12 +522,8 @@ SharedSurfacesAnimation::SetCurrentFrame(SourceSurface* aParentSurface,
auto i = mKeys.Length();
while (i > 0) {
--i;
SharedSurfacesChild::ImageKeyData& entry = mKeys[i];
if (entry.mManager->IsDestroyed()) {
mKeys.RemoveElementAt(i);
continue;
}
ImageKeyData& entry = mKeys[i];
MOZ_ASSERT(!entry.mManager->IsDestroyed());
entry.MergeDirtyRect(Some(aDirtyRect));
Maybe<IntRect> dirtyRect = entry.TakeDirtyRect();
@ -520,7 +544,7 @@ SharedSurfacesAnimation::UpdateKey(SourceSurface* aParentSurface,
wr::IpcResourceUpdateQueue& aResources,
wr::ImageKey& aKey)
{
SharedUserData* data = nullptr;
SharedSurfacesChild::SharedUserData* data = nullptr;
nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data);
if (NS_FAILED(rv)) {
return rv;
@ -532,9 +556,51 @@ SharedSurfacesAnimation::UpdateKey(SourceSurface* aParentSurface,
mId = data->Id();
}
aKey = SharedSurfacesChild::SharedUserData::UpdateKey(aManager,
aResources,
Nothing());
// We iterate through all of the items to ensure we clean up the old
// WebRenderLayerManager references. Most of the time there will be few
// entries and this should not be particularly expensive compared to the
// cost of duplicating image keys. In an ideal world, we would generate a
// single key for the surface, and it would be usable on all of the
// renderer instances. For now, we must allocate a key for each WR bridge.
wr::ImageKey key;
bool found = false;
auto i = mKeys.Length();
while (i > 0) {
--i;
ImageKeyData& entry = mKeys[i];
MOZ_ASSERT(!entry.mManager->IsDestroyed());
if (entry.mManager == aManager) {
WebRenderBridgeChild* wrBridge = aManager->WrBridge();
MOZ_ASSERT(wrBridge);
// Even if the manager is the same, its underlying WebRenderBridgeChild
// can change state. If our namespace differs, then our old key has
// already been discarded.
bool ownsKey = wrBridge->GetNamespace() == entry.mImageKey.mNamespace;
if (!ownsKey) {
entry.mImageKey = wrBridge->GetNextImageKey();
aResources.AddExternalImage(mId, entry.mImageKey);
} else {
Maybe<IntRect> dirtyRect = entry.TakeDirtyRect();
if (dirtyRect) {
aResources.UpdateExternalImage(mId, entry.mImageKey,
ViewAs<ImagePixel>(dirtyRect.ref()));
}
}
aKey = entry.mImageKey;
found = true;
break;
}
}
if (!found) {
aKey = aManager->WrBridge()->GetNextImageKey();
ImageKeyData data(aManager, aKey);
mKeys.AppendElement(std::move(data));
aResources.AddExternalImage(mId, aKey);
}
return NS_OK;
}

Просмотреть файл

@ -97,7 +97,7 @@ private:
friend class SharedSurfacesAnimation;
class ImageKeyData final {
class ImageKeyData {
public:
ImageKeyData(WebRenderLayerManager* aManager,
const wr::ImageKey& aImageKey);
@ -120,7 +120,7 @@ private:
wr::ImageKey mImageKey;
};
class SharedUserData {
class SharedUserData final {
public:
SharedUserData()
: mShared(false)
@ -188,12 +188,16 @@ private:
* This helper class owns a single ImageKey which will map to different external
* image IDs representing different frames in an animation.
*/
class SharedSurfacesAnimation final : private SharedSurfacesChild::SharedUserData
class SharedSurfacesAnimation final
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedSurfacesAnimation)
SharedSurfacesAnimation()
{ }
void Destroy();
/**
* Set the animation to display the given frame.
* @param aParentSurface The owning surface of aSurface. This may be the same
@ -235,6 +239,14 @@ public:
* image keys are already invalid.
*/
void Invalidate(WebRenderLayerManager* aManager);
private:
~SharedSurfacesAnimation();
typedef SharedSurfacesChild::ImageKeyData ImageKeyData;
AutoTArray<ImageKeyData, 1> mKeys;
wr::ExternalImageId mId;
};
} // namespace layers