Use a RemoteRotatedBuffer for the front buffer of ContentClientDoubleBuffered. (
bug 1409871 part 5, r=nical)
The front buffer for a double buffered content client is really just another
rotated buffer, so it can simplify the code to use the class we just added.
The goal is to have the back and the front buffer using remote rotated buffers,
but this is a good first step.
Note: The front buffer is represented as a Maybe<RemoteRotatedBuffer> in this
commit, but in the future it will be a RefPtr. That can't be done yet, because
rotated buffer can't implement refcounting in addition to compositable client.
MozReview-Commit-ID: Czk3otkf1pb
--- a/gfx/layers/RotatedBuffer.cpp
+++ b/gfx/layers/RotatedBuffer.cpp
@@ -391,16 +391,24 @@ RemoteRotatedBuffer::Unlock()
if (mClient->IsLocked()) {
mClient->Unlock();
}
if (mClientOnWhite && mClientOnWhite->IsLocked()) {
mClientOnWhite->Unlock();
}
}
+void
+RemoteRotatedBuffer::Clear()
+{
+ MOZ_ASSERT(!mTarget && !mTargetOnWhite);
+ mClient = nullptr;
+ mClientOnWhite = nullptr;
+}
+
already_AddRefed<gfx::SourceSurface>
RemoteRotatedBuffer::GetSourceSurface(ContextSource aSource) const
{
if (aSource == ContextSource::BUFFER_BLACK) {
return mTarget->Snapshot();
} else {
MOZ_ASSERT(aSource == ContextSource::BUFFER_WHITE);
return mTargetOnWhite->Snapshot();
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -209,16 +209,21 @@ public:
: RotatedBuffer(aBufferRect, aBufferRotation)
, mClient(aClient)
, mClientOnWhite(aClientOnWhite)
{ }
bool Lock(OpenMode aMode);
void Unlock();
+ void Clear();
+
+ TextureClient* GetClient() const { return mClient; }
+ TextureClient* GetClientOnWhite() const { return mClientOnWhite; }
+
virtual bool HaveBuffer() const override { return !!mClient; }
virtual bool HaveBufferOnWhite() const override { return !!mClientOnWhite; }
virtual already_AddRefed<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const override;
protected:
virtual gfx::DrawTarget* GetDTBuffer() const override;
virtual gfx::DrawTarget* GetDTBufferOnWhite() const override;
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -527,89 +527,102 @@ void
ContentClientDoubleBuffered::Dump(std::stringstream& aStream,
const char* aPrefix,
bool aDumpHtml, TextureDumpMode aCompress)
{
// TODO We should combine the OnWhite/OnBlack here an just output a single image.
if (!aDumpHtml) {
aStream << "\n" << aPrefix << "Surface: ";
}
- CompositableClient::DumpTextureClient(aStream, mFrontClient, aCompress);
+ if (mFrontBuffer) {
+ CompositableClient::DumpTextureClient(aStream, mFrontBuffer->GetClient(), aCompress);
+ }
}
void
ContentClientDoubleBuffered::DestroyFrontBuffer()
{
- if (mFrontClient) {
- mOldTextures.AppendElement(mFrontClient);
- mFrontClient = nullptr;
- }
+ if (mFrontBuffer) {
+ RefPtr<TextureClient> client = mFrontBuffer->GetClient();
+ RefPtr<TextureClient> clientOnWhite = mFrontBuffer->GetClientOnWhite();
- if (mFrontClientOnWhite) {
- mOldTextures.AppendElement(mFrontClientOnWhite);
- mFrontClientOnWhite = nullptr;
+ if (client) {
+ mOldTextures.AppendElement(client);
+ }
+ if (clientOnWhite) {
+ mOldTextures.AppendElement(clientOnWhite);
+ }
+
+ mFrontBuffer = Nothing();
}
}
void
ContentClientDoubleBuffered::Updated(const nsIntRegion& aRegionToDraw,
const nsIntRegion& aVisibleRegion,
bool aDidSelfCopy)
{
ContentClientRemoteBuffer::Updated(aRegionToDraw, aVisibleRegion, aDidSelfCopy);
}
void
ContentClientDoubleBuffered::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
{
mFrontUpdatedRegion = aFrontUpdatedRegion;
- RefPtr<TextureClient> oldBack = mTextureClient;
- mTextureClient = mFrontClient;
- mFrontClient = oldBack;
-
- oldBack = mTextureClientOnWhite;
- mTextureClientOnWhite = mFrontClientOnWhite;
- mFrontClientOnWhite = oldBack;
+ RefPtr<TextureClient> newBack;
+ RefPtr<TextureClient> newBackOnWhite;
+ IntRect newBackBufferRect;
+ nsIntPoint newBackBufferRotation;
- IntRect oldBufferRect = mBufferRect;
- mBufferRect = mFrontBufferRect;
- mFrontBufferRect = oldBufferRect;
+ if (mFrontBuffer) {
+ newBack = mFrontBuffer->GetClient();
+ newBackOnWhite = mFrontBuffer->GetClientOnWhite();
+ newBackBufferRect = mFrontBuffer->BufferRect();
+ newBackBufferRotation = mFrontBuffer->BufferRotation();
+ }
- nsIntPoint oldBufferRotation = mBufferRotation;
- mBufferRotation = mFrontBufferRotation;
- mFrontBufferRotation = oldBufferRotation;
+ mFrontBuffer = Some(RemoteRotatedBuffer(mTextureClient, mTextureClientOnWhite,
+ mBufferRect, mBufferRotation));
- MOZ_ASSERT(mFrontClient);
+ mTextureClient = newBack;
+ mTextureClientOnWhite = newBackOnWhite;
+ mBufferRect = newBackBufferRect;
+ mBufferRotation = newBackBufferRotation;
ContentClientRemoteBuffer::SwapBuffers(aFrontUpdatedRegion);
}
void
ContentClientDoubleBuffered::BeginPaint()
{
ContentClientRemoteBuffer::BeginPaint();
mIsNewBuffer = false;
if (!mFrontAndBackBufferDiffer) {
return;
}
+ if (!mFrontBuffer) {
+ mFrontAndBackBufferDiffer = false;
+ return;
+ }
+
if (mDidSelfCopy) {
// We can't easily draw our front buffer into us, since we're going to be
// copying stuff around anyway it's easiest if we just move our situation
// to non-rotated while we're at it. If this situation occurs we'll have
// hit a self-copy path in PaintThebes before as well anyway.
- mBufferRect.MoveTo(mFrontBufferRect.TopLeft());
+ mBufferRect.MoveTo(mFrontBuffer->BufferRect().TopLeft());
mBufferRotation = nsIntPoint();
return;
}
- mBufferRect = mFrontBufferRect;
- mBufferRotation = mFrontBufferRotation;
+ mBufferRect = mFrontBuffer->BufferRect();
+ mBufferRotation = mFrontBuffer->BufferRotation();
}
void
ContentClientDoubleBuffered::BeginAsyncPaint()
{
BeginPaint();
mInAsyncPaint = true;
}
@@ -620,18 +633,18 @@ ContentClientDoubleBuffered::BeginAsyncP
// back buffer (i.e. as they were for the old back buffer)
void
ContentClientDoubleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw)
{
if (!mFrontAndBackBufferDiffer) {
MOZ_ASSERT(!mDidSelfCopy, "If we have to copy the world, then our buffers are different, right?");
return;
}
- MOZ_ASSERT(mFrontClient);
- if (!mFrontClient) {
+ MOZ_ASSERT(mFrontBuffer);
+ if (!mFrontBuffer) {
return;
}
MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
this,
mFrontUpdatedRegion.GetBounds().x,
mFrontUpdatedRegion.GetBounds().y,
mFrontUpdatedRegion.GetBounds().Width(),
@@ -652,55 +665,27 @@ ContentClientDoubleBuffered::FinalizeFra
return;
}
if (!EnsureBuffer() ||
(HaveBufferOnWhite() && !EnsureBufferOnWhite())) {
return;
}
- // We need to ensure that we lock these two buffers in the same
- // order as the compositor to prevent deadlocks.
- TextureClientAutoLock frontLock(mFrontClient, OpenMode::OPEN_READ_ONLY);
- if (!frontLock.Succeeded()) {
- return;
- }
- Maybe<TextureClientAutoLock> frontOnWhiteLock;
- if (mFrontClientOnWhite) {
- frontOnWhiteLock.emplace(mFrontClientOnWhite, OpenMode::OPEN_READ_ONLY);
- if (!frontOnWhiteLock->Succeeded()) {
- return;
- }
- }
-
- // Restrict the DrawTargets and frontBuffer to a scope to make
- // sure there is no more external references to the DrawTargets
- // when we Unlock the TextureClients.
- gfx::DrawTarget* dt = mFrontClient->BorrowDrawTarget();
- gfx::DrawTarget* dtw = mFrontClientOnWhite ? mFrontClientOnWhite->BorrowDrawTarget() : nullptr;
- if (dt && dt->IsValid()) {
- RefPtr<SourceSurface> surf = dt->Snapshot();
- RefPtr<SourceSurface> surfOnWhite = dtw ? dtw->Snapshot() : nullptr;
- SourceRotatedBuffer frontBuffer(surf,
- surfOnWhite,
- mFrontBufferRect,
- mFrontBufferRotation);
- UpdateDestinationFrom(frontBuffer, updateRegion);
- } else {
- // We know this can happen, but we want to track it somewhat, in case it leads
- // to other problems.
- gfxCriticalNote << "Invalid draw target(s) " << hexa(dt) << " and " << hexa(dtw);
+ if (mFrontBuffer->Lock(OpenMode::OPEN_READ_ONLY)) {
+ UpdateDestinationFrom(*mFrontBuffer, updateRegion);
+ mFrontBuffer->Unlock();
}
}
void
ContentClientDoubleBuffered::EnsureBackBufferIfFrontBuffer()
{
- if (!mTextureClient && mFrontClient) {
- CreateBackBuffer(mFrontBufferRect);
+ if (!mTextureClient && mFrontBuffer) {
+ CreateBackBuffer(mFrontBuffer->BufferRect());
- mBufferRect = mFrontBufferRect;
- mBufferRotation = mFrontBufferRotation;
+ mBufferRect = mFrontBuffer->BufferRect();
+ mBufferRotation = mFrontBuffer->BufferRotation();
}
}
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -16,16 +16,17 @@
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/layers/CompositableClient.h" // for CompositableClient
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/LayersTypes.h" // for TextureDumpMode
#include "mozilla/layers/TextureClient.h" // for TextureClient
+#include "mozilla/Maybe.h" // for Maybe
#include "mozilla/mozalloc.h" // for operator delete
#include "ReadbackProcessor.h" // For ReadbackProcessor::Update
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsPoint.h" // for nsIntPoint
#include "nsRect.h" // for mozilla::gfx::IntRect
#include "nsRegion.h" // for nsIntRegion
#include "nsTArray.h" // for nsTArray
@@ -324,18 +325,17 @@ public:
: ContentClientRemoteBuffer(aFwd)
{}
virtual ~ContentClientDoubleBuffered() {}
virtual void Clear() override
{
ContentClientRemoteBuffer::Clear();
- mFrontClient = nullptr;
- mFrontClientOnWhite = nullptr;
+ mFrontBuffer = Nothing();
}
virtual void Updated(const nsIntRegion& aRegionToDraw,
const nsIntRegion& aVisibleRegion,
bool aDidSelfCopy) override;
virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override;
@@ -359,25 +359,21 @@ protected:
virtual void DestroyFrontBuffer() override;
private:
virtual void AbortTextureClientCreation() override
{
mTextureClient = nullptr;
mTextureClientOnWhite = nullptr;
- mFrontClient = nullptr;
- mFrontClientOnWhite = nullptr;
+ mFrontBuffer = Nothing();
}
- RefPtr<TextureClient> mFrontClient;
- RefPtr<TextureClient> mFrontClientOnWhite;
+ Maybe<RemoteRotatedBuffer> mFrontBuffer;
nsIntRegion mFrontUpdatedRegion;
- gfx::IntRect mFrontBufferRect;
- nsIntPoint mFrontBufferRotation;
};
/**
* A single buffered ContentClient. We have a single TextureClient/Host
* which we update and then send a message to the compositor that we are
* done updating. It is not safe for the compositor to use the corresponding
* TextureHost's memory directly, it must upload it to video memory of some
* kind. We are free to modify the TextureClient once we receive reply from