diff --git a/gfx/layers/CompositorTypes.h b/gfx/layers/CompositorTypes.h index d4e6aa5ce630..0765c751c943 100644 --- a/gfx/layers/CompositorTypes.h +++ b/gfx/layers/CompositorTypes.h @@ -252,7 +252,12 @@ enum class OpenMode : uint8_t { OPEN_WRITE = 0x2, OPEN_READ_WRITE = OPEN_READ|OPEN_WRITE, OPEN_READ_ONLY = OPEN_READ, - OPEN_WRITE_ONLY = OPEN_WRITE + OPEN_WRITE_ONLY = OPEN_WRITE, + + // This is only used in conjunction with OMTP to indicate that the DrawTarget + // that is being borrowed will be painted asynchronously, and so will outlive + // the write lock. + OPEN_ASYNC_WRITE = 0x04 }; MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(OpenMode) diff --git a/gfx/layers/client/ClientPaintedLayer.cpp b/gfx/layers/client/ClientPaintedLayer.cpp index b4a1f5648819..24476f273f3c 100644 --- a/gfx/layers/client/ClientPaintedLayer.cpp +++ b/gfx/layers/client/ClientPaintedLayer.cpp @@ -185,7 +185,7 @@ ClientPaintedLayer::PaintThebes(nsTArray* aReadbackUp bool ClientPaintedLayer::PaintOffMainThread() { - mContentClient->BeginPaint(); + mContentClient->BeginAsyncPaint(); uint32_t flags = GetPaintFlags(); diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index 26323d5edd1f..2f1b7b138c10 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -91,9 +91,16 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder) return MakeAndAddRef(aForwarder); } +void +ContentClient::BeginAsyncPaint() +{ + mInAsyncPaint = true; +} + void ContentClient::EndPaint(nsTArray* aReadbackUpdates) { + mInAsyncPaint = false; } void @@ -238,6 +245,13 @@ ContentClientRemoteBuffer::BeginPaint() } } +void +ContentClientRemoteBuffer::BeginAsyncPaint() +{ + BeginPaint(); + mInAsyncPaint = true; +} + void ContentClientRemoteBuffer::EndPaint(nsTArray* aReadbackUpdates) { @@ -349,14 +363,19 @@ ContentClientRemoteBuffer::CreateBuffer(ContentType aType, return; } + OpenMode mode = OpenMode::OPEN_READ_WRITE; + if (mInAsyncPaint) { + mode |= OpenMode::OPEN_ASYNC_WRITE; + } + // We just created the textures and we are about to get their draw targets // so we have to lock them here. - DebugOnly locked = mTextureClient->Lock(OpenMode::OPEN_READ_WRITE); + DebugOnly locked = mTextureClient->Lock(mode); MOZ_ASSERT(locked, "Could not lock the TextureClient"); *aBlackDT = mTextureClient->BorrowDrawTarget(); if (aFlags & BUFFER_COMPONENT_ALPHA) { - locked = mTextureClientOnWhite->Lock(OpenMode::OPEN_READ_WRITE); + locked = mTextureClientOnWhite->Lock(mode); MOZ_ASSERT(locked, "Could not lock the second TextureClient for component alpha"); *aWhiteDT = mTextureClientOnWhite->BorrowDrawTarget(); @@ -430,14 +449,18 @@ ContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) bool ContentClientRemoteBuffer::LockBuffers() { + OpenMode mode = OpenMode::OPEN_READ_WRITE; + if (mInAsyncPaint) { + mode |= OpenMode::OPEN_ASYNC_WRITE; + } if (mTextureClient) { - bool locked = mTextureClient->Lock(OpenMode::OPEN_READ_WRITE); + bool locked = mTextureClient->Lock(mode); if (!locked) { return false; } } if (mTextureClientOnWhite) { - bool locked = mTextureClientOnWhite->Lock(OpenMode::OPEN_READ_WRITE); + bool locked = mTextureClientOnWhite->Lock(mode); if (!locked) { UnlockBuffers(); return false; @@ -553,6 +576,13 @@ ContentClientDoubleBuffered::BeginPaint() mBufferRotation = mFrontBufferRotation; } +void +ContentClientDoubleBuffered::BeginAsyncPaint() +{ + BeginPaint(); + mInAsyncPaint = true; +} + // Sync front/back buffers content // After executing, the new back buffer has the same (interesting) pixels as // the new front buffer, and mValidRegion et al. are correct wrt the new diff --git a/gfx/layers/client/ContentClient.h b/gfx/layers/client/ContentClient.h index 96ed41b4448f..9354467c0bd8 100644 --- a/gfx/layers/client/ContentClient.h +++ b/gfx/layers/client/ContentClient.h @@ -82,7 +82,8 @@ public: static already_AddRefed CreateContentClient(CompositableForwarder* aFwd); explicit ContentClient(CompositableForwarder* aForwarder) - : CompositableClient(aForwarder) + : CompositableClient(aForwarder), + mInAsyncPaint(false) {} virtual ~ContentClient() {} @@ -103,7 +104,11 @@ public: // call before and after painting into this content client virtual void BeginPaint() {} + virtual void BeginAsyncPaint(); virtual void EndPaint(nsTArray* aReadbackUpdates = nullptr); + +protected: + bool mInAsyncPaint; }; /** @@ -243,6 +248,7 @@ public: * are affected by mapping/unmapping. */ virtual void BeginPaint() override; + virtual void BeginAsyncPaint() override; virtual void EndPaint(nsTArray* aReadbackUpdates = nullptr) override; virtual void Updated(const nsIntRegion& aRegionToDraw, @@ -347,6 +353,7 @@ public: virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override; virtual void BeginPaint() override; + virtual void BeginAsyncPaint() override; virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) override; diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 615021446e26..fdfd43891c04 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -509,7 +509,7 @@ TextureClient::Lock(OpenMode aMode) auto format = GetFormat(); if (mIsLocked && CanExposeDrawTarget() && - aMode == OpenMode::OPEN_READ_WRITE && + (aMode & OpenMode::OPEN_READ_WRITE) == OpenMode::OPEN_READ_WRITE && NS_IsMainThread() && // the formats that we apparently expect, in the cairo backend. Any other // format will trigger an assertion in GfxFormatToCairoFormat. @@ -557,7 +557,8 @@ TextureClient::Unlock() mBorrowedDrawTarget->DetachAllSnapshots(); // If this assertion is hit, it means something is holding a strong reference // to our DrawTarget externally, which is not allowed. - MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs); + MOZ_ASSERT_IF(!(mOpenMode & OpenMode::OPEN_ASYNC_WRITE), + mBorrowedDrawTarget->refCount() <= mExpectedDtRefs); mBorrowedDrawTarget = nullptr; }