Bug 1469964 - Part 2. Make shared surfaces use external image update mechanism. r=nical

This commit is contained in:
Andrew Osmond 2018-07-12 11:43:12 -04:00
parent 7fb17ddb91
commit a52fbf8ab5
4 changed files with 67 additions and 34 deletions

View file

@ -599,16 +599,16 @@ public:
}
/**
* Indicates how many times the surface has been invalidated.
* Yields a dirty rect of what has changed since it was last called.
*/
virtual int32_t Invalidations() const {
return -1;
virtual Maybe<IntRect> TakeDirtyRect() {
return Nothing();
}
/**
* Increment the invalidation counter.
* Indicate a region which has changed in the surface.
*/
virtual void Invalidate() { }
virtual void Invalidate(const IntRect& aDirtyRect) { }
protected:
bool mIsMapped;

View file

@ -119,7 +119,6 @@ public:
, mStride(0)
, mMapCount(0)
, mHandleCount(0)
, mInvalidations(0)
, mFormat(SurfaceFormat::UNKNOWN)
, mClosed(false)
, mFinalized(false)
@ -249,22 +248,34 @@ public:
}
/**
* Indicates how many times the surface has been invalidated.
* Yields a dirty rect of what has changed since it was last called.
*/
int32_t Invalidations() const override
Maybe<IntRect> TakeDirtyRect() override
{
MutexAutoLock lock(mMutex);
return mInvalidations;
if (mDirtyRect) {
Maybe<IntRect> ret = std::move(mDirtyRect);
return ret;
}
return Nothing();
}
/**
* Increment the invalidation counter.
*/
void Invalidate() override
void Invalidate(const IntRect& aDirtyRect) override
{
MutexAutoLock lock(mMutex);
++mInvalidations;
MOZ_ASSERT(mInvalidations >= 0);
if (!aDirtyRect.IsEmpty()) {
if (mDirtyRect) {
mDirtyRect->UnionRect(mDirtyRect.ref(), aDirtyRect);
} else {
mDirtyRect = Some(aDirtyRect);
}
} else {
mDirtyRect = Some(IntRect(IntPoint(0, 0), mSize));
}
MOZ_ASSERT_IF(mDirtyRect, !mDirtyRect->IsEmpty());
}
/**
@ -333,7 +344,7 @@ private:
int32_t mStride;
int32_t mMapCount;
int32_t mHandleCount;
int32_t mInvalidations;
Maybe<IntRect> mDirtyRect;
IntSize mSize;
RefPtr<SharedMemoryBasic> mBuf;
RefPtr<SharedMemoryBasic> mOldBuf;

View file

@ -23,24 +23,20 @@ class SharedSurfacesChild::ImageKeyData final
{
public:
ImageKeyData(WebRenderLayerManager* aManager,
const wr::ImageKey& aImageKey,
int32_t aInvalidations)
const wr::ImageKey& aImageKey)
: mManager(aManager)
, mImageKey(aImageKey)
, mInvalidations(aInvalidations)
{ }
ImageKeyData(ImageKeyData&& aOther)
: mManager(std::move(aOther.mManager))
, mImageKey(aOther.mImageKey)
, mInvalidations(aOther.mInvalidations)
{ }
ImageKeyData& operator=(ImageKeyData&& aOther)
{
mManager = std::move(aOther.mManager);
mImageKey = aOther.mImageKey;
mInvalidations = aOther.mInvalidations;
return *this;
}
@ -49,7 +45,6 @@ public:
RefPtr<WebRenderLayerManager> mManager;
wr::ImageKey mImageKey;
int32_t mInvalidations;
};
class SharedSurfacesChild::SharedUserData final
@ -119,7 +114,7 @@ public:
wr::ImageKey UpdateKey(WebRenderLayerManager* aManager,
wr::IpcResourceUpdateQueue& aResources,
int32_t aInvalidations)
const Maybe<IntRect>& aDirtyRect)
{
MOZ_ASSERT(aManager);
MOZ_ASSERT(!aManager->IsDestroyed());
@ -146,13 +141,12 @@ public:
// 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.mInvalidations != aInvalidations) {
if (ownsKey) {
aManager->AddImageKeyForDiscard(entry.mImageKey);
}
entry.mInvalidations = aInvalidations;
if (!ownsKey) {
entry.mImageKey = wrBridge->GetNextImageKey();
aResources.AddExternalImage(mId, entry.mImageKey);
} else if (aDirtyRect) {
aResources.UpdateExternalImage(mId, entry.mImageKey,
ViewAs<ImagePixel>(aDirtyRect.ref()));
}
key = entry.mImageKey;
@ -162,7 +156,7 @@ public:
if (!found) {
key = aManager->WrBridge()->GetNextImageKey();
ImageKeyData data(aManager, key, aInvalidations);
ImageKeyData data(aManager, key);
mKeys.AppendElement(std::move(data));
aResources.AddExternalImage(mId, key);
}
@ -323,12 +317,12 @@ SharedSurfacesChild::Share(SourceSurfaceSharedData* aSurface,
// surfaces promise to increment the invalidation counter each time the
// surface has changed. We can use this counter to determine whether or not
// we should upate our paired ImageKey.
int32_t invalidations = aSurface->Invalidations();
Maybe<IntRect> dirtyRect = aSurface->TakeDirtyRect();
SharedUserData* data = nullptr;
nsresult rv = SharedSurfacesChild::ShareInternal(aSurface, &data);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(data);
aKey = data->UpdateKey(aManager, aResources, invalidations);
aKey = data->UpdateKey(aManager, aResources, dirtyRect);
}
return rv;

View file

@ -619,19 +619,27 @@ imgFrame::ImageUpdatedInternal(const nsIntRect& aUpdateRect)
{
mMonitor.AssertCurrentThreadOwns();
mDecoded.UnionRect(mDecoded, aUpdateRect);
// Clamp to the frame rect to ensure that decoder bugs don't result in a
// decoded rect that extends outside the bounds of the frame rect.
mDecoded.IntersectRect(mDecoded, mFrameRect);
IntRect updateRect = mFrameRect.Intersect(aUpdateRect);
if (updateRect.IsEmpty()) {
return NS_OK;
}
mDecoded.UnionRect(mDecoded, updateRect);
// Paletted images cannot invalidate.
if (mPalettedImageData) {
return NS_OK;
}
// Update our invalidation counters for any consumers watching for changes
// in the surface.
if (mRawSurface) {
mRawSurface->Invalidate();
mRawSurface->Invalidate(updateRect);
}
if (mLockedSurface && mRawSurface != mLockedSurface) {
mLockedSurface->Invalidate();
mLockedSurface->Invalidate(updateRect);
}
return NS_OK;
}
@ -643,7 +651,27 @@ imgFrame::Finish(Opacity aFrameOpacity /* = Opacity::SOME_TRANSPARENCY */,
MonitorAutoLock lock(mMonitor);
MOZ_ASSERT(mLockCount > 0, "Image data should be locked");
ImageUpdatedInternal(GetRect());
if (mPalettedImageData) {
ImageUpdatedInternal(mFrameRect);
} else if (!mDecoded.IsEqualEdges(mFrameRect)) {
// The decoder should have produced rows starting from either the bottom or
// the top of the image. We need to calculate the region for which we have
// not yet invalidated.
IntRect delta(0, 0, mFrameRect.width, 0);
if (mDecoded.y == 0) {
delta.y = mDecoded.height;
delta.height = mFrameRect.height - mDecoded.height;
} else if (mDecoded.y + mDecoded.height == mFrameRect.height) {
delta.height = mFrameRect.height - mDecoded.y;
} else {
MOZ_ASSERT_UNREACHABLE("Decoder only updated middle of image!");
delta = mFrameRect;
}
ImageUpdatedInternal(delta);
}
MOZ_ASSERT(mDecoded.IsEqualEdges(mFrameRect));
if (aFinalize) {
FinalizeSurfaceInternal();