Refactor NotifyBeginAsyncPaint logic to not be repeated (bug 1422392, r=dvander)

MozReview-Commit-ID: B8BZCxYErjv

--HG--
extra : rebase_source : 17f022a10b484f5ae9ac6de9d376075c894f7226
This commit is contained in:
Ryan Hunt 2017-12-04 21:23:50 -05:00
Родитель 98e347bbf9
Коммит 14e019993c
4 изменённых файлов: 115 добавлений и 184 удалений

Просмотреть файл

@ -51,49 +51,6 @@ CapturedBufferState::PrepareBuffer()
(!mBufferInitialize || mBufferInitialize->CopyBuffer());
}
void
CapturedBufferState::GetTextureClients(nsTArray<RefPtr<TextureClient>>& aTextureClients)
{
if (mBufferFinalize) {
if (TextureClient* source = mBufferFinalize->mSource->GetClient()) {
aTextureClients.AppendElement(source);
}
if (TextureClient* sourceOnWhite = mBufferFinalize->mSource->GetClientOnWhite()) {
aTextureClients.AppendElement(sourceOnWhite);
}
if (TextureClient* destination = mBufferFinalize->mDestination->GetClient()) {
aTextureClients.AppendElement(destination);
}
if (TextureClient* destinationOnWhite = mBufferFinalize->mDestination->GetClientOnWhite()) {
aTextureClients.AppendElement(destinationOnWhite);
}
}
if (mBufferUnrotate) {
if (TextureClient* client = mBufferUnrotate->mBuffer->GetClient()) {
aTextureClients.AppendElement(client);
}
if (TextureClient* clientOnWhite = mBufferUnrotate->mBuffer->GetClientOnWhite()) {
aTextureClients.AppendElement(clientOnWhite);
}
}
if (mBufferInitialize) {
if (TextureClient* source = mBufferInitialize->mSource->GetClient()) {
aTextureClients.AppendElement(source);
}
if (TextureClient* sourceOnWhite = mBufferInitialize->mSource->GetClientOnWhite()) {
aTextureClients.AppendElement(sourceOnWhite);
}
if (TextureClient* destination = mBufferInitialize->mDestination->GetClient()) {
aTextureClients.AppendElement(destination);
}
if (TextureClient* destinationOnWhite = mBufferInitialize->mDestination->GetClientOnWhite()) {
aTextureClients.AppendElement(destinationOnWhite);
}
}
}
bool
CapturedTiledPaintState::Copy::CopyBuffer()
{
@ -283,7 +240,7 @@ PaintThread::PrepareBuffer(CapturedBufferState* aState)
RefPtr<CompositorBridgeChild> cbc(CompositorBridgeChild::Get());
RefPtr<CapturedBufferState> state(aState);
cbc->NotifyBeginAsyncPrepareBuffer(state);
cbc->NotifyBeginAsyncPaint(state);
RefPtr<PaintThread> self = this;
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PrepareBuffer",
@ -316,7 +273,7 @@ PaintThread::AsyncPrepareBuffer(CompositorBridgeChild* aBridge,
gfxCriticalNote << "Failed to prepare buffers on the paint thread.";
}
aBridge->NotifyFinishedAsyncPrepareBuffer(aState);
aBridge->NotifyFinishedAsyncPaint(aState);
}
void
@ -392,7 +349,7 @@ PaintThread::PaintTiledContents(CapturedTiledPaintState* aState)
RefPtr<CompositorBridgeChild> cbc(CompositorBridgeChild::Get());
RefPtr<CapturedTiledPaintState> state(aState);
cbc->NotifyBeginAsyncTiledPaint(state);
cbc->NotifyBeginAsyncPaint(state);
RefPtr<PaintThread> self = this;
RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintTiledContents",
@ -446,7 +403,7 @@ PaintThread::AsyncPaintTiledContents(CompositorBridgeChild* aBridge,
NS_ReleaseOnMainThreadSystemGroup("CapturePaintState::DrawTargetCapture", aState->mCapture.forget());
}
aBridge->NotifyFinishedAsyncTiledPaint(aState);
aBridge->NotifyFinishedAsyncPaint(aState);
}
void

Просмотреть файл

@ -44,6 +44,21 @@ public:
, mContentType(aContentType)
{}
template<typename F>
void ForEachTextureClient(F aClosure) const
{
aClosure(mTextureClient);
if (mTextureClientOnWhite) {
aClosure(mTextureClientOnWhite);
}
}
void DropTextureClients()
{
mTextureClient = nullptr;
mTextureClientOnWhite = nullptr;
}
nsIntRegion mRegionToDraw;
RefPtr<TextureClient> mTextureClient;
RefPtr<TextureClient> mTextureClientOnWhite;
@ -100,7 +115,56 @@ public:
* for the frame.
*/
bool PrepareBuffer();
void GetTextureClients(nsTArray<RefPtr<TextureClient>>& aTextureClients);
template<typename F>
void ForEachTextureClient(F aClosure) const
{
if (mBufferFinalize) {
if (TextureClient* source = mBufferFinalize->mSource->GetClient()) {
aClosure(source);
}
if (TextureClient* sourceOnWhite = mBufferFinalize->mSource->GetClientOnWhite()) {
aClosure(sourceOnWhite);
}
if (TextureClient* destination = mBufferFinalize->mDestination->GetClient()) {
aClosure(destination);
}
if (TextureClient* destinationOnWhite = mBufferFinalize->mDestination->GetClientOnWhite()) {
aClosure(destinationOnWhite);
}
}
if (mBufferUnrotate) {
if (TextureClient* client = mBufferUnrotate->mBuffer->GetClient()) {
aClosure(client);
}
if (TextureClient* clientOnWhite = mBufferUnrotate->mBuffer->GetClientOnWhite()) {
aClosure(clientOnWhite);
}
}
if (mBufferInitialize) {
if (TextureClient* source = mBufferInitialize->mSource->GetClient()) {
aClosure(source);
}
if (TextureClient* sourceOnWhite = mBufferInitialize->mSource->GetClientOnWhite()) {
aClosure(sourceOnWhite);
}
if (TextureClient* destination = mBufferInitialize->mDestination->GetClient()) {
aClosure(destination);
}
if (TextureClient* destinationOnWhite = mBufferInitialize->mDestination->GetClientOnWhite()) {
aClosure(destinationOnWhite);
}
}
}
void DropTextureClients()
{
mBufferFinalize = Nothing();
mBufferUnrotate = Nothing();
mBufferInitialize = Nothing();
}
Maybe<Copy> mBufferFinalize;
Maybe<Unrotate> mBufferUnrotate;
@ -158,6 +222,19 @@ public:
, mCapture(aCapture)
{}
template<typename F>
void ForEachTextureClient(F aClosure) const
{
for (auto client : mClients) {
aClosure(client);
}
}
void DropTextureClients()
{
mClients.clear();
}
RefPtr<gfx::DrawTarget> mTargetTiled;
RefPtr<gfx::DrawTargetCapture> mCapture;
std::vector<Copy> mCopies;

Просмотреть файл

@ -1192,123 +1192,6 @@ CompositorBridgeChild::FlushAsyncPaints()
}
}
void
CompositorBridgeChild::NotifyBeginAsyncPrepareBuffer(CapturedBufferState* aState)
{
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(mPaintLock);
// We must not be waiting for paints (or buffer copying) to complete yet. This
// would imply we started a new paint without waiting for a previous one, which
// could lead to incorrect rendering or IPDL deadlocks.
MOZ_ASSERT(!mIsDelayingForAsyncPaints);
mOutstandingAsyncPaints++;
// Mark texture clients that they are being used for async painting, and
// make sure we hold them alive on the main thread.
aState->GetTextureClients(mTextureClientsForAsyncPaint);
}
void
CompositorBridgeChild::NotifyFinishedAsyncPrepareBuffer(CapturedBufferState* aState)
{
MOZ_ASSERT(PaintThread::IsOnPaintThread());
MonitorAutoLock lock(mPaintLock);
mOutstandingAsyncPaints--;
}
void
CompositorBridgeChild::NotifyBeginAsyncPaint(CapturedPaintState* aState)
{
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(mPaintLock);
// We must not be waiting for paints to complete yet. This would imply we
// started a new paint without waiting for a previous one, which could lead to
// incorrect rendering or IPDL deadlocks.
MOZ_ASSERT(!mIsDelayingForAsyncPaints);
mOutstandingAsyncPaints++;
// Mark texture clients that they are being used for async painting, and
// make sure we hold them alive on the main thread.
aState->mTextureClient->AddPaintThreadRef();
mTextureClientsForAsyncPaint.AppendElement(aState->mTextureClient);
if (aState->mTextureClientOnWhite) {
aState->mTextureClientOnWhite->AddPaintThreadRef();
mTextureClientsForAsyncPaint.AppendElement(aState->mTextureClientOnWhite);
}
}
void
CompositorBridgeChild::NotifyFinishedAsyncPaint(CapturedPaintState* aState)
{
MOZ_ASSERT(PaintThread::IsOnPaintThread());
MonitorAutoLock lock(mPaintLock);
mOutstandingAsyncPaints--;
// These textures should be held alive on the main thread. The ref we
// captured should not be the final ref.
MOZ_RELEASE_ASSERT(!aState->mTextureClient->HasOneRef());
// It's now safe to drop the paint thread ref we're holding, since we've
// flushed writes to the underlying TextureData. Note that we keep the
// main thread ref around until FlushAsyncPaints is called, lazily ensuring
// the Release occurs on the main thread (versus a message in the event
// loop).
//
// Note that we zap our ref immediately after. Otherwise, the main thread
// could wake up when we drop the lock, and we could still be holding a ref
// on the paint thread. If this causes TextureClient to destroy then it will
// be destroyed on the wrong thread.
aState->mTextureClient->DropPaintThreadRef();
aState->mTextureClient = nullptr;
if (aState->mTextureClientOnWhite) {
aState->mTextureClientOnWhite->DropPaintThreadRef();
aState->mTextureClientOnWhite = nullptr;
}
}
void
CompositorBridgeChild::NotifyBeginAsyncTiledPaint(CapturedTiledPaintState* aState)
{
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(mPaintLock);
// We must not be waiting for paints to complete yet. This would imply we
// started a new paint without waiting for a previous one, which could lead to
// incorrect rendering or IPDL deadlocks.
MOZ_ASSERT(!mIsDelayingForAsyncPaints);
mOutstandingAsyncPaints++;
// Mark texture clients that they are being used for async painting, and
// make sure we hold them alive on the main thread.
for (auto& client : aState->mClients) {
mTextureClientsForAsyncPaint.AppendElement(client);
}
aState->mClients.clear();
}
void
CompositorBridgeChild::NotifyFinishedAsyncTiledPaint(CapturedTiledPaintState* aState)
{
MOZ_ASSERT(PaintThread::IsOnPaintThread());
MonitorAutoLock lock(mPaintLock);
mOutstandingAsyncPaints--;
aState->mTargetTiled = nullptr;
}
void
CompositorBridgeChild::NotifyBeginAsyncEndLayerTransaction()
{

Просмотреть файл

@ -14,6 +14,7 @@
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/layers/PCompositorBridgeChild.h"
#include "mozilla/layers/TextureForwarder.h" // for TextureForwarder
#include "mozilla/layers/PaintThread.h" // for PaintThread
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsClassHashtable.h" // for nsClassHashtable
#include "nsRefPtrHashtable.h"
@ -45,9 +46,6 @@ class CompositorManagerChild;
class CompositorOptions;
class TextureClient;
class TextureClientPool;
class CapturedBufferState;
class CapturedPaintState;
class CapturedTiledPaintState;
struct FrameMetrics;
class CompositorBridgeChild final : public PCompositorBridgeChild,
@ -225,29 +223,45 @@ public:
// operation completes.
void FlushAsyncPaints();
// Must only be called from the main thread. Notifies the CompositorBridge
// that the paint thread is going to begin preparing a buffer asynchronously.
void NotifyBeginAsyncPrepareBuffer(CapturedBufferState* aState);
// Must only be called from the paint thread. Notifies the CompositorBridge
// that the paint thread has finished an asynchronous buffer prepare.
void NotifyFinishedAsyncPrepareBuffer(CapturedBufferState* aState);
// Must only be called from the main thread. Notifies the CompositorBridge
// that the paint thread is going to begin painting asynchronously.
void NotifyBeginAsyncPaint(CapturedPaintState* aState);
template<typename CapturedState>
void NotifyBeginAsyncPaint(CapturedState& aState)
{
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock lock(mPaintLock);
// We must not be waiting for paints or buffer copying to complete yet. This
// would imply we started a new paint without waiting for a previous one, which
// could lead to incorrect rendering or IPDL deadlocks.
MOZ_ASSERT(!mIsDelayingForAsyncPaints);
mOutstandingAsyncPaints++;
// Mark texture clients that they are being used for async painting, and
// make sure we hold them alive on the main thread.
aState->ForEachTextureClient([this] (auto aClient) {
aClient->AddPaintThreadRef();
mTextureClientsForAsyncPaint.AppendElement(aClient);
});
}
// Must only be called from the paint thread. Notifies the CompositorBridge
// that the paint thread has finished an asynchronous paint request.
void NotifyFinishedAsyncPaint(CapturedPaintState* aState);
template<typename CapturedState>
void NotifyFinishedAsyncPaint(CapturedState& aState)
{
MOZ_ASSERT(PaintThread::IsOnPaintThread());
// Must only be called from the main thread. Notifies the CompositorBridge
// that the paint thread is going to begin painting asynchronously.
void NotifyBeginAsyncTiledPaint(CapturedTiledPaintState* aState);
MonitorAutoLock lock(mPaintLock);
mOutstandingAsyncPaints--;
// Must only be called from the paint thread. Notifies the CompositorBridge
// that the paint thread has finished an asynchronous paint request.
void NotifyFinishedAsyncTiledPaint(CapturedTiledPaintState* aState);
aState->ForEachTextureClient([] (auto aClient) {
aClient->DropPaintThreadRef();
});
aState->DropTextureClients();
}
// Must only be called from the main thread. Notifies the CompositorBridge
// that the paint thread is going to perform texture synchronization at the