forked from mirrors/gecko-dev
Bug 1469964 - Part 2. Make shared surfaces use external image update mechanism. r=nical
This commit is contained in:
parent
7fb17ddb91
commit
a52fbf8ab5
4 changed files with 67 additions and 34 deletions
10
gfx/2d/2D.h
10
gfx/2d/2D.h
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in a new issue