Bug 1143575. Factor out AsyncTransactionWaiter from AsyncTransactionTracker so we'll be able to wait for multiple AsyncTransactionTrackers. r=nical,sotaro

--HG--
extra : commitid : KV6Mne8t10A
extra : rebase_source : 02de1f49ce13465481cfa688b8867fc558cac474
This commit is contained in:
Robert O'Callahan 2015-05-12 15:36:49 +12:00
Родитель 4b6793f937
Коммит 7f3db8a464
11 изменённых файлов: 120 добавлений и 93 удалений

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

@ -34,7 +34,8 @@ class PCompositableChild;
*/
class RemoveTextureFromCompositableTracker : public AsyncTransactionTracker {
public:
RemoveTextureFromCompositableTracker()
explicit RemoveTextureFromCompositableTracker(AsyncTransactionWaiter* aWaiter = nullptr)
: AsyncTransactionTracker(aWaiter)
{
MOZ_COUNT_CTOR(RemoveTextureFromCompositableTracker);
}

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

@ -442,20 +442,24 @@ ContentClientDoubleBuffered::Updated(const nsIntRegion& aRegionToDraw,
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if (mFrontClient) {
// remove old buffer from CompositableHost
RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
RefPtr<AsyncTransactionWaiter> waiter = new AsyncTransactionWaiter();
RefPtr<AsyncTransactionTracker> tracker =
new RemoveTextureFromCompositableTracker(waiter);
// Hold TextureClient until transaction complete.
tracker->SetTextureClient(mFrontClient);
mFrontClient->SetRemoveFromCompositableTracker(tracker);
mFrontClient->SetRemoveFromCompositableWaiter(waiter);
// RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontClient);
}
if (mFrontClientOnWhite) {
// remove old buffer from CompositableHost
RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
RefPtr<AsyncTransactionWaiter> waiter = new AsyncTransactionWaiter();
RefPtr<AsyncTransactionTracker> tracker =
new RemoveTextureFromCompositableTracker(waiter);
// Hold TextureClient until transaction complete.
tracker->SetTextureClient(mFrontClientOnWhite);
mFrontClientOnWhite->SetRemoveFromCompositableTracker(tracker);
mFrontClientOnWhite->SetRemoveFromCompositableWaiter(waiter);
// RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontClientOnWhite);
}

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

@ -74,21 +74,18 @@ ImageClient::CreateImageClient(CompositableType aCompositableHostType,
void
ImageClient::RemoveTexture(TextureClient* aTexture)
{
RemoveTextureWithTracker(aTexture, nullptr);
RemoveTextureWithWaiter(aTexture);
}
void
ImageClient::RemoveTextureWithTracker(TextureClient* aTexture,
AsyncTransactionTracker* aAsyncTransactionTracker)
ImageClient::RemoveTextureWithWaiter(TextureClient* aTexture,
AsyncTransactionWaiter* aAsyncTransactionWaiter)
{
#ifdef MOZ_WIDGET_GONK
if (aAsyncTransactionTracker ||
if (aAsyncTransactionWaiter ||
GetForwarder()->IsImageBridgeChild()) {
RefPtr<AsyncTransactionTracker> request = aAsyncTransactionTracker;
if (!request) {
// Create AsyncTransactionTracker if it is not provided as argument.
request = new RemoveTextureFromCompositableTracker();
}
RefPtr<AsyncTransactionTracker> request =
new RemoveTextureFromCompositableTracker(aAsyncTransactionWaiter);
// Hold TextureClient until the transaction complete to postpone
// the TextureClient recycle/delete.
request->SetTextureClient(aTexture);
@ -98,11 +95,6 @@ ImageClient::RemoveTextureWithTracker(TextureClient* aTexture,
#endif
GetForwarder()->RemoveTextureFromCompositable(this, aTexture);
if (aAsyncTransactionTracker) {
// Do not need to wait a transaction complete message
// from the compositor side.
aAsyncTransactionTracker->NotifyComplete();
}
}
ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
@ -117,22 +109,13 @@ TextureInfo ImageClientSingle::GetTextureInfo() const
return TextureInfo(CompositableType::IMAGE);
}
already_AddRefed<AsyncTransactionTracker>
ImageClientSingle::PrepareFlushAllImages()
{
return MakeAndAddRef<RemoveTextureFromCompositableTracker>();
}
void
ImageClientSingle::FlushAllImages(bool aExceptFront,
AsyncTransactionTracker* aAsyncTransactionTracker)
AsyncTransactionWaiter* aAsyncTransactionWaiter)
{
if (!aExceptFront && mFrontBuffer) {
RemoveTextureWithTracker(mFrontBuffer, aAsyncTransactionTracker);
RemoveTextureWithWaiter(mFrontBuffer, aAsyncTransactionWaiter);
mFrontBuffer = nullptr;
} else if (aAsyncTransactionTracker) {
// already flushed
aAsyncTransactionTracker->NotifyComplete();
}
}

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

@ -61,22 +61,17 @@ public:
void SetLayer(ClientLayer* aLayer) { mLayer = aLayer; }
ClientLayer* GetLayer() const { return mLayer; }
/**
* Create AsyncTransactionTracker that is used for FlushAllImagesAsync().
*/
virtual already_AddRefed<AsyncTransactionTracker> PrepareFlushAllImages() { return nullptr; }
/**
* asynchronously remove all the textures used by the image client.
*
*/
virtual void FlushAllImages(bool aExceptFront,
AsyncTransactionTracker* aAsyncTransactionTracker) {}
AsyncTransactionWaiter* aAsyncTransactionWaiter) {}
virtual void RemoveTexture(TextureClient* aTexture) override;
void RemoveTextureWithTracker(TextureClient* aTexture,
AsyncTransactionTracker* aAsyncTransactionTracker = nullptr);
void RemoveTextureWithWaiter(TextureClient* aTexture,
AsyncTransactionWaiter* aAsyncTransactionWaiter = nullptr);
protected:
ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
@ -107,10 +102,8 @@ public:
virtual already_AddRefed<Image> CreateImage(ImageFormat aFormat) override;
virtual already_AddRefed<AsyncTransactionTracker> PrepareFlushAllImages() override;
virtual void FlushAllImages(bool aExceptFront,
AsyncTransactionTracker* aAsyncTransactionTracker) override;
AsyncTransactionWaiter* aAsyncTransactionWaiter) override;
protected:
RefPtr<TextureClient> mFrontBuffer;

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

@ -40,7 +40,7 @@ namespace mozilla {
namespace layers {
class AsyncTransactionTracker;
class AsyncTransactionWaiter;
class CompositableForwarder;
class ISurfaceAllocator;
class CompositableClient;
@ -448,7 +448,7 @@ public:
/**
* Set AsyncTransactionTracker of RemoveTextureFromCompositableAsync() transaction.
*/
virtual void SetRemoveFromCompositableTracker(AsyncTransactionTracker* aTracker) {}
virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {}
/**
* This function waits until the buffer is no longer being used.

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

@ -569,10 +569,12 @@ TileClient::Flip()
if (mFrontBuffer && mFrontBuffer->GetIPDLActor() &&
mCompositableClient && mCompositableClient->GetIPDLActor()) {
// remove old buffer from CompositableHost
RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
RefPtr<AsyncTransactionWaiter> waiter = new AsyncTransactionWaiter();
RefPtr<AsyncTransactionTracker> tracker =
new RemoveTextureFromCompositableTracker(waiter);
// Hold TextureClient until transaction complete.
tracker->SetTextureClient(mFrontBuffer);
mFrontBuffer->SetRemoveFromCompositableTracker(tracker);
mFrontBuffer->SetRemoveFromCompositableWaiter(waiter);
// RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
mManager->AsShadowForwarder()->RemoveTextureFromCompositableAsync(tracker,
mCompositableClient,
@ -667,10 +669,12 @@ TileClient::DiscardFrontBuffer()
if (mFrontBuffer->GetIPDLActor() &&
mCompositableClient && mCompositableClient->GetIPDLActor()) {
// remove old buffer from CompositableHost
RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
RefPtr<AsyncTransactionWaiter> waiter = new AsyncTransactionWaiter();
RefPtr<AsyncTransactionTracker> tracker =
new RemoveTextureFromCompositableTracker(waiter);
// Hold TextureClient until transaction complete.
tracker->SetTextureClient(mFrontBuffer);
mFrontBuffer->SetRemoveFromCompositableTracker(tracker);
mFrontBuffer->SetRemoveFromCompositableWaiter(waiter);
// RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
mManager->AsShadowForwarder()->RemoveTextureFromCompositableAsync(tracker,
mCompositableClient,

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

@ -12,29 +12,15 @@
namespace mozilla {
namespace layers {
uint64_t AsyncTransactionTracker::sSerialCounter(0);
Mutex* AsyncTransactionTracker::sLock = nullptr;
AsyncTransactionTracker::AsyncTransactionTracker()
: mSerial(GetNextSerial())
, mCompletedMonitor("AsyncTransactionTracker.mCompleted")
, mCompleted(false)
{
}
AsyncTransactionTracker::~AsyncTransactionTracker()
{
}
void
AsyncTransactionTracker::WaitComplete()
AsyncTransactionWaiter::WaitComplete()
{
MOZ_ASSERT(!InImageBridgeChildThread());
MonitorAutoLock mon(mCompletedMonitor);
int count = 0;
const int maxCount = 5;
while (!mCompleted && (count < maxCount)) {
while (mWaitCount > 0 && (count < maxCount)) {
if (!NS_SUCCEEDED(mCompletedMonitor.Wait(PR_MillisecondsToInterval(10000)))) {
NS_WARNING("Failed to wait Monitor");
return;
@ -45,29 +31,48 @@ AsyncTransactionTracker::WaitComplete()
count++;
}
if (!mCompleted) {
if (mWaitCount > 0) {
printf_stderr("Timeout of waiting transaction complete.");
}
}
uint64_t AsyncTransactionTracker::sSerialCounter(0);
Mutex* AsyncTransactionTracker::sLock = nullptr;
AsyncTransactionTracker::AsyncTransactionTracker(AsyncTransactionWaiter* aWaiter)
: mSerial(GetNextSerial())
, mWaiter(aWaiter)
, mCompleted(false)
{
if (mWaiter) {
mWaiter->IncrementWaitCount();
}
}
AsyncTransactionTracker::~AsyncTransactionTracker()
{
}
void
AsyncTransactionTracker::NotifyComplete()
{
MonitorAutoLock mon(mCompletedMonitor);
MOZ_ASSERT(!mCompleted);
mCompleted = true;
Complete();
mCompletedMonitor.Notify();
if (mWaiter) {
mWaiter->DecrementWaitCount();
}
}
void
AsyncTransactionTracker::NotifyCancel()
{
MonitorAutoLock mon(mCompletedMonitor);
MOZ_ASSERT(!mCompleted);
mCompleted = true;
Cancel();
mCompletedMonitor.Notify();
if (mWaiter) {
mWaiter->DecrementWaitCount();
}
}
uint64_t AsyncTransactionTrackersHolder::sSerialCounter(0);

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

@ -21,6 +21,46 @@ namespace layers {
class TextureClient;
class AsyncTransactionTrackersHolder;
/**
* Object that lets you wait for one or more async transactions to complete.
*/
class AsyncTransactionWaiter
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncTransactionWaiter)
AsyncTransactionWaiter()
: mCompletedMonitor("AsyncTransactionWaiter")
, mWaitCount(0)
{}
void IncrementWaitCount()
{
MonitorAutoLock lock(mCompletedMonitor);
++mWaitCount;
}
void DecrementWaitCount()
{
MonitorAutoLock lock(mCompletedMonitor);
MOZ_ASSERT(mWaitCount > 0);
--mWaitCount;
if (mWaitCount == 0) {
mCompletedMonitor.Notify();
}
}
/**
* Wait until asynchronous transactions complete.
*/
void WaitComplete();
private:
~AsyncTransactionWaiter() {}
Monitor mCompletedMonitor;
uint32_t mWaitCount;
};
/**
* AsyncTransactionTracker tracks asynchronous transaction.
* It is typically used for asynchronous layer transaction handling.
@ -31,17 +71,7 @@ class AsyncTransactionTracker
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncTransactionTracker)
AsyncTransactionTracker();
Monitor& GetReentrantMonitor()
{
return mCompletedMonitor;
}
/**
* Wait until asynchronous transaction complete.
*/
void WaitComplete();
explicit AsyncTransactionTracker(AsyncTransactionWaiter* aWaiter = nullptr);
/**
* Notify async transaction complete.
@ -100,8 +130,8 @@ protected:
}
uint64_t mSerial;
Monitor mCompletedMonitor;
bool mCompleted;
RefPtr<AsyncTransactionWaiter> mWaiter;
DebugOnly<bool> mCompleted;
/**
* gecko does not provide atomic operation for uint64_t.

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

@ -414,16 +414,21 @@ void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
}
static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer,
bool aExceptFront, AsyncTransactionTracker* aStatus)
bool aExceptFront, AsyncTransactionWaiter* aWaiter)
{
MOZ_ASSERT(aClient);
sImageBridgeChildSingleton->BeginTransaction();
if (aContainer && !aExceptFront) {
aContainer->ClearCurrentImage();
}
aClient->FlushAllImages(aExceptFront, aStatus);
aClient->FlushAllImages(aExceptFront, aWaiter);
aClient->OnTransaction();
sImageBridgeChildSingleton->EndTransaction();
// This decrement is balanced by the increment in FlushAllImages.
// If any AsyncTransactionTrackers were created by FlushAllImages and attached
// to aWaiter, aWaiter will not complete until those trackers all complete.
// Otherwise, aWaiter will be ready to complete now.
aWaiter->DecrementWaitCount();
}
//static
@ -441,13 +446,15 @@ void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
return;
}
RefPtr<AsyncTransactionTracker> status = aClient->PrepareFlushAllImages();
RefPtr<AsyncTransactionWaiter> waiter = new AsyncTransactionWaiter();
// This increment is balanced by the decrement in FlushAllImagesSync
waiter->IncrementWaitCount();
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
FROM_HERE,
NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, aExceptFront, status));
NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, aExceptFront, waiter));
status->WaitComplete();
waiter->WaitComplete();
}
void

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

@ -76,17 +76,17 @@ GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
}
void
GrallocTextureClientOGL::SetRemoveFromCompositableTracker(AsyncTransactionTracker* aTracker)
GrallocTextureClientOGL::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter)
{
mRemoveFromCompositableTracker = aTracker;
mRemoveFromCompositableWaiter = aWaiter;
}
void
GrallocTextureClientOGL::WaitForBufferOwnership(bool aWaitReleaseFence)
{
if (mRemoveFromCompositableTracker) {
mRemoveFromCompositableTracker->WaitComplete();
mRemoveFromCompositableTracker = nullptr;
if (mRemoveFromCompositableWaiter) {
mRemoveFromCompositableWaiter->WaitComplete();
mRemoveFromCompositableWaiter = nullptr;
}
if (!aWaitReleaseFence) {

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

@ -60,7 +60,7 @@ public:
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
virtual void SetRemoveFromCompositableTracker(AsyncTransactionTracker* aTracker) override;
virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) override;
virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true) override;
@ -127,7 +127,7 @@ protected:
*/
MaybeMagicGrallocBufferHandle mGrallocHandle;
RefPtr<AsyncTransactionTracker> mRemoveFromCompositableTracker;
RefPtr<AsyncTransactionWaiter> mRemoveFromCompositableWaiter;
android::sp<android::GraphicBuffer> mGraphicBuffer;