☠☠ backed out by 28647c01f828 ☠ ☠ | |
author | Ryan Hunt <rhunt@eqrion.net> |
Wed, 25 Oct 2017 10:20:49 -0400 | |
changeset 443205 | cb6507b560aaad188fc83a47b664aaa5692a0acd |
parent 443204 | 3d0da65640964e5a0565b5e7b7646cf719ce1449 |
child 443206 | e9349ad2f1f8fec862b1d2271d0d8f25ad0814d4 |
push id | 1618 |
push user | Callek@gmail.com |
push date | Thu, 11 Jan 2018 17:45:48 +0000 |
treeherder | mozilla-release@882ca853e05a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bas |
bugs | 1399692 |
milestone | 58.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/PaintThread.cpp +++ b/gfx/layers/PaintThread.cpp @@ -16,16 +16,40 @@ #include "mozilla/Preferences.h" #include "mozilla/SyncRunnable.h" namespace mozilla { namespace layers { using namespace gfx; +bool +CapturedBufferState::Copy::CopyBuffer() +{ + if (mSource->Lock(OpenMode::OPEN_READ_ONLY)) { + mDestination->UpdateDestinationFrom(*mSource, mBounds); + mSource->Unlock(); + return true; + } + return false; +} + +bool +CapturedBufferState::Unrotate::UnrotateBuffer() +{ + return mBuffer->UnrotateBufferTo(mParameters); +} + +bool +CapturedBufferState::PrepareBuffer() +{ + return (!mBufferCopy || mBufferCopy->CopyBuffer()) && + (!mBufferUnrotate || mBufferUnrotate->UnrotateBuffer()); +} + StaticAutoPtr<PaintThread> PaintThread::sSingleton; StaticRefPtr<nsIThread> PaintThread::sThread; PlatformThreadId PaintThread::sThreadId; // RAII make sure we clean up and restore our draw targets // when we paint async. struct MOZ_STACK_CLASS AutoCapturedPaintSetup {
--- a/gfx/layers/PaintThread.h +++ b/gfx/layers/PaintThread.h @@ -7,16 +7,17 @@ #ifndef MOZILLA_LAYERS_PAINTTHREAD_H #define MOZILLA_LAYERS_PAINTTHREAD_H #include "base/platform_thread.h" #include "mozilla/RefPtr.h" #include "mozilla/StaticPtr.h" #include "mozilla/UniquePtr.h" #include "mozilla/layers/TextureClient.h" +#include "RotatedBuffer.h" #include "nsThreadUtils.h" namespace mozilla { namespace gfx { class DrawTarget; class DrawTargetCapture; }; @@ -53,16 +54,65 @@ public: gfx::Matrix mTargetTransform; SurfaceMode mSurfaceMode; gfxContentType mContentType; protected: virtual ~CapturedPaintState() {} }; +// Holds the key operations for a ContentClient to prepare +// its buffers for painting +class CapturedBufferState final { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CapturedBufferState) +public: + struct Copy { + Copy(RefPtr<RotatedBuffer> aSource, + RefPtr<RotatedBuffer> aDestination, + gfx::IntRect aBounds) + : mSource(aSource) + , mDestination(aDestination) + , mBounds(aBounds) + {} + + bool CopyBuffer(); + + RefPtr<RotatedBuffer> mSource; + RefPtr<RotatedBuffer> mDestination; + gfx::IntRect mBounds; + }; + + struct Unrotate { + Unrotate(RotatedBuffer::Parameters aParameters, + RefPtr<RotatedBuffer> aBuffer) + : mParameters(aParameters) + , mBuffer(aBuffer) + {} + + bool UnrotateBuffer(); + + RotatedBuffer::Parameters mParameters; + RefPtr<RotatedBuffer> mBuffer; + }; + + /** + * Prepares the rotated buffers for painting by copying a previous frame + * into the buffer and/or unrotating the pixels and returns whether the + * operations were successful. If this fails a new buffer should be created + * for the frame. + */ + bool PrepareBuffer(); + + Maybe<Copy> mBufferCopy; + Maybe<Unrotate> mBufferUnrotate; + +protected: + ~CapturedBufferState() {} +}; + typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState* aPaintState); class CompositorBridgeChild; class PaintThread final { friend void DestroyPaintThread(UniquePtr<PaintThread>&& aPaintThread);
--- a/gfx/layers/RotatedBuffer.cpp +++ b/gfx/layers/RotatedBuffer.cpp @@ -286,112 +286,118 @@ WrapRotationAxis(int32_t* aRotationPoint if (*aRotationPoint < 0) { *aRotationPoint += aSize; } else if (*aRotationPoint >= aSize) { *aRotationPoint -= aSize; } } bool -RotatedBuffer::AdjustTo(const gfx::IntRect& aDestBufferRect, - const gfx::IntRect& aDrawBounds, - bool aCanHaveRotation, - bool aCanDrawRotated) +RotatedBuffer::Parameters::IsRotated() const +{ + return mBufferRotation != IntPoint(0,0); +} + +bool +RotatedBuffer::Parameters::RectWrapsBuffer(const gfx::IntRect& aRect) const +{ + int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x; + int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y; + return (aRect.x < xBoundary && xBoundary < aRect.XMost()) || + (aRect.y < yBoundary && yBoundary < aRect.YMost()); +} + +void +RotatedBuffer::Parameters::SetUnrotated() +{ + mBufferRotation = IntPoint(0,0); + mDidSelfCopy = true; +} + +RotatedBuffer::Parameters +RotatedBuffer::AdjustedParameters(const gfx::IntRect& aDestBufferRect) const { IntRect keepArea; if (keepArea.IntersectRect(aDestBufferRect, mBufferRect)) { // Set mBufferRotation so that the pixels currently in mDTBuffer // will still be rendered in the right place when mBufferRect // changes to aDestBufferRect. IntPoint newRotation = mBufferRotation + (aDestBufferRect.TopLeft() - mBufferRect.TopLeft()); WrapRotationAxis(&newRotation.x, mBufferRect.Width()); WrapRotationAxis(&newRotation.y, mBufferRect.Height()); NS_ASSERTION(gfx::IntRect(gfx::IntPoint(0,0), mBufferRect.Size()).Contains(newRotation), "newRotation out of bounds"); - int32_t xBoundary = aDestBufferRect.XMost() - newRotation.x; - int32_t yBoundary = aDestBufferRect.YMost() - newRotation.y; - bool drawWrapsBuffer = (aDrawBounds.x < xBoundary && xBoundary < aDrawBounds.XMost()) || - (aDrawBounds.y < yBoundary && yBoundary < aDrawBounds.YMost()); + return Parameters{aDestBufferRect, newRotation}; + } + + // No pixels are going to be kept. The whole visible region + // will be redrawn, so we don't need to copy anything, so we don't + // set destBuffer. + return Parameters{aDestBufferRect, IntPoint(0,0)}; +} - if ((drawWrapsBuffer && !aCanDrawRotated) || - (newRotation != IntPoint(0,0) && !aCanHaveRotation)) { - // The stuff we need to redraw will wrap around an edge of the - // buffer (and the caller doesn't know how to support that), so - // move the pixels we can keep into a position that lets us - // redraw in just one quadrant. - RefPtr<gfx::DrawTarget> dtBuffer = GetDTBuffer(); - RefPtr<gfx::DrawTarget> dtBufferOnWhite = GetDTBufferOnWhite(); +bool +RotatedBuffer::UnrotateBufferTo(const Parameters& aParameters) +{ + RefPtr<gfx::DrawTarget> dtBuffer = GetDTBuffer(); + RefPtr<gfx::DrawTarget> dtBufferOnWhite = GetDTBufferOnWhite(); - if (mBufferRotation == IntPoint(0,0)) { - IntRect srcRect(IntPoint(0, 0), mBufferRect.Size()); - IntPoint dest = mBufferRect.TopLeft() - aDestBufferRect.TopLeft(); - - MOZ_ASSERT(dtBuffer && dtBuffer->IsValid()); - dtBuffer->CopyRect(srcRect, dest); - if (HaveBufferOnWhite()) { - MOZ_ASSERT(dtBufferOnWhite && dtBufferOnWhite->IsValid()); - dtBufferOnWhite->CopyRect(srcRect, dest); - } + if (mBufferRotation == IntPoint(0,0)) { + IntRect srcRect(IntPoint(0, 0), mBufferRect.Size()); + IntPoint dest = mBufferRect.TopLeft() - aParameters.mBufferRect.TopLeft(); - mDidSelfCopy = true; - mBufferRect = aDestBufferRect; - } else { - // With azure and a data surface perform an buffer unrotate - // (SelfCopy). - unsigned char* data; - IntSize size; - int32_t stride; - SurfaceFormat format; - - if (dtBuffer->LockBits(&data, &size, &stride, &format)) { - uint8_t bytesPerPixel = BytesPerPixel(format); - BufferUnrotate(data, - size.width * bytesPerPixel, - size.height, stride, - newRotation.x * bytesPerPixel, newRotation.y); - dtBuffer->ReleaseBits(data); + MOZ_ASSERT(dtBuffer && dtBuffer->IsValid()); + dtBuffer->CopyRect(srcRect, dest); + if (HaveBufferOnWhite()) { + MOZ_ASSERT(dtBufferOnWhite && dtBufferOnWhite->IsValid()); + dtBufferOnWhite->CopyRect(srcRect, dest); + } + } else { + // With azure and a data surface perform an buffer unrotate + // (SelfCopy). + unsigned char* data; + IntSize size; + int32_t stride; + SurfaceFormat format; - if (HaveBufferOnWhite()) { - MOZ_ASSERT(dtBufferOnWhite && dtBufferOnWhite->IsValid()); - dtBufferOnWhite->LockBits(&data, &size, &stride, &format); - uint8_t bytesPerPixel = BytesPerPixel(format); - BufferUnrotate(data, - size.width * bytesPerPixel, - size.height, stride, - newRotation.x * bytesPerPixel, newRotation.y); - dtBufferOnWhite->ReleaseBits(data); - } + if (dtBuffer->LockBits(&data, &size, &stride, &format)) { + uint8_t bytesPerPixel = BytesPerPixel(format); + BufferUnrotate(data, + size.width * bytesPerPixel, + size.height, stride, + aParameters.mBufferRotation.x * bytesPerPixel, + aParameters.mBufferRotation.y); + dtBuffer->ReleaseBits(data); - // Buffer unrotate moves all the pixels - mDidSelfCopy = true; - mBufferRect = aDestBufferRect; - mBufferRotation = IntPoint(0, 0); - } - - if (!mDidSelfCopy) { - // We couldn't unrotate the buffer, so we need to create a - // new one and start from scratch - return false; - } + if (HaveBufferOnWhite()) { + MOZ_ASSERT(dtBufferOnWhite && dtBufferOnWhite->IsValid()); + dtBufferOnWhite->LockBits(&data, &size, &stride, &format); + uint8_t bytesPerPixel = BytesPerPixel(format); + BufferUnrotate(data, + size.width * bytesPerPixel, + size.height, stride, + aParameters.mBufferRotation.x * bytesPerPixel, + aParameters.mBufferRotation.y); + dtBufferOnWhite->ReleaseBits(data); } } else { - mBufferRect = aDestBufferRect; - mBufferRotation = newRotation; + return false; } - } else { - // No pixels are going to be kept. The whole visible region - // will be redrawn, so we don't need to copy anything, so we don't - // set destBuffer. - mBufferRect = aDestBufferRect; - mBufferRotation = IntPoint(0,0); } + return true; +} - return true; +void +RotatedBuffer::SetParameters(const RotatedBuffer::Parameters& aParameters) +{ + mBufferRect = aParameters.mBufferRect; + mBufferRotation = aParameters.mBufferRotation; + mDidSelfCopy = aParameters.mDidSelfCopy; } RotatedBuffer::ContentType RotatedBuffer::GetContentType() const { return ContentForFormat(GetFormat()); }
--- a/gfx/layers/RotatedBuffer.h +++ b/gfx/layers/RotatedBuffer.h @@ -19,21 +19,19 @@ #include "nsDebug.h" // for NS_RUNTIMEABORT #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc #include "nsRegion.h" // for nsIntRegion #include "LayersTypes.h" namespace mozilla { namespace layers { -class CapturedPaintState; - -typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState*); - class PaintedLayer; +class CapturedBufferState; +class ContentClient; // Mixin class for classes which need logic for loaning out a draw target. // See comments on BorrowDrawTargetForQuadrantUpdate. class BorrowDrawTarget { public: void ReturnDrawTarget(gfx::DrawTarget*& aReturned); @@ -153,25 +151,48 @@ public: */ gfx::DrawTarget* BorrowDrawTargetForQuadrantUpdate(const gfx::IntRect& aBounds, ContextSource aSource, DrawIterator* aIter, bool aSetTransform = true, gfx::Matrix* aOutTransform = nullptr); + struct Parameters { + Parameters(const gfx::IntRect& aBufferRect, + const gfx::IntPoint& aBufferRotation) + : mBufferRect(aBufferRect) + , mBufferRotation(aBufferRotation) + , mDidSelfCopy(false) + { + } + + bool IsRotated() const; + bool RectWrapsBuffer(const gfx::IntRect& aRect) const; + + void SetUnrotated(); + + gfx::IntRect mBufferRect; + gfx::IntPoint mBufferRotation; + bool mDidSelfCopy; + }; + /** - * Adjusts the buffer to be centered on the destination buffer rect, - * and ready to draw the specified bounds. Returns whether a new buffer - * needs to be created. + * Returns the new buffer parameters for rotating to a + * destination buffer rect. */ - bool AdjustTo(const gfx::IntRect& aDestBufferRect, - const gfx::IntRect& aDrawBounds, - bool aCanHaveRotation, - bool aCanDrawRotated); + Parameters AdjustedParameters(const gfx::IntRect& aDestBufferRect) const; + + /** + * Unrotates the pixels of the rotated buffer for the specified + * new buffer parameters. + */ + bool UnrotateBufferTo(const Parameters& aParameters); + + void SetParameters(const Parameters& aParameters); /** * |BufferRect()| is the rect of device pixels that this * RotatedBuffer covers. That is what DrawBufferWithRotation() * will paint when it's called. */ const gfx::IntRect& BufferRect() const { return mBufferRect; } const gfx::IntPoint& BufferRotation() const { return mBufferRotation; } @@ -218,16 +239,23 @@ public: virtual gfx::SurfaceFormat GetFormat() const = 0; virtual already_AddRefed<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const = 0; virtual gfx::DrawTarget* GetDTBuffer() const = 0; virtual gfx::DrawTarget* GetDTBufferOnWhite() const = 0; + /** + * Creates a shallow copy of the rotated buffer with the same underlying + * texture clients and draw targets. Rotated buffers are not thread safe, + * so a copy needs to be sent for off main thread painting. + */ + virtual RefPtr<RotatedBuffer> ShallowCopy() const = 0; + protected: virtual ~RotatedBuffer() {} enum XSide { LEFT, RIGHT }; enum YSide { TOP, BOTTOM @@ -295,23 +323,42 @@ public: virtual gfx::SurfaceFormat GetFormat() const override; virtual already_AddRefed<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const override; virtual gfx::DrawTarget* GetDTBuffer() const override; virtual gfx::DrawTarget* GetDTBufferOnWhite() const override; + virtual RefPtr<RotatedBuffer> ShallowCopy() const { + return new RemoteRotatedBuffer { + mClient, mClientOnWhite, + mTarget, mTargetOnWhite, + mBufferRect, mBufferRotation + }; + } + TextureClient* GetClient() const { return mClient; } TextureClient* GetClientOnWhite() const { return mClientOnWhite; } void SyncWithObject(SyncObjectClient* aSyncObject); void Clear(); private: + RemoteRotatedBuffer(TextureClient* aClient, TextureClient* aClientOnWhite, + gfx::DrawTarget* aTarget, gfx::DrawTarget* aTargetOnWhite, + const gfx::IntRect& aBufferRect, + const gfx::IntPoint& aBufferRotation) + : RotatedBuffer(aBufferRect, aBufferRotation) + , mClient(aClient) + , mClientOnWhite(aClientOnWhite) + , mTarget(aTarget) + , mTargetOnWhite(aTargetOnWhite) + { } + RefPtr<TextureClient> mClient; RefPtr<TextureClient> mClientOnWhite; RefPtr<gfx::DrawTarget> mTarget; RefPtr<gfx::DrawTarget> mTargetOnWhite; }; /** @@ -338,16 +385,23 @@ public: virtual gfx::SurfaceFormat GetFormat() const override; virtual already_AddRefed<gfx::SourceSurface> GetSourceSurface(ContextSource aSource) const override; virtual gfx::DrawTarget* GetDTBuffer() const override; virtual gfx::DrawTarget* GetDTBufferOnWhite() const override; + virtual RefPtr<RotatedBuffer> ShallowCopy() const { + return new DrawTargetRotatedBuffer { + mTarget, mTargetOnWhite, + mBufferRect, mBufferRotation + }; + } + private: RefPtr<gfx::DrawTarget> mTarget; RefPtr<gfx::DrawTarget> mTargetOnWhite; }; /** * SourceRotatedBuffer is a rotated buffer that is backed by source surfaces, * and may only be used to draw into other buffers or be read directly. @@ -372,16 +426,20 @@ public: virtual gfx::SurfaceFormat GetFormat() const override; virtual bool HaveBuffer() const override { return !!mSource; } virtual bool HaveBufferOnWhite() const override { return !!mSourceOnWhite; } virtual gfx::DrawTarget* GetDTBuffer() const override { return nullptr; } virtual gfx::DrawTarget* GetDTBufferOnWhite() const override { return nullptr; } + virtual RefPtr<RotatedBuffer> ShallowCopy() const { + return nullptr; + } + private: RefPtr<gfx::SourceSurface> mSource; RefPtr<gfx::SourceSurface> mSourceOnWhite; }; } // namespace layers } // namespace mozilla
--- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -18,16 +18,17 @@ #include "mozilla/gfx/BasePoint.h" // for BasePoint #include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/Rect.h" // for Rect #include "mozilla/gfx/Types.h" #include "mozilla/layers/CompositorBridgeChild.h" // for CompositorBridgeChild #include "mozilla/layers/LayerManagerComposite.h" #include "mozilla/layers/LayersMessages.h" // for ThebesBufferData #include "mozilla/layers/LayersTypes.h" +#include "mozilla/layers/PaintThread.h" #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc #include "nsISupportsImpl.h" // for gfxContext::Release, etc #include "nsIWidget.h" // for nsIWidget #include "nsLayoutUtils.h" #ifdef XP_WIN #include "gfxWindowsPlatform.h" #endif #ifdef MOZ_WIDGET_GTK @@ -141,44 +142,63 @@ ContentClient::BeginPaint(PaintedLayer* } result.mRegionToDraw.Sub(dest.mNeededRegion, dest.mValidRegion); if (result.mRegionToDraw.IsEmpty()) return result; - OpenMode lockMode = aFlags & PAINT_ASYNC ? OpenMode::OPEN_READ_ASYNC_WRITE - : OpenMode::OPEN_READ_WRITE; - // We need to disable rotation if we're going to be resampled when // drawing, because we might sample across the rotation boundary. // Also disable buffer rotation when using webrender. bool canHaveRotation = gfxPlatform::BufferRotationEnabled() && !(aFlags & (PAINT_WILL_RESAMPLE | PAINT_NO_ROTATION)) && !(aLayer->Manager()->AsWebRenderLayerManager()); bool canDrawRotated = aFlags & PAINT_CAN_DRAW_ROTATED; + bool asyncPaint = (aFlags & PAINT_ASYNC); + IntRect drawBounds = result.mRegionToDraw.GetBounds(); + OpenMode lockMode = asyncPaint ? OpenMode::OPEN_READ_ASYNC_WRITE + : OpenMode::OPEN_READ_WRITE; if (dest.mCanReuseBuffer) { MOZ_ASSERT(mBuffer); + bool canReuseBuffer = false; + if (mBuffer->Lock(lockMode)) { + RefPtr<CapturedBufferState> bufferState = new CapturedBufferState(); + // Do not modify result.mRegionToDraw or result.mContentType after this call. - FinalizeFrame(result.mRegionToDraw); + FinalizeFrame(result.mRegionToDraw, bufferState); + + auto newParameters = mBuffer->AdjustedParameters(dest.mBufferRect); - if (!mBuffer->AdjustTo(dest.mBufferRect, - drawBounds, - canHaveRotation, - canDrawRotated)) { - dest.mBufferRect = ComputeBufferRect(dest.mNeededRegion.GetBounds()); - dest.mCanReuseBuffer = false; + if ((!canHaveRotation && newParameters.IsRotated()) || + (!canDrawRotated && newParameters.RectWrapsBuffer(drawBounds))) { + bufferState->mBufferUnrotate = Some(CapturedBufferState::Unrotate { + newParameters, + mBuffer->ShallowCopy(), + }); + } + + if (bufferState->PrepareBuffer()) { + if (bufferState->mBufferUnrotate) { + newParameters.SetUnrotated(); + } + mBuffer->SetParameters(newParameters); + canReuseBuffer = true; + } + } + + if (!canReuseBuffer) { + if (mBuffer->IsLocked()) { mBuffer->Unlock(); } - } else { dest.mBufferRect = ComputeBufferRect(dest.mNeededRegion.GetBounds()); dest.mCanReuseBuffer = false; } } NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || dest.mBufferRect == dest.mNeededRegion.GetBounds(), "If we're resampling, we need to validate the entire buffer"); @@ -208,20 +228,25 @@ ContentClient::BeginPaint(PaintedLayer* if (!newBuffer->Lock(lockMode)) { gfxCriticalNote << "Failed to lock new back buffer."; return result; } // If we have an existing front buffer, copy it into the new back buffer if (RefPtr<RotatedBuffer> frontBuffer = GetFrontBuffer()) { - if (frontBuffer->Lock(OpenMode::OPEN_READ_ONLY)) { - newBuffer->UpdateDestinationFrom(*frontBuffer, newBuffer->BufferRect()); - frontBuffer->Unlock(); - } else { + RefPtr<CapturedBufferState> bufferState = new CapturedBufferState(); + + bufferState->mBufferCopy = Some(CapturedBufferState::Copy { + frontBuffer->ShallowCopy(), + newBuffer->ShallowCopy(), + newBuffer->BufferRect(), + }); + + if (!bufferState->PrepareBuffer()) { gfxCriticalNote << "Failed to copy front buffer to back buffer."; return result; } } // Ensure our reference to the front buffer is released // as well as the old back buffer Clear(); @@ -846,17 +871,18 @@ ContentClientDoubleBuffered::GetFrontBuf return mFrontBuffer; } // 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 // back buffer (i.e. as they were for the old back buffer) void -ContentClientDoubleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw) +ContentClientDoubleBuffered::FinalizeFrame(const nsIntRegion& aRegionToDraw, + CapturedBufferState* aPrepareState) { if (!mFrontAndBackBufferDiffer) { MOZ_ASSERT(!mFrontBuffer || !mFrontBuffer->DidSelfCopy(), "If the front buffer did a self copy then our front and back buffer must be different."); return; } MOZ_ASSERT(mFrontBuffer && mBuffer); @@ -893,16 +919,18 @@ ContentClientDoubleBuffered::FinalizeFra // No point in sync'ing what we are going to draw over anyway. And if there is // nothing to sync at all, there is nothing to do and we can go home early. updateRegion.Sub(updateRegion, aRegionToDraw); if (updateRegion.IsEmpty()) { return; } - if (mFrontBuffer->Lock(OpenMode::OPEN_READ_ONLY)) { - mBuffer->UpdateDestinationFrom(*mFrontBuffer, updateRegion.GetBounds()); - mFrontBuffer->Unlock(); - } + MOZ_ASSERT(!aPrepareState->mBufferCopy); + aPrepareState->mBufferCopy = Some(CapturedBufferState::Copy { + mFrontBuffer->ShallowCopy(), + mBuffer->ShallowCopy(), + updateRegion.GetBounds(), + }); } } // namespace layers } // namespace mozilla
--- a/gfx/layers/client/ContentClient.h +++ b/gfx/layers/client/ContentClient.h @@ -17,16 +17,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/layers/PaintThread.h" // for CapturedBufferState #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 @@ -35,16 +36,19 @@ namespace mozilla { namespace gfx { class DrawTarget; } // namespace gfx namespace layers { class PaintedLayer; class CapturedPaintState; +class CapturedBufferState; + +typedef bool (*PrepDrawTargetForPaintingCallback)(CapturedPaintState*); /** * A compositable client for PaintedLayers. These are different to Image/Canvas * clients due to sending a valid region across IPC and because we do a lot more * optimisation work, encapsulated in RotatedBuffers. * * We use content clients for OMTC and non-OMTC, basic rendering so that * BasicPaintedLayer has only one interface to deal with. We support single and @@ -211,17 +215,18 @@ protected: /** * Any actions that should be performed at the last moment before we begin * rendering the next frame. I.e., after we calculate what we will draw, * but before we rotate the buffer and possibly create new buffers. * aRegionToDraw is the region which is guaranteed to be overwritten when * drawing the next frame. */ - virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) {} + virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw, + CapturedBufferState* aState) {} /** * Create a new rotated buffer for the specified content type, buffer rect, * and buffer flags. */ virtual RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType, const gfx::IntRect& aRect, uint32_t aFlags) = 0; @@ -356,17 +361,18 @@ public: virtual void Clear() override; virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override; virtual PaintState BeginPaint(PaintedLayer* aLayer, uint32_t aFlags) override; virtual RefPtr<RotatedBuffer> GetFrontBuffer() const override; - virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) override; + virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw, + CapturedBufferState* aState) override; virtual TextureInfo GetTextureInfo() const override { return TextureInfo(CompositableType::CONTENT_DOUBLE, mTextureFlags); } private: RefPtr<RemoteRotatedBuffer> mFrontBuffer;
--- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -218,16 +218,17 @@ EXPORTS.mozilla.layers += [ 'opengl/CompositorOGL.h', 'opengl/MacIOSurfaceTextureClientOGL.h', 'opengl/MacIOSurfaceTextureHostOGL.h', 'opengl/TextureClientOGL.h', 'opengl/TextureHostOGL.h', 'PaintThread.h', 'PersistentBufferProvider.h', 'RenderTrace.h', + 'RotatedBuffer.h', 'ShareableCanvasRenderer.h', 'SourceSurfaceSharedData.h', 'SourceSurfaceVolatileData.h', 'SyncObject.h', 'TextureSourceProvider.h', 'TextureWrapperImage.h', 'TransactionIdAllocator.h', 'UpdateImageHelper.h',