mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1428558
- Part 5. Add SharedSurfacesAnimation to manage single ImageKey for animated images. r=nical
Differential Revision: https://phabricator.services.mozilla.com/D7502
This commit is contained in:
parent
ed51ad4899
commit
6a77ac0bd5
@ -59,33 +59,36 @@ SharedSurfacesChild::ImageKeyData::MergeDirtyRect(const Maybe<IntRect>& aDirtyRe
|
||||
|
||||
SharedSurfacesChild::SharedUserData::~SharedUserData()
|
||||
{
|
||||
if (mShared) {
|
||||
mShared = false;
|
||||
if (mShared || !mKeys.IsEmpty()) {
|
||||
if (NS_IsMainThread()) {
|
||||
SharedSurfacesChild::Unshare(mId, mKeys);
|
||||
SharedSurfacesChild::Unshare(mId, mShared, mKeys);
|
||||
} else {
|
||||
class DestroyRunnable final : public Runnable
|
||||
{
|
||||
public:
|
||||
DestroyRunnable(const wr::ExternalImageId& aId,
|
||||
bool aReleaseId,
|
||||
nsTArray<ImageKeyData>&& aKeys)
|
||||
: Runnable("SharedSurfacesChild::SharedUserData::DestroyRunnable")
|
||||
, mId(aId)
|
||||
, mReleaseId(aReleaseId)
|
||||
, mKeys(std::move(aKeys))
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
SharedSurfacesChild::Unshare(mId, mKeys);
|
||||
SharedSurfacesChild::Unshare(mId, mReleaseId, mKeys);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
wr::ExternalImageId mId;
|
||||
bool mReleaseId;
|
||||
AutoTArray<ImageKeyData, 1> mKeys;
|
||||
};
|
||||
|
||||
nsCOMPtr<nsIRunnable> task = new DestroyRunnable(mId, std::move(mKeys));
|
||||
nsCOMPtr<nsIRunnable> task =
|
||||
new DestroyRunnable(mId, mShared, std::move(mKeys));
|
||||
SystemGroup::Dispatch(TaskCategory::Other, task.forget());
|
||||
}
|
||||
}
|
||||
@ -129,6 +132,7 @@ SharedSurfacesChild::SharedUserData::UpdateKey(WebRenderLayerManager* aManager,
|
||||
entry.MergeDirtyRect(aDirtyRect);
|
||||
Maybe<IntRect> dirtyRect = entry.TakeDirtyRect();
|
||||
if (dirtyRect) {
|
||||
MOZ_ASSERT(mShared);
|
||||
aResources.UpdateExternalImage(mId, entry.mImageKey,
|
||||
ViewAs<ImagePixel>(dirtyRect.ref()));
|
||||
}
|
||||
@ -370,6 +374,7 @@ SharedSurfacesChild::Share(SourceSurface* aSurface,
|
||||
|
||||
/* static */ void
|
||||
SharedSurfacesChild::Unshare(const wr::ExternalImageId& aId,
|
||||
bool aReleaseId,
|
||||
nsTArray<ImageKeyData>& aKeys)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@ -380,6 +385,11 @@ SharedSurfacesChild::Unshare(const wr::ExternalImageId& aId,
|
||||
}
|
||||
}
|
||||
|
||||
if (!aReleaseId) {
|
||||
// We don't own the external image ID itself.
|
||||
return;
|
||||
}
|
||||
|
||||
CompositorManagerChild* manager = CompositorManagerChild::GetInstance();
|
||||
if (MOZ_UNLIKELY(!manager || !manager->CanSend())) {
|
||||
return;
|
||||
@ -418,5 +428,66 @@ SharedSurfacesChild::GetExternalId(const SourceSurfaceSharedData* aSurface)
|
||||
return Some(data->Id());
|
||||
}
|
||||
|
||||
nsresult
|
||||
SharedSurfacesAnimation::SetCurrentFrame(SourceSurfaceSharedData* aSurface,
|
||||
const gfx::IntRect& aDirtyRect)
|
||||
{
|
||||
MOZ_ASSERT(aSurface);
|
||||
|
||||
SharedUserData* data = nullptr;
|
||||
nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data);
|
||||
mId = data->Id();
|
||||
|
||||
auto i = mKeys.Length();
|
||||
while (i > 0) {
|
||||
--i;
|
||||
SharedSurfacesChild::ImageKeyData& entry = mKeys[i];
|
||||
if (entry.mManager->IsDestroyed()) {
|
||||
mKeys.RemoveElementAt(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
entry.MergeDirtyRect(Some(aDirtyRect));
|
||||
|
||||
Maybe<IntRect> dirtyRect = entry.TakeDirtyRect();
|
||||
if (dirtyRect) {
|
||||
auto& resourceUpdates = entry.mManager->AsyncResourceUpdates();
|
||||
resourceUpdates.UpdateExternalImage(mId, entry.mImageKey,
|
||||
ViewAs<ImagePixel>(dirtyRect.ref()));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SharedSurfacesAnimation::UpdateKey(SourceSurfaceSharedData* aSurface,
|
||||
WebRenderLayerManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::ImageKey& aKey)
|
||||
{
|
||||
SharedUserData* data = nullptr;
|
||||
nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data);
|
||||
if (mId.mHandle != data->Id().mHandle) {
|
||||
mKeys.Clear();
|
||||
mId = data->Id();
|
||||
}
|
||||
|
||||
aKey = SharedSurfacesChild::SharedUserData::UpdateKey(aManager,
|
||||
aResources,
|
||||
Nothing());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -84,6 +84,8 @@ private:
|
||||
SharedSurfacesChild() = delete;
|
||||
~SharedSurfacesChild() = delete;
|
||||
|
||||
friend class SharedSurfacesAnimation;
|
||||
|
||||
class ImageKeyData final {
|
||||
public:
|
||||
ImageKeyData(WebRenderLayerManager* aManager,
|
||||
@ -107,8 +109,12 @@ private:
|
||||
wr::ImageKey mImageKey;
|
||||
};
|
||||
|
||||
class SharedUserData final {
|
||||
class SharedUserData {
|
||||
public:
|
||||
SharedUserData()
|
||||
: mShared(false)
|
||||
{ }
|
||||
|
||||
explicit SharedUserData(const wr::ExternalImageId& aId)
|
||||
: mId(aId)
|
||||
, mShared(false)
|
||||
@ -116,6 +122,12 @@ private:
|
||||
|
||||
~SharedUserData();
|
||||
|
||||
SharedUserData(const SharedUserData& aOther) = delete;
|
||||
SharedUserData& operator=(const SharedUserData& aOther) = delete;
|
||||
|
||||
SharedUserData(SharedUserData&& aOther) = delete;
|
||||
SharedUserData& operator=(SharedUserData&& aOther) = delete;
|
||||
|
||||
const wr::ExternalImageId& Id() const
|
||||
{
|
||||
return mId;
|
||||
@ -143,7 +155,7 @@ private:
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
const Maybe<gfx::IntRect>& aDirtyRect);
|
||||
|
||||
private:
|
||||
protected:
|
||||
AutoTArray<ImageKeyData, 1> mKeys;
|
||||
wr::ExternalImageId mId;
|
||||
bool mShared : 1;
|
||||
@ -152,12 +164,47 @@ private:
|
||||
static nsresult ShareInternal(gfx::SourceSurfaceSharedData* aSurface,
|
||||
SharedUserData** aUserData);
|
||||
|
||||
static void Unshare(const wr::ExternalImageId& aId, nsTArray<ImageKeyData>& aKeys);
|
||||
static void Unshare(const wr::ExternalImageId& aId,
|
||||
bool aReleaseId,
|
||||
nsTArray<ImageKeyData>& aKeys);
|
||||
|
||||
static void DestroySharedUserData(void* aClosure);
|
||||
|
||||
static gfx::UserDataKey sSharedKey;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
public:
|
||||
SharedSurfacesAnimation()
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Set the animation to display the given frame.
|
||||
* @param aSurface The current frame.
|
||||
* @param aDirtyRect Dirty rect representing the change between the new frame
|
||||
* and the previous frame. We will request only the delta
|
||||
* be reuploaded by WebRender.
|
||||
*/
|
||||
nsresult SetCurrentFrame(gfx::SourceSurfaceSharedData* aSurface,
|
||||
const gfx::IntRect& aDirtyRect);
|
||||
|
||||
/**
|
||||
* Generate an ImageKey for the given frame.
|
||||
* @param aSurface The current frame. This should match what was cached via
|
||||
* SetCurrentFrame, but if it does not, it will need to
|
||||
* regenerate the cached ImageKey.
|
||||
*/
|
||||
nsresult UpdateKey(gfx::SourceSurfaceSharedData* aSurface,
|
||||
WebRenderLayerManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::ImageKey& aKey);
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user