Bug 1252835 - Make TextureHost recycling implicit r=nical

This commit is contained in:
Sotaro Ikeda 2016-06-15 04:28:10 -07:00
parent cae8c6bcee
commit f731d220ed
58 changed files with 1110 additions and 810 deletions

View File

@ -306,7 +306,7 @@ SurfaceFactory::~SurfaceFactory()
while (!mRecycleTotalPool.empty()) {
RefPtr<layers::SharedSurfaceTextureClient> tex = *mRecycleTotalPool.begin();
StopRecycling(tex);
tex->CancelWaitForCompositorRecycle();
tex->CancelWaitForRecycle();
}
MOZ_RELEASE_ASSERT(mRecycleTotalPool.empty(),"GFX: Surface recycle pool not empty.");

View File

@ -8,6 +8,7 @@
#include "mozilla/layers/CompositorBridgeParent.h" // for CompositorBridgeParent
#include "mozilla/layers/Effects.h" // for Effect, EffectChain, etc
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureHost.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "gfx2DGlue.h"
@ -33,6 +34,7 @@ Compositor::Compositor(widget::CompositorWidgetProxy* aWidget,
, mPixelsFilled(0)
, mScreenRotation(ROTATION_0)
, mWidget(aWidget)
, mIsDestroyed(false)
{
}
@ -44,6 +46,13 @@ Compositor::~Compositor()
mUnlockAfterComposition.Clear();
}
void
Compositor::Destroy()
{
FlushPendingNotifyNotUsed();
mIsDestroyed = true;
}
void
Compositor::EndFrame()
{
@ -53,6 +62,23 @@ Compositor::EndFrame()
mUnlockAfterComposition.Clear();
}
void
Compositor::NotifyNotUsedAfterComposition(TextureHost* aTextureHost)
{
MOZ_ASSERT(!mIsDestroyed);
mNotifyNotUsedAfterComposition.AppendElement(aTextureHost);
}
void
Compositor::FlushPendingNotifyNotUsed()
{
for (auto& textureHost : mNotifyNotUsedAfterComposition) {
textureHost->CallNotifyNotUsed();
}
mNotifyNotUsedAfterComposition.Clear();
}
/* static */ void
Compositor::AssertOnCompositorThread()
{

View File

@ -133,6 +133,7 @@ class CompositorOGL;
class CompositorD3D9;
class CompositorD3D11;
class BasicCompositor;
class TextureHost;
class TextureReadLock;
enum SurfaceInitMode
@ -200,7 +201,8 @@ public:
CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) { return nullptr; }
virtual bool Initialize() = 0;
virtual void Destroy() = 0;
virtual void Destroy();
bool IsDestroyed() const { return mIsDestroyed; }
virtual void DetachWidget() { mWidget = nullptr; }
@ -544,6 +546,16 @@ public:
mUnlockAfterComposition.AppendElement(aLock);
}
/// Most compositor backends operate asynchronously under the hood. This
/// means that when a layer stops using a texture it is often desirable to
/// wait for the end of the next composition before NotifyNotUsed() call.
/// This function provides a convenient way to do this delayed NotifyNotUsed()
/// call, if the texture itself requires it.
/// See bug 1260611 and bug 1252835
void NotifyNotUsedAfterComposition(TextureHost* aTextureHost);
void FlushPendingNotifyNotUsed();
protected:
void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
const gfx::Rect& aVisibleRect,
@ -573,6 +585,11 @@ protected:
*/
nsTArray<RefPtr<TextureReadLock>> mUnlockAfterComposition;
/**
* An array of TextureHosts that will need to call NotifyNotUsed() after the next composition.
*/
nsTArray<RefPtr<TextureHost>> mNotifyNotUsedAfterComposition;
/**
* Render time for the current composition.
*/
@ -603,6 +620,8 @@ protected:
widget::CompositorWidgetProxy* mWidget;
bool mIsDestroyed;
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
FenceHandle mReleaseFenceHandle;
#endif

View File

@ -44,7 +44,9 @@ enum class TextureFlags : uint32_t {
// Data in this texture has not been alpha-premultiplied.
// XXX - Apparently only used with ImageClient/Host
NON_PREMULTIPLIED = 1 << 4,
// The texture should be recycled when no longer in used
// The TextureClient should be recycled with recycle callback when no longer
// in used. When the texture is used in host side, ref count of TextureClient
// is transparently added by ShadowLayerForwarder or ImageBridgeChild.
RECYCLE = 1 << 5,
// If DEALLOCATE_CLIENT is set, the shared data is deallocated on the
// client side and requires some extra synchronizaion to ensure race-free

View File

@ -52,8 +52,6 @@ public:
virtual bool Initialize() override;
virtual void Destroy() override {}
virtual void DetachWidget() override;
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() override;

View File

@ -464,25 +464,6 @@ CanvasClientSharedSurface::Updated()
auto forwarder = GetForwarder();
#ifndef MOZ_WIDGET_GONK
if (mFront) {
if (mFront->GetFlags() & TextureFlags::RECYCLE) {
mFront->WaitForCompositorRecycle();
}
}
#else
// AutoRemoveTexture does the followings.
// - Ensure to deliver FenceHandle from TextureHost to TextureClient, before
// next TextureClient usage.
// - Control TextureClient's recycling timing.
// - Call RemoveTexture() after newFront's UseTextures() call.
// It could improve performance of Host side's EGL handling on gonk
AutoRemoveTexture autoRemove(this);
if (mFront && mFront != mNewFront) {
autoRemove.mTexture = mFront;
}
#endif
mFront = mNewFront;
mNewFront = nullptr;
@ -505,7 +486,7 @@ CanvasClientSharedSurface::Updated()
void
CanvasClientSharedSurface::OnDetach() {
if (mShSurfClient) {
mShSurfClient->CancelWaitForCompositorRecycle();
mShSurfClient->CancelWaitForRecycle();
}
ClearSurfaces();
}

View File

@ -101,7 +101,7 @@ ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
, mCompositorMightResample(false)
, mNeedsComposite(false)
, mPaintSequenceNumber(0)
, mForwarder(new ShadowLayerForwarder)
, mForwarder(new ShadowLayerForwarder(this))
, mDeviceCounter(gfxPlatform::GetPlatform()->GetDeviceCounter())
{
MOZ_COUNT_CTOR(ClientLayerManager);
@ -670,7 +670,6 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
}
mForwarder->SendPendingAsyncMessges();
mPhase = PHASE_NONE;
// this may result in Layers being deleted, which results in

View File

@ -31,7 +31,6 @@ using namespace mozilla::gfx;
* CompositableChild is owned by a CompositableClient.
*/
class CompositableChild : public ChildActor<PCompositableChild>
, public AsyncTransactionTrackersHolder
{
public:
CompositableChild()
@ -46,7 +45,6 @@ public:
}
virtual void ActorDestroy(ActorDestroyReason) override {
DestroyAsyncTransactionTrackersHolder();
if (mCompositableClient) {
mCompositableClient->mCompositableChild = nullptr;
}
@ -73,27 +71,6 @@ RemoveTextureFromCompositableTracker::ReleaseTextureClient()
}
}
/* static */ void
CompositableClient::TransactionCompleteted(PCompositableChild* aActor, uint64_t aTransactionId)
{
CompositableChild* child = static_cast<CompositableChild*>(aActor);
child->TransactionCompleteted(aTransactionId);
}
/* static */ void
CompositableClient::HoldUntilComplete(PCompositableChild* aActor, AsyncTransactionTracker* aTracker)
{
CompositableChild* child = static_cast<CompositableChild*>(aActor);
child->HoldUntilComplete(aTracker);
}
/* static */ uint64_t
CompositableClient::GetTrackersHolderId(PCompositableChild* aActor)
{
CompositableChild* child = static_cast<CompositableChild*>(aActor);
return child->GetId();
}
/* static */ PCompositableChild*
CompositableClient::CreateIPDLActor()
{
@ -181,10 +158,6 @@ CompositableClient::Destroy()
return;
}
// Send pending AsyncMessages before deleting CompositableChild since the former
// might have references to the latter.
mForwarder->SendPendingAsyncMessges();
mCompositableChild->mCompositableClient = nullptr;
mCompositableChild->Destroy(mForwarder);
mCompositableChild = nullptr;
@ -299,7 +272,6 @@ CompositableClient::DumpTextureClient(std::stringstream& aStream,
AutoRemoveTexture::~AutoRemoveTexture()
{
if (mCompositable && mTexture && mCompositable->IsConnected()) {
mTexture->RemoveFromCompositable(mCompositable);
mCompositable->RemoveTexture(mTexture);
}
}

View File

@ -226,12 +226,6 @@ public:
void InitIPDLActor(PCompositableChild* aActor, uint64_t aAsyncID = 0);
static void TransactionCompleteted(PCompositableChild* aActor, uint64_t aTransactionId);
static void HoldUntilComplete(PCompositableChild* aActor, AsyncTransactionTracker* aTracker);
static uint64_t GetTrackersHolderId(PCompositableChild* aActor);
TextureFlags GetTextureFlags() const { return mTextureFlags; }
TextureClientRecycleAllocator* GetTextureClientRecycler();

View File

@ -445,14 +445,6 @@ ContentClientDoubleBuffered::Updated(const nsIntRegion& aRegionToDraw,
bool aDidSelfCopy)
{
ContentClientRemoteBuffer::Updated(aRegionToDraw, aVisibleRegion, aDidSelfCopy);
if (mFrontClient) {
mFrontClient->RemoveFromCompositable(this);
}
if (mFrontClientOnWhite) {
mFrontClientOnWhite->RemoveFromCompositable(this);
}
}
void

View File

@ -77,23 +77,14 @@ void
ImageClient::RemoveTextureWithWaiter(TextureClient* aTexture,
AsyncTransactionWaiter* aAsyncTransactionWaiter)
{
if ((aAsyncTransactionWaiter || GetForwarder()->UsesImageBridge())
#ifndef MOZ_WIDGET_GONK
// If the texture client is taking part in recycling then we should make sure
// the host has finished with it before dropping the ref and triggering
// the recycle callback.
&& aTexture->GetRecycleAllocator()
#endif
) {
if (aAsyncTransactionWaiter &&
GetForwarder()->UsesImageBridge()) {
RefPtr<AsyncTransactionTracker> request =
new RemoveTextureFromCompositableTracker(aAsyncTransactionWaiter);
// Hold TextureClient until the transaction complete to postpone
// the TextureClient recycle/delete.
request->SetTextureClient(aTexture);
GetForwarder()->RemoveTextureFromCompositableAsync(request, this, aTexture);
return;
}
MOZ_ASSERT(!aAsyncTransactionWaiter);
GetForwarder()->RemoveTextureFromCompositable(this, aTexture);
}
@ -112,6 +103,8 @@ TextureInfo ImageClientSingle::GetTextureInfo() const
void
ImageClientSingle::FlushAllImages(AsyncTransactionWaiter* aAsyncTransactionWaiter)
{
MOZ_ASSERT(GetForwarder()->UsesImageBridge());
for (auto& b : mBuffers) {
RemoveTextureWithWaiter(b.mTextureClient, aAsyncTransactionWaiter);
}

View File

@ -13,8 +13,10 @@
#include "mozilla/layers/AsyncTransactionTracker.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/TextureClientRecycleAllocator.h"
#include "mozilla/Mutex.h"
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
#include "ImageContainer.h" // for PlanarYCbCrData, etc
@ -108,33 +110,6 @@ public:
bool Recv__delete__() override { return true; }
bool RecvCompositorRecycle() override
{
RECYCLE_LOG("[CLIENT] Receive recycle %p (%p)\n", mTextureClient, mWaitForRecycle.get());
mWaitForRecycle = nullptr;
return true;
}
void WaitForCompositorRecycle()
{
Lock();
mWaitForRecycle = mDestroyed ? nullptr : mTextureClient;
Unlock();
RECYCLE_LOG("[CLIENT] Wait for recycle %p\n", mWaitForRecycle.get());
MOZ_ASSERT(CanSend());
SendClientRecycle();
}
void CancelWaitForCompositorRecycle()
{
RECYCLE_LOG("[CLIENT] Cancelling wait for recycle %p\n", mWaitForRecycle.get());
Lock();
mWaitForRecycle = nullptr;
Unlock();
}
CompositableForwarder* GetForwarder() { return mForwarder; }
ClientIPCAllocator* GetAllocator() { return mForwarder; }
@ -230,7 +205,6 @@ private:
mutable gfx::CriticalSection mLock;
RefPtr<CompositableForwarder> mForwarder;
RefPtr<TextureClient> mWaitForRecycle;
TextureClient* mTextureClient;
TextureData* mTextureData;
@ -271,7 +245,6 @@ void
TextureChild::ActorDestroy(ActorDestroyReason why)
{
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
mWaitForRecycle = nullptr;
if (mTextureData) {
DestroyTextureData(mTextureData, GetAllocator(), mOwnsTextureData, mMainThreadOnly);
@ -279,6 +252,8 @@ TextureChild::ActorDestroy(ActorDestroyReason why)
}
}
/* static */ Atomic<uint64_t> TextureClient::sSerialCounter(0);
void DeallocateTextureClientSyncProxy(TextureDeallocParams params,
ReentrantMonitor* aBarrier, bool* aDone)
{
@ -385,6 +360,7 @@ void TextureClient::Destroy(bool aForceSync)
mActor->Lock();
}
CancelWaitFenceHandleOnImageBridge();
RefPtr<TextureChild> actor = mActor;
mActor = nullptr;
@ -464,9 +440,8 @@ TextureClient::Lock(OpenMode aMode)
return mOpenMode == aMode;
}
if (mRemoveFromCompositableWaiter) {
mRemoveFromCompositableWaiter->WaitComplete();
mRemoveFromCompositableWaiter = nullptr;
if (!!mFenceHandleWaiter && (aMode & OpenMode::OPEN_WRITE)) {
mFenceHandleWaiter->WaitComplete();
}
if (aMode & OpenMode::OPEN_WRITE && IsReadLocked()) {
@ -476,7 +451,8 @@ TextureClient::Lock(OpenMode aMode)
LockActor();
mIsLocked = mData->Lock(aMode, mReleaseFenceHandle.IsValid() ? &mReleaseFenceHandle : nullptr);
FenceHandle* fence = (mReleaseFenceHandle.IsValid() && (aMode & OpenMode::OPEN_WRITE)) ? &mReleaseFenceHandle : nullptr;
mIsLocked = mData->Lock(aMode, fence);
mOpenMode = aMode;
auto format = GetFormat();
@ -683,9 +659,8 @@ TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
void
TextureClient::WaitForBufferOwnership(bool aWaitReleaseFence)
{
if (mRemoveFromCompositableWaiter) {
mRemoveFromCompositableWaiter->WaitComplete();
mRemoveFromCompositableWaiter = nullptr;
if (mFenceHandleWaiter) {
mFenceHandleWaiter->WaitComplete();
}
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21
@ -788,22 +763,6 @@ TextureClient::RecycleTexture(TextureFlags aFlags)
UnlockActor();
}
void
TextureClient::WaitForCompositorRecycle()
{
if (IsSharedWithCompositor()) {
mActor->WaitForCompositorRecycle();
}
}
void
TextureClient::CancelWaitForCompositorRecycle()
{
if (IsSharedWithCompositor()) {
mActor->CancelWaitForCompositorRecycle();
}
}
void
TextureClient::SetAddedToCompositableClient()
{
@ -812,6 +771,75 @@ TextureClient::SetAddedToCompositableClient()
}
}
void
TextureClient::WaitFenceHandleOnImageBridge(Mutex& aMutex)
{
MOZ_ASSERT(NS_IsMainThread());
aMutex.AssertCurrentThreadOwns();
if (!mFenceHandleWaiter) {
mFenceHandleWaiter = new AsyncTransactionWaiter();
}
MOZ_ASSERT(mFenceHandleWaiter->GetWaitCount() <= 1);
if (mFenceHandleWaiter->GetWaitCount() > 0) {
return;
}
mFenceHandleWaiter->IncrementWaitCount();
}
void
TextureClient::ClearWaitFenceHandleOnImageBridge(Mutex& aMutex)
{
MOZ_ASSERT(InImageBridgeChildThread());
aMutex.AssertCurrentThreadOwns();
if (!mFenceHandleWaiter) {
return;
}
MOZ_ASSERT(mFenceHandleWaiter->GetWaitCount() <= 1);
if (mFenceHandleWaiter->GetWaitCount() == 0) {
return;
}
mFenceHandleWaiter->DecrementWaitCount();
}
void
TextureClient::CancelWaitFenceHandleOnImageBridge()
{
if (!NeedsFenceHandle() || GetFlags() & TextureFlags::RECYCLE) {
return;
}
ImageBridgeChild::GetSingleton()->CancelWaitFenceHandle(this);
}
void CancelTextureClientRecycle(uint64_t aTextureId, ClientIPCAllocator* aAllocator)
{
if (!aAllocator) {
return;
}
MessageLoop* msgLoop = nullptr;
msgLoop = aAllocator->GetMessageLoop();
if (!msgLoop) {
return;
}
if (MessageLoop::current() == msgLoop) {
aAllocator->CancelWaitForRecycle(aTextureId);
} else {
msgLoop->PostTask(NewRunnableFunction(CancelTextureClientRecycle,
aTextureId, aAllocator));
}
}
void
TextureClient::CancelWaitForRecycle()
{
if (GetFlags() & TextureFlags::RECYCLE) {
CancelTextureClientRecycle(mSerial, GetAllocator());
return;
}
CancelWaitFenceHandleOnImageBridge();
}
/* static */ void
TextureClient::TextureClientRecycleCallback(TextureClient* aClient, void* aClosure)
{
@ -844,7 +872,10 @@ TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
return false;
}
mActor = static_cast<TextureChild*>(aForwarder->CreateTexture(desc, aForwarder->GetCompositorBackendType(), GetFlags()));
mActor = static_cast<TextureChild*>(aForwarder->CreateTexture(desc,
aForwarder->GetCompositorBackendType(),
GetFlags(),
mSerial));
MOZ_ASSERT(mActor);
mActor->mForwarder = aForwarder;
mActor->mTextureClient = this;
@ -1072,10 +1103,11 @@ TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, ClientIPCA
#endif
, mIsLocked(false)
, mUpdated(false)
, mInUse(false)
, mAddedToCompositableClient(false)
, mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
, mWorkaroundAnnoyingSharedSurfaceOwnershipIssues(false)
, mFwdTransactionId(0)
, mSerial(++sSerialCounter)
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
, mPoolTracker(nullptr)
#endif
@ -1114,35 +1146,6 @@ bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
return true;
}
void
TextureClient::RemoveFromCompositable(CompositableClient* aCompositable,
AsyncTransactionWaiter* aWaiter)
{
MOZ_ASSERT(aCompositable);
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if (mActor && aCompositable->GetIPDLActor()
&& mData->AsGrallocTextureData()) {
// remove old buffer from CompositableHost
RefPtr<AsyncTransactionWaiter> waiter = aWaiter ? aWaiter
: new AsyncTransactionWaiter();
RefPtr<AsyncTransactionTracker> tracker =
new RemoveTextureFromCompositableTracker(waiter);
// Hold TextureClient until transaction complete.
tracker->SetTextureClient(this);
mRemoveFromCompositableWaiter = waiter;
// RemoveTextureFromCompositableAsync() expects CompositorBridgeChild's presence.
mActor->GetForwarder()->RemoveTextureFromCompositableAsync(tracker, aCompositable, this);
}
#endif
}
void
TextureClient::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {
mRemoveFromCompositableWaiter = aWaiter;
}
already_AddRefed<gfx::DataSourceSurface>
TextureClient::GetAsSurface()
{

View File

@ -29,6 +29,7 @@
#include "nsISupportsImpl.h" // for TextureImage::AddRef, etc
#include "GfxTexturesReporter.h"
#include "pratom.h"
#include "nsThreadUtils.h"
class gfxImageSurface;
@ -410,13 +411,6 @@ public:
bool CanExposeMappedData() const { return mInfo.canExposeMappedData; }
/* TextureClientRecycleAllocator tracking to decide if we need
* to check with the compositor before recycling.
* Should be superceeded (and removed) by bug 1252835.
*/
void SetInUse(bool aInUse) { mInUse = aInUse; }
bool IsInUse() { return mInUse; }
/**
* Returns a DrawTarget to draw into the TextureClient.
* This function should never be called when not on the main thread!
@ -513,21 +507,6 @@ public:
// The TextureClient must not be locked when calling this method.
void RecycleTexture(TextureFlags aFlags);
/**
* valid only for TextureFlags::RECYCLE TextureClient.
* When called this texture client will grab a strong reference and release
* it once the compositor notifies that it is done with the texture.
* NOTE: In this stage the texture client can no longer be used by the
* client in a transaction.
*/
void WaitForCompositorRecycle();
/**
* Should only be called when dying. We no longer care whether the compositor
* has finished with the texture.
*/
void CancelWaitForCompositorRecycle();
/**
* After being shared with the compositor side, an immutable texture is never
* modified, it can only be read. It is safe to not Lock/Unlock immutable
@ -605,11 +584,6 @@ public:
return mAcquireFenceHandle;
}
/**
* Set AsyncTransactionTracker of RemoveTextureFromCompositableAsync() transaction.
*/
virtual void SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter);
/**
* This function waits until the buffer is no longer being used.
*
@ -646,9 +620,43 @@ public:
TextureData* GetInternalData() { return mData; }
const TextureData* GetInternalData() const { return mData; }
virtual void RemoveFromCompositable(CompositableClient* aCompositable,
AsyncTransactionWaiter* aWaiter = nullptr);
uint64_t GetSerial() const { return mSerial; }
bool NeedsFenceHandle()
{
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
if (!mData) {
return false;
}
return !!mData->AsGrallocTextureData();
#else
return false;
#endif
}
void WaitFenceHandleOnImageBridge(Mutex& aMutex);
void ClearWaitFenceHandleOnImageBridge(Mutex& aMutex);
void CancelWaitFenceHandleOnImageBridge();
void CancelWaitForRecycle();
/**
* Set last transaction id of CompositableForwarder.
*
* Called when TextureClient has TextureFlags::RECYCLE flag.
* When CompositableForwarder forwards the TextureClient with
* TextureFlags::RECYCLE, it holds TextureClient's ref until host side
* releases it. The host side sends TextureClient release message.
* The id is used to check if the message is for the last TextureClient
* forwarding.
*/
void SetLastFwdTransactionId(uint64_t aTransactionId)
{
MOZ_ASSERT(mFwdTransactionId < aTransactionId);
mFwdTransactionId = aTransactionId;
}
uint64_t GetLastFwdTransactionId() { return mFwdTransactionId; }
void EnableReadLock();
@ -691,7 +699,6 @@ protected:
RefPtr<ClientIPCAllocator> mAllocator;
RefPtr<TextureChild> mActor;
RefPtr<ITextureClientRecycleAllocator> mRecycleAllocator;
RefPtr<AsyncTransactionWaiter> mRemoveFromCompositableWaiter;
RefPtr<TextureReadLock> mReadLock;
TextureData* mData;
@ -700,6 +707,8 @@ protected:
TextureFlags mFlags;
FenceHandle mReleaseFenceHandle;
FenceHandle mAcquireFenceHandle;
RefPtr<AsyncTransactionWaiter> mFenceHandleWaiter;
gl::GfxTextureWasteTracker mWasteTracker;
OpenMode mOpenMode;
@ -711,7 +720,6 @@ protected:
// is sent to the compositor. We need this remember to lock mReadLock on
// behalf of the compositor just before sending the notification.
bool mUpdated;
bool mInUse;
bool mAddedToCompositableClient;
bool mWorkaroundAnnoyingSharedSurfaceLifetimeIssues;
@ -719,6 +727,13 @@ protected:
RefPtr<TextureReadbackSink> mReadbackSink;
uint64_t mFwdTransactionId;
// Serial id of TextureClient. It is unique in current process.
const uint64_t mSerial;
// Used to assign serial ids of TextureClient.
static mozilla::Atomic<uint64_t> sSerialCounter;
friend class TextureChild;
friend class RemoveTextureFromCompositableTracker;
friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);

View File

@ -181,7 +181,6 @@ TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& a
// Make sure the texture holds a reference to us, and ask it to call RecycleTextureClient when its
// ref count drops to 1.
client->SetRecycleAllocator(this);
client->SetInUse(true);
return client.forget();
}
@ -205,35 +204,9 @@ TextureClientRecycleAllocator::ShrinkToMinimumSize()
}
}
class TextureClientWaitTask : public Runnable
{
public:
explicit TextureClientWaitTask(TextureClient* aClient)
: mTextureClient(aClient)
{}
NS_IMETHOD Run() override
{
mTextureClient->WaitForCompositorRecycle();
return NS_OK;
}
private:
RefPtr<TextureClient> mTextureClient;
};
void
TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
{
if (aClient->IsInUse()) {
aClient->SetInUse(false);
// This adds another ref to aClient, and drops it after a round trip
// to the compositor. We should then get this callback a second time
// and can recycle properly.
RefPtr<Runnable> task = new TextureClientWaitTask(aClient);
mSurfaceAllocator->GetMessageLoop()->PostTask(task.forget());
return;
}
// Clearing the recycle allocator drops a reference, so make sure we stay alive
// for the duration of this function.
RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);

View File

@ -470,15 +470,6 @@ TileClient::Dump(std::stringstream& aStream)
void
TileClient::Flip()
{
if (mCompositableClient) {
if (mFrontBuffer) {
mFrontBuffer->RemoveFromCompositable(mCompositableClient);
}
if (mFrontBufferOnWhite) {
mFrontBufferOnWhite->RemoveFromCompositable(mCompositableClient);
}
}
RefPtr<TextureClient> frontBuffer = mFrontBuffer;
RefPtr<TextureClient> frontBufferOnWhite = mFrontBufferOnWhite;
mFrontBuffer = mBackBuffer;
@ -559,13 +550,8 @@ TileClient::DiscardFrontBuffer()
if (mFrontBuffer) {
MOZ_ASSERT(mFrontBuffer->GetReadLock());
if (mCompositableClient) {
mFrontBuffer->RemoveFromCompositable(mCompositableClient);
}
mAllocator->ReturnTextureClientDeferred(mFrontBuffer);
if (mFrontBufferOnWhite) {
mFrontBufferOnWhite->RemoveFromCompositable(mCompositableClient);
mAllocator->ReturnTextureClientDeferred(mFrontBufferOnWhite);
}
if (mFrontBuffer->IsLocked()) {

View File

@ -188,7 +188,7 @@ public:
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0;
struct TimedTexture {
RefPtr<TextureHost> mTexture;
CompositableTextureHostRef mTexture;
TimeStamp mTimeStamp;
gfx::IntRect mPictureRect;
int32_t mFrameID;

View File

@ -331,11 +331,6 @@ ImageHost::Composite(LayerComposite* aLayer,
TimedImage* img = &mImages[imageIndex];
img->mTextureHost->SetCompositor(GetCompositor());
// If this TextureHost will be recycled, then make sure we hold a reference to
// it until we're sure that the compositor has finished reading from it.
if (img->mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
aLayer->GetLayerManager()->HoldTextureUntilNextComposite(img->mTextureHost);
}
SetCurrentTextureHost(img->mTextureHost);
{

View File

@ -395,9 +395,7 @@ LayerManagerComposite::EndTransaction(const TimeStamp& aTimeStamp,
if (mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
MOZ_ASSERT(!aTimeStamp.IsNull());
UpdateAndRender();
mPreviousHeldTextureHosts.Clear();
mPreviousHeldTextureHosts.SwapElements(mCurrentHeldTextureHosts);
mCompositor->FlushPendingNotifyNotUsed();
} else {
// Modified the layer tree.
mGeometryChanged = true;

View File

@ -337,10 +337,6 @@ public:
void ForcePresent() { mCompositor->ForcePresent(); }
void HoldTextureUntilNextComposite(TextureHost* aTextureHost) {
mCurrentHeldTextureHosts.AppendElement(aTextureHost);
}
private:
/** Region we're clipping our current drawing to. */
nsIntRegion mClippingRegion;
@ -401,9 +397,6 @@ private:
nsTArray<ImageCompositeNotification> mImageCompositeNotifications;
nsTArray<RefPtr<TextureHost>> mCurrentHeldTextureHosts;
nsTArray<RefPtr<TextureHost>> mPreviousHeldTextureHosts;
/**
* Context target, nullptr when drawing directly to our swap chain.
*/

View File

@ -66,7 +66,7 @@ namespace layers {
class TextureParent : public ParentActor<PTextureParent>
{
public:
explicit TextureParent(HostIPCAllocator* aAllocator);
explicit TextureParent(HostIPCAllocator* aAllocator, uint64_t aSerial);
~TextureParent();
@ -74,9 +74,7 @@ public:
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags);
void CompositorRecycle();
virtual bool RecvClientRecycle() override;
void NotifyNotUsed(uint64_t aTransactionId);
virtual bool RecvRecycleTexture(const TextureFlags& aTextureFlags) override;
@ -84,9 +82,12 @@ public:
virtual void Destroy() override;
uint64_t GetSerial() const { return mSerial; }
HostIPCAllocator* mSurfaceAllocator;
RefPtr<TextureHost> mWaitForClientRecycle;
RefPtr<TextureHost> mTextureHost;
// mSerial is unique in TextureClient's process.
const uint64_t mSerial;
};
////////////////////////////////////////////////////////////////////////////////
@ -94,7 +95,8 @@ PTextureParent*
TextureHost::CreateIPDLActor(HostIPCAllocator* aAllocator,
const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags)
TextureFlags aFlags,
uint64_t aSerial)
{
if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
aSharedData.get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::Tuintptr_t &&
@ -103,7 +105,7 @@ TextureHost::CreateIPDLActor(HostIPCAllocator* aAllocator,
NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
return nullptr;
}
TextureParent* actor = new TextureParent(aAllocator);
TextureParent* actor = new TextureParent(aAllocator, aSerial);
if (!actor->Init(aSharedData, aLayersBackend, aFlags)) {
delete actor;
return nullptr;
@ -136,6 +138,16 @@ TextureHost::AsTextureHost(PTextureParent* actor)
return static_cast<TextureParent*>(actor)->mTextureHost;
}
// static
uint64_t
TextureHost::GetTextureSerial(PTextureParent* actor)
{
if (!actor) {
return UINT64_MAX;
}
return static_cast<TextureParent*>(actor)->mSerial;
}
PTextureParent*
TextureHost::GetIPDLActor()
{
@ -177,6 +189,13 @@ TextureHost::GetAndResetAcquireFenceHandle()
return FenceHandle(fdObj);
}
void
TextureHost::SetLastFwdTransactionId(uint64_t aTransactionId)
{
MOZ_ASSERT(mFwdTransactionId <= aTransactionId);
mFwdTransactionId = aTransactionId;
}
// implemented in TextureHostOGL.cpp
already_AddRefed<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
ISurfaceAllocator* aDeallocator,
@ -293,19 +312,11 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
return result.forget();
}
void
TextureHost::CompositorRecycle()
{
if (!mActor) {
return;
}
static_cast<TextureParent*>(mActor)->CompositorRecycle();
}
TextureHost::TextureHost(TextureFlags aFlags)
: mActor(nullptr)
, mFlags(aFlags)
, mCompositableCount(0)
, mFwdTransactionId(0)
{
MOZ_COUNT_CTOR(TextureHost);
}
@ -353,10 +364,51 @@ TextureHost::RecycleTexture(TextureFlags aFlags)
{
MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
MOZ_ASSERT(aFlags & TextureFlags::RECYCLE);
MOZ_ASSERT(!HasRecycleCallback());
mFlags = aFlags;
}
void
TextureHost::NotifyNotUsed()
{
if (!mActor) {
return;
}
// Do not need to call NotifyNotUsed() if TextureHost does not have
// TextureFlags::RECYCLE flag and TextureHost is not GrallocTextureHostOGL.
if (!(GetFlags() & TextureFlags::RECYCLE) &&
!AsGrallocTextureHostOGL()) {
return;
}
auto compositor = GetCompositor();
// The following cases do not need to defer NotifyNotUsed until next Composite.
// - TextureHost does not have Compositor.
// - Compositor is BasicCompositor.
// - TextureHost has intermediate buffer.
// - TextureHost is GrallocTextureHostOGL. Fence object is used to detect
// end of buffer usage.
if (!compositor ||
compositor->IsDestroyed() ||
compositor->AsBasicCompositor() ||
HasIntermediateBuffer() ||
AsGrallocTextureHostOGL()) {
static_cast<TextureParent*>(mActor)->NotifyNotUsed(mFwdTransactionId);
return;
}
compositor->NotifyNotUsedAfterComposition(this);
}
void
TextureHost::CallNotifyNotUsed()
{
if (!mActor) {
return;
}
static_cast<TextureParent*>(mActor)->NotifyNotUsed(mFwdTransactionId);
}
void
TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{
@ -964,8 +1016,9 @@ size_t MemoryTextureHost::GetBufferSize()
return std::numeric_limits<size_t>::max();
}
TextureParent::TextureParent(HostIPCAllocator* aSurfaceAllocator)
TextureParent::TextureParent(HostIPCAllocator* aSurfaceAllocator, uint64_t aSerial)
: mSurfaceAllocator(aSurfaceAllocator)
, mSerial(aSerial)
{
MOZ_COUNT_CTOR(TextureParent);
}
@ -973,40 +1026,15 @@ TextureParent::TextureParent(HostIPCAllocator* aSurfaceAllocator)
TextureParent::~TextureParent()
{
MOZ_COUNT_DTOR(TextureParent);
if (mTextureHost) {
mTextureHost->ClearRecycleCallback();
}
}
static void RecycleCallback(TextureHost*, void* aClosure) {
TextureParent* tp = reinterpret_cast<TextureParent*>(aClosure);
tp->CompositorRecycle();
}
void
TextureParent::CompositorRecycle()
TextureParent::NotifyNotUsed(uint64_t aTransactionId)
{
mTextureHost->ClearRecycleCallback();
if (mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
mozilla::Unused << SendCompositorRecycle();
// Don't forget to prepare for the next reycle
// if TextureClient request it.
mWaitForClientRecycle = mTextureHost;
if (!mTextureHost) {
return;
}
}
bool
TextureParent::RecvClientRecycle()
{
// This will allow the RecycleCallback to be called once the compositor
// releases any external references to TextureHost.
mTextureHost->SetRecycleCallback(RecycleCallback, this);
if (!mWaitForClientRecycle) {
RECYCLE_LOG("Not a recycable tile");
}
mWaitForClientRecycle = nullptr;
return true;
mSurfaceAllocator->NotifyNotUsed(this, aTransactionId);
}
bool
@ -1020,10 +1048,6 @@ TextureParent::Init(const SurfaceDescriptor& aSharedData,
aFlags);
if (mTextureHost) {
mTextureHost->mActor = this;
if (aFlags & TextureFlags::RECYCLE) {
mWaitForClientRecycle = mTextureHost;
RECYCLE_LOG("Setup recycling for tile %p\n", this);
}
}
return !!mTextureHost;
@ -1036,18 +1060,10 @@ TextureParent::Destroy()
return;
}
if (mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
RECYCLE_LOG("clear recycling for tile %p\n", this);
mTextureHost->ClearRecycleCallback();
}
if (mTextureHost->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
mTextureHost->ForgetSharedData();
}
// Clear recycle callback.
mTextureHost->ClearRecycleCallback();
mWaitForClientRecycle = nullptr;
mTextureHost->mActor = nullptr;
mTextureHost = nullptr;
}

View File

@ -43,6 +43,7 @@ class Compositor;
class CompositableParentManager;
class ReadLockDescriptor;
class CompositorBridgeParent;
class GrallocTextureHostOGL;
class SurfaceDescriptor;
class HostIPCAllocator;
class ISurfaceAllocator;
@ -384,16 +385,6 @@ public:
LayersBackend aBackend,
TextureFlags aFlags);
/**
* Tell to TextureChild that TextureHost is recycled.
* This function should be called from TextureHost's RecycleCallback.
* If SetRecycleCallback is set to TextureHost.
* TextureHost can be recycled by calling RecycleCallback
* when reference count becomes one.
* One reference count is always added by TextureChild.
*/
void CompositorRecycle();
/**
* Lock the texture host for compositing.
*/
@ -511,7 +502,8 @@ public:
static PTextureParent* CreateIPDLActor(HostIPCAllocator* aAllocator,
const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags);
TextureFlags aFlags,
uint64_t aSerial);
static bool DestroyIPDLActor(PTextureParent* actor);
/**
@ -526,6 +518,8 @@ public:
*/
static TextureHost* AsTextureHost(PTextureParent* actor);
static uint64_t GetTextureSerial(PTextureParent* actor);
/**
* Return a pointer to the IPDLActor.
*
@ -570,6 +564,8 @@ public:
MOZ_ASSERT(mCompositableCount >= 0);
if (mCompositableCount == 0) {
UnbindTextureSource();
// Send mFwdTransactionId to client side if necessary.
NotifyNotUsed();
}
}
@ -595,6 +591,8 @@ public:
virtual void WaitAcquireFenceHandleSyncComplete() {};
void SetLastFwdTransactionId(uint64_t aTransactionId);
virtual bool NeedsFenceHandle() { return false; }
virtual FenceHandle GetCompositorReleaseFence() { return FenceHandle(); }
@ -606,6 +604,10 @@ public:
virtual Compositor* GetCompositor() = 0;
virtual GrallocTextureHostOGL* AsGrallocTextureHostOGL() { return nullptr; }
void CallNotifyNotUsed();
protected:
void ReadUnlock();
@ -617,12 +619,19 @@ protected:
virtual void UpdatedInternal(const nsIntRegion *Region) {}
/**
* Called when mCompositableCount becomes 0.
*/
void NotifyNotUsed();
PTextureParent* mActor;
RefPtr<TextureReadLock> mReadLock;
TextureFlags mFlags;
int mCompositableCount;
uint64_t mFwdTransactionId;
friend class TextureParent;
friend class TiledLayerBufferComposite;
};
/**

View File

@ -48,7 +48,6 @@ public:
virtual CompositorD3D11* AsCompositorD3D11() override { return this; }
virtual bool Initialize() override;
virtual void Destroy() override {}
virtual TextureFactoryIdentifier
GetTextureFactoryIdentifier() override;

View File

@ -27,7 +27,6 @@ public:
virtual CompositorD3D9* AsCompositorD3D9() override { return this; }
virtual bool Initialize() override;
virtual void Destroy() override {}
virtual TextureFactoryIdentifier
GetTextureFactoryIdentifier() override;

View File

@ -85,20 +85,12 @@ AsyncTransactionTracker::NotifyCancel()
}
Atomic<uint64_t> AsyncTransactionTrackersHolder::sSerialCounter(0);
Mutex* AsyncTransactionTrackersHolder::sHolderLock = nullptr;
std::map<uint64_t, AsyncTransactionTrackersHolder*> AsyncTransactionTrackersHolder::sTrackersHolders;
AsyncTransactionTrackersHolder::AsyncTransactionTrackersHolder()
: mSerial(GetNextSerial())
, mIsTrackersHolderDestroyed(false)
{
MOZ_COUNT_CTOR(AsyncTransactionTrackersHolder);
{
MOZ_ASSERT(sHolderLock);
MutexAutoLock lock(*sHolderLock);
sTrackersHolders[mSerial] = this;
}
}
AsyncTransactionTrackersHolder::~AsyncTransactionTrackersHolder()
@ -106,16 +98,6 @@ AsyncTransactionTrackersHolder::~AsyncTransactionTrackersHolder()
if (!mIsTrackersHolderDestroyed) {
DestroyAsyncTransactionTrackersHolder();
}
{
if (sHolderLock) {
sHolderLock->Lock();
}
sTrackersHolders.erase(mSerial);
if (sHolderLock) {
sHolderLock->Unlock();
}
}
MOZ_COUNT_DTOR(AsyncTransactionTrackersHolder);
}
@ -132,7 +114,6 @@ AsyncTransactionTrackersHolder::HoldUntilComplete(AsyncTransactionTracker* aTran
}
if (aTransactionTracker) {
MutexAutoLock lock(*sHolderLock);
mAsyncTransactionTrackers[aTransactionTracker->GetId()] = aTransactionTracker;
}
}
@ -140,7 +121,6 @@ AsyncTransactionTrackersHolder::HoldUntilComplete(AsyncTransactionTracker* aTran
void
AsyncTransactionTrackersHolder::TransactionCompleteted(uint64_t aTransactionId)
{
MutexAutoLock lock(*sHolderLock);
TransactionCompletetedInternal(aTransactionId);
}
@ -166,45 +146,15 @@ AsyncTransactionTrackersHolder::SetReleaseFenceHandle(FenceHandle& aReleaseFence
}
}
/*static*/ void
AsyncTransactionTrackersHolder::TransactionCompleteted(uint64_t aHolderId, uint64_t aTransactionId)
{
MutexAutoLock lock(*sHolderLock);
AsyncTransactionTrackersHolder* holder = sTrackersHolders[aHolderId];
if (!holder) {
return;
}
holder->TransactionCompletetedInternal(aTransactionId);
}
/*static*/ void
AsyncTransactionTrackersHolder::SetReleaseFenceHandle(FenceHandle& aReleaseFenceHandle,
uint64_t aHolderId,
uint64_t aTransactionId)
{
MutexAutoLock lock(*sHolderLock);
AsyncTransactionTrackersHolder* holder = sTrackersHolders[aHolderId];
if (!holder) {
return;
}
holder->SetReleaseFenceHandle(aReleaseFenceHandle, aTransactionId);
}
void
AsyncTransactionTrackersHolder::ClearAllAsyncTransactionTrackers()
{
if (sHolderLock) {
sHolderLock->Lock();
}
std::map<uint64_t, RefPtr<AsyncTransactionTracker> >::iterator it;
for (it = mAsyncTransactionTrackers.begin();
it != mAsyncTransactionTrackers.end(); it++) {
it->second->NotifyCancel();
}
mAsyncTransactionTrackers.clear();
if (sHolderLock) {
sHolderLock->Unlock();
}
}
void

View File

@ -54,6 +54,8 @@ public:
*/
void WaitComplete();
uint32_t GetWaitCount() { return mWaitCount; }
private:
~AsyncTransactionWaiter() {}
@ -106,14 +108,6 @@ public:
protected:
virtual ~AsyncTransactionTracker();
static void Initialize()
{
}
static void Finalize()
{
}
static uint64_t GetNextSerial()
{
return ++sSerialCounter;
@ -125,10 +119,6 @@ protected:
bool mCompleted;
#endif
/**
* gecko does not provide atomic operation for uint64_t.
* Ensure atomicity by using Mutex.
*/
static Atomic<uint64_t> sSerialCounter;
};
@ -138,23 +128,6 @@ public:
AsyncTransactionTrackersHolder();
virtual ~AsyncTransactionTrackersHolder();
static void Initialize()
{
if (!sHolderLock) {
sHolderLock = new Mutex("AsyncTransactionTrackersHolder::sHolderLock");
}
AsyncTransactionTracker::Initialize();
}
static void Finalize()
{
if (sHolderLock) {
delete sHolderLock;
sHolderLock = nullptr;
}
AsyncTransactionTracker::Finalize();
}
void HoldUntilComplete(AsyncTransactionTracker* aTransactionTracker);
void TransactionCompleteted(uint64_t aTransactionId);
@ -170,6 +143,8 @@ public:
return mSerial;
}
void DestroyAsyncTransactionTrackersHolder();
protected:
static uint64_t GetNextSerial()
@ -183,24 +158,12 @@ protected:
void ClearAllAsyncTransactionTrackers();
void DestroyAsyncTransactionTrackersHolder();
uint64_t mSerial;
const uint64_t mSerial;
bool mIsTrackersHolderDestroyed;
std::map<uint64_t, RefPtr<AsyncTransactionTracker> > mAsyncTransactionTrackers;
/**
* gecko does not provide atomic operation for uint64_t.
* Ensure atomicity by using Mutex.
*/
static Atomic<uint64_t> sSerialCounter;
static Mutex* sHolderLock;
/**
* Map of all living AsyncTransactionTrackersHolder instances
*/
static std::map<uint64_t, AsyncTransactionTrackersHolder*> sTrackersHolders;
};
} // namespace layers

View File

@ -17,6 +17,8 @@
#include "mozilla/layers/TextureClient.h" // for TextureClient
#include "nsRegion.h" // for nsIntRegion
#include "mozilla/gfx/Rect.h"
#include "nsHashKeys.h"
#include "nsTHashtable.h"
namespace mozilla {
namespace layers {
@ -68,7 +70,8 @@ public:
virtual PTextureChild* CreateTexture(
const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags) = 0;
TextureFlags aFlags,
uint64_t aSerial) = 0;
/**
* Communicate to the compositor that aRegion in the texture identified by
@ -132,8 +135,6 @@ public:
TextureClient* aClientOnBlack,
TextureClient* aClientOnWhite) = 0;
virtual void SendPendingAsyncMessges() = 0;
void IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier);
virtual int32_t GetMaxTextureSize() const override
@ -166,6 +167,9 @@ public:
return mTextureFactoryIdentifier;
}
virtual void UpdateFwdTransactionId() = 0;
virtual uint64_t GetFwdTransactionId() = 0;
int32_t GetSerial() { return mSerial; }
SyncObject* GetSyncObject() { return mSyncObject; }
@ -177,6 +181,7 @@ protected:
nsTArray<RefPtr<TextureClient> > mTexturesToRemove;
nsTArray<RefPtr<CompositableClient>> mCompositableClientsToRemove;
RefPtr<SyncObject> mSyncObject;
const int32_t mSerial;
static mozilla::Atomic<int32_t> sSerialCounter;
};

View File

@ -118,7 +118,33 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
NS_ASSERTION(tiledHost, "The compositable is not tiled");
const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
bool success = tiledHost->UseTiledLayerBuffer(this, tileDesc);
const InfallibleTArray<TileDescriptor>& tileDescriptors = tileDesc.tiles();
for (size_t i = 0; i < tileDescriptors.Length(); i++) {
const TileDescriptor& tileDesc = tileDescriptors[i];
if (tileDesc.type() != TileDescriptor::TTexturedTileDescriptor) {
continue;
}
const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(texturedDesc.textureParent());
if (texture) {
texture->SetLastFwdTransactionId(mFwdTransactionId);
// Make sure that each texture was handled by the compositable
// because the recycling logic depends on it.
MOZ_ASSERT(texture->NumCompositableRefs() > 0);
}
if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
texture = TextureHost::AsTextureHost(texturedDesc.textureOnWhite().get_PTextureParent());
if (texture) {
texture->SetLastFwdTransactionId(mFwdTransactionId);
// Make sure that each texture was handled by the compositable
// because the recycling logic depends on it.
MOZ_ASSERT(texture->NumCompositableRefs() > 0);
}
}
}
if (!success) {
return false;
}
@ -131,8 +157,6 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
MOZ_ASSERT(tex.get());
compositable->RemoveTextureHost(tex);
// send FenceHandle if present.
SendFenceHandleIfPresent(op.textureParent());
break;
}
case CompositableOperationDetail::TOpRemoveTextureAsync: {
@ -142,24 +166,9 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
MOZ_ASSERT(tex.get());
compositable->RemoveTextureHost(tex);
if (!UsesImageBridge() && ImageBridgeParent::GetInstance(GetChildProcessId())) {
// send FenceHandle if present via ImageBridge.
ImageBridgeParent::AppendDeliverFenceMessage(
GetChildProcessId(),
op.holderId(),
op.transactionId(),
op.textureParent());
// If the message is recievied via PLayerTransaction,
// Send message back via PImageBridge.
ImageBridgeParent::ReplyRemoveTexture(
GetChildProcessId(),
OpReplyRemoveTexture(op.holderId(),
op.transactionId()));
} else {
// send FenceHandle if present.
SendFenceHandleIfPresent(op.textureParent());
// Only ImageBridge child sends it.
MOZ_ASSERT(UsesImageBridge());
if (UsesImageBridge()) {
ReplyRemoveTexture(OpReplyRemoveTexture(op.holderId(),
op.transactionId()));
}
@ -192,6 +201,16 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
}
if (textures.Length() > 0) {
compositable->UseTextureHost(textures);
for (auto& timedTexture : op.textures()) {
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(timedTexture.textureParent());
if (texture) {
texture->SetLastFwdTransactionId(mFwdTransactionId);
// Make sure that each texture was handled by the compositable
// because the recycling logic depends on it.
MOZ_ASSERT(texture->NumCompositableRefs() > 0);
}
}
}
if (UsesImageBridge() && compositable->GetLayer()) {
@ -205,9 +224,24 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent());
texOnBlack->DeserializeReadLock(op.sharedLockBlack(), this);
texOnWhite->DeserializeReadLock(op.sharedLockWhite(), this);
MOZ_ASSERT(texOnBlack && texOnWhite);
compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite);
if (texOnBlack) {
texOnBlack->SetLastFwdTransactionId(mFwdTransactionId);
// Make sure that each texture was handled by the compositable
// because the recycling logic depends on it.
MOZ_ASSERT(texOnBlack->NumCompositableRefs() > 0);
}
if (texOnWhite) {
texOnWhite->SetLastFwdTransactionId(mFwdTransactionId);
// Make sure that each texture was handled by the compositable
// because the recycling logic depends on it.
MOZ_ASSERT(texOnWhite->NumCompositableRefs() > 0);
}
if (UsesImageBridge()) {
ScheduleComposition(compositable);
}
@ -251,42 +285,6 @@ CompositableParentManager::DestroyActor(const OpDestroy& aOp)
}
}
void
CompositableParentManager::SendPendingAsyncMessages()
{
if (mPendingAsyncMessage.empty()) {
return;
}
// Some type of AsyncParentMessageData message could have
// one file descriptor (e.g. OpDeliverFence).
// A number of file descriptors per gecko ipc message have a limitation
// on OS_POSIX (MACOSX or LINUX).
#if defined(OS_POSIX)
static const uint32_t kMaxMessageNumber = FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE;
#else
// default number that works everywhere else
static const uint32_t kMaxMessageNumber = 250;
#endif
InfallibleTArray<AsyncParentMessageData> messages;
messages.SetCapacity(mPendingAsyncMessage.size());
for (size_t i = 0; i < mPendingAsyncMessage.size(); i++) {
messages.AppendElement(mPendingAsyncMessage[i]);
// Limit maximum number of messages.
if (messages.Length() >= kMaxMessageNumber) {
SendAsyncMessage(messages);
// Initialize Messages.
messages.Clear();
}
}
if (messages.Length() > 0) {
SendAsyncMessage(messages);
}
mPendingAsyncMessage.clear();
}
} // namespace layers
} // namespace mozilla

View File

@ -28,14 +28,16 @@ typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
class CompositableParentManager : public HostIPCAllocator
{
public:
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) = 0;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) = 0;
void SendPendingAsyncMessages();
void DestroyActor(const OpDestroy& aOp);
void UpdateFwdTransactionId(uint64_t aTransactionId)
{
MOZ_ASSERT(mFwdTransactionId < aTransactionId);
mFwdTransactionId = aTransactionId;
}
uint64_t GetFwdTransactionId() { return mFwdTransactionId; }
protected:
/**
* Handle the IPDL messages that affect PCompositable actors.
@ -43,9 +45,9 @@ protected:
bool ReceiveCompositableUpdate(const CompositableOperation& aEdit,
EditReplyVector& replyv);
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) {}
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) {};
std::vector<AsyncParentMessageData> mPendingAsyncMessage;
uint64_t mFwdTransactionId = 0;
};
} // namespace layers

View File

@ -13,6 +13,7 @@
#include "base/task.h" // for NewRunnableMethod, etc
#include "mozilla/layers/LayerTransactionChild.h"
#include "mozilla/layers/PLayerTransactionChild.h"
#include "mozilla/layers/TextureClient.h"// for TextureClient
#include "mozilla/mozalloc.h" // for operator new, etc
#include "nsAutoPtr.h"
#include "nsDebug.h" // for NS_RUNTIMEABORT
@ -42,6 +43,7 @@ Atomic<int32_t> CompositableForwarder::sSerialCounter(0);
CompositorBridgeChild::CompositorBridgeChild(ClientLayerManager *aLayerManager)
: mLayerManager(aLayerManager)
, mCanSend(false)
, mFwdTransactionId(0)
{
}
@ -76,6 +78,7 @@ CompositorBridgeChild::Destroy()
{
// This must not be called from the destructor!
MOZ_ASSERT(mRefCnt != 0);
mTexturesWaitingRecycled.Clear();
if (!mCanSend) {
return;
@ -766,7 +769,8 @@ PTextureChild*
CompositorBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
const LayersBackend&,
const TextureFlags&,
const uint64_t&)
const uint64_t&,
const uint64_t& aSerial)
{
return TextureClient::CreateIPDLActor();
}
@ -777,6 +781,90 @@ CompositorBridgeChild::DeallocPTextureChild(PTextureChild* actor)
return TextureClient::DestroyIPDLActor(actor);
}
bool
CompositorBridgeChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
{
for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncParentMessageData& message = aMessages[i];
switch (message.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = message.get_OpDeliverFence();
FenceHandle fence = op.fence();
DeliverFence(op.TextureId(), fence);
break;
}
case AsyncParentMessageData::TOpNotifyNotUsed: {
const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed();
NotifyNotUsed(op.TextureId(), op.fwdTransactionId());
break;
}
default:
NS_ERROR("unknown AsyncParentMessageData type");
return false;
}
}
return true;
}
void
CompositorBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient)
{
if (!aClient) {
return;
}
if (!(aClient->GetFlags() & TextureFlags::RECYCLE) &&
!aClient->NeedsFenceHandle()) {
return;
}
if (aClient->GetFlags() & TextureFlags::RECYCLE) {
aClient->SetLastFwdTransactionId(GetFwdTransactionId());
mTexturesWaitingRecycled.Put(aClient->GetSerial(), aClient);
return;
}
MOZ_ASSERT(!(aClient->GetFlags() & TextureFlags::RECYCLE));
MOZ_ASSERT(aClient->NeedsFenceHandle());
// Handle a case of fence delivery via ImageBridge.
// GrallocTextureData alwasys requests fence delivery if ANDROID_VERSION >= 17.
ImageBridgeChild::GetSingleton()->HoldUntilFenceHandleDelivery(aClient, GetFwdTransactionId());
}
void
CompositorBridgeChild::NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId)
{
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
if (!client) {
return;
}
if (aFwdTransactionId < client->GetLastFwdTransactionId()) {
// Released on host side, but client already requested newer use texture.
return;
}
mTexturesWaitingRecycled.Remove(aTextureId);
}
void
CompositorBridgeChild::DeliverFence(uint64_t aTextureId, FenceHandle& aReleaseFenceHandle)
{
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
if (!client) {
return;
}
client->SetReleaseFenceHandle(aReleaseFenceHandle);
}
void
CompositorBridgeChild::CancelWaitForRecycle(uint64_t aTextureId)
{
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
if (!client) {
return;
}
mTexturesWaitingRecycled.Remove(aTextureId);
}
} // namespace layers
} // namespace mozilla

View File

@ -31,10 +31,13 @@ using mozilla::dom::TabChild;
class ClientLayerManager;
class CompositorBridgeParent;
class TextureClient;
struct FrameMetrics;
class CompositorBridgeChild final : public PCompositorBridgeChild
{
typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(CompositorBridgeChild)
public:
@ -98,10 +101,14 @@ public:
virtual PTextureChild* AllocPTextureChild(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags,
const uint64_t& aId) override;
const uint64_t& aId,
const uint64_t& aSerial) override;
virtual bool DeallocPTextureChild(PTextureChild* actor) override;
virtual bool
RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
/**
* Request that the parent tell us when graphics are ready on GPU.
* When we get that message, we bounce it to the TabParent via
@ -140,6 +147,25 @@ public:
static void ShutDown();
void UpdateFwdTransactionId() { ++mFwdTransactionId; }
uint64_t GetFwdTransactionId() { return mFwdTransactionId; }
/**
* Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
* Host side's usage is checked via CompositableRef.
*/
void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);
/**
* Notify id of Texture When host side end its use. Transaction id is used to
* make sure if there is no newer usage.
*/
void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
void DeliverFence(uint64_t aTextureId, FenceHandle& aReleaseFenceHandle);
void CancelWaitForRecycle(uint64_t aTextureId);
private:
// Private destructor, to discourage deletion outside of Release():
virtual ~CompositorBridgeChild();
@ -211,6 +237,18 @@ private:
// True until the beginning of the two-step shutdown sequence of this actor.
bool mCanSend;
/**
* Transaction id of ShadowLayerForwarder.
* It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
*/
uint64_t mFwdTransactionId;
/**
* Hold TextureClients refs until end of their usages on host side.
* It defer calling of TextureClient recycle callback.
*/
nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingRecycled;
};
} // namespace layers

View File

@ -1815,7 +1815,7 @@ CompositorBridgeParent::RequestNotifyLayerTreeCleared(uint64_t aLayersId, Compos
*/
class CrossProcessCompositorBridgeParent final : public PCompositorBridgeParent,
public ShadowLayersManager,
public HostIPCAllocator,
public CompositorBridgeParentIPCAllocator,
public ShmemAllocator
{
friend class CompositorBridgeParent;
@ -1956,7 +1956,8 @@ public:
virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags,
const uint64_t& aId) override;
const uint64_t& aId,
const uint64_t& aSerial) override;
virtual bool DeallocPTextureParent(PTextureParent* actor) override;
@ -1979,6 +1980,13 @@ public:
return OtherPid();
}
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override
{
Unused << SendParentAsyncMessages(aMessage);
}
virtual CompositorBridgeParentIPCAllocator* AsCompositorBridgeParentIPCAllocator() override { return this; }
protected:
void OnChannelConnected(int32_t pid) override {
mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();
@ -2198,9 +2206,10 @@ PTextureParent*
CompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags,
const uint64_t& aId)
const uint64_t& aId,
const uint64_t& aSerial)
{
return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags);
return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial);
}
bool
@ -2231,6 +2240,12 @@ CompositorBridgeParent::DeallocShmem(ipc::Shmem& aShmem)
PCompositorBridgeParent::DeallocShmem(aShmem);
}
void
CompositorBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
{
Unused << SendParentAsyncMessages(aMessage);
}
bool
CompositorBridgeParent::IsSameProcess() const
{
@ -2763,7 +2778,8 @@ PTextureParent*
CrossProcessCompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags,
const uint64_t& aId)
const uint64_t& aId,
const uint64_t& aSerial)
{
CompositorBridgeParent::LayerTreeState* state = nullptr;
@ -2786,7 +2802,7 @@ CrossProcessCompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor&
gfxDevCrash(gfx::LogReason::PAllocTextureBackendMismatch) << "Texture backend is wrong";
}
return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags);
return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial);
}
bool

View File

@ -204,7 +204,7 @@ protected:
class CompositorBridgeParent final : public PCompositorBridgeParent,
public ShadowLayersManager,
public HostIPCAllocator,
public CompositorBridgeParentIPCAllocator,
public ShmemAllocator
{
friend class CompositorVsyncScheduler;
@ -288,7 +288,8 @@ public:
virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags,
const uint64_t& aId) override;
const uint64_t& aId,
const uint64_t& aSerial) override;
virtual bool DeallocPTextureParent(PTextureParent* actor) override;
virtual bool IsSameProcess() const override;
@ -309,6 +310,11 @@ public:
{
return OtherPid();
}
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
virtual CompositorBridgeParentIPCAllocator* AsCompositorBridgeParentIPCAllocator() override { return this; }
/**
* Request that the compositor be recreated due to a shared device reset.
* This must be called on the main thread, and blocks until a task posted

View File

@ -7,6 +7,9 @@
#include "ISurfaceAllocator.h"
#include "mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent
#include "mozilla/layers/TextureHost.h" // for TextureHost
namespace mozilla {
namespace layers {
@ -19,5 +22,111 @@ mozilla::ipc::SharedMemory::SharedMemoryType OptimalShmemType()
return ipc::SharedMemory::SharedMemoryType::TYPE_BASIC;
}
void
HostIPCAllocator::SendFenceHandleIfPresent(PTextureParent* aTexture)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
return;
}
if (!(texture->GetFlags() & TextureFlags::RECYCLE) &&
!texture->NeedsFenceHandle()) {
return;
}
uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
// Send a ReleaseFence of CompositorOGL.
FenceHandle fence = texture->GetCompositorReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(textureId, fence));
}
// Send a ReleaseFence that is set to TextureHost by HwcComposer2D.
fence = texture->GetAndResetReleaseFenceHandle();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(textureId, fence));
}
}
void
HostIPCAllocator::SendPendingAsyncMessages()
{
if (mPendingAsyncMessage.empty()) {
return;
}
// Some type of AsyncParentMessageData message could have
// one file descriptor (e.g. OpDeliverFence).
// A number of file descriptors per gecko ipc message have a limitation
// on OS_POSIX (MACOSX or LINUX).
#if defined(OS_POSIX)
static const uint32_t kMaxMessageNumber = FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE;
#else
// default number that works everywhere else
static const uint32_t kMaxMessageNumber = 250;
#endif
InfallibleTArray<AsyncParentMessageData> messages;
messages.SetCapacity(mPendingAsyncMessage.size());
for (size_t i = 0; i < mPendingAsyncMessage.size(); i++) {
messages.AppendElement(mPendingAsyncMessage[i]);
// Limit maximum number of messages.
if (messages.Length() >= kMaxMessageNumber) {
SendAsyncMessage(messages);
// Initialize Messages.
messages.Clear();
}
}
if (messages.Length() > 0) {
SendAsyncMessage(messages);
}
mPendingAsyncMessage.clear();
}
void
CompositorBridgeParentIPCAllocator::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
return;
}
if (!(texture->GetFlags() & TextureFlags::RECYCLE) &&
!texture->NeedsFenceHandle()) {
return;
}
if (texture->GetFlags() & TextureFlags::RECYCLE) {
SendFenceHandleIfPresent(aTexture);
uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
mPendingAsyncMessage.push_back(
OpNotifyNotUsed(textureId, aTransactionId));
return;
}
// Gralloc requests to deliver fence to client side.
// If client side does not use TextureFlags::RECYCLE flag,
// The fence can not be delivered via LayerTransactionParent.
// TextureClient might wait the fence delivery on main thread.
MOZ_ASSERT(ImageBridgeParent::GetInstance(GetChildProcessId()));
if (ImageBridgeParent::GetInstance(GetChildProcessId())) {
// Send message back via PImageBridge.
ImageBridgeParent::NotifyNotUsedToNonRecycle(
GetChildProcessId(),
aTexture,
aTransactionId);
} else {
NS_ERROR("ImageBridgeParent should exist");
}
if (!IsAboutToSendAsyncMessages()) {
SendPendingAsyncMessages();
}
}
} // namespace layers
} // namespace mozilla

View File

@ -123,6 +123,8 @@ public:
virtual MessageLoop * GetMessageLoop() const = 0;
virtual int32_t GetMaxTextureSize() const { return gfxPrefs::MaxTextureSize(); }
virtual void CancelWaitForRecycle(uint64_t aTextureId) = 0;
};
/// Methods that are specific to the host/parent side.
@ -135,8 +137,36 @@ public:
* Get child side's process Id.
*/
virtual base::ProcessId GetChildProcessId() = 0;
virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) = 0;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) = 0;
void SendFenceHandleIfPresent(PTextureParent* aTexture);
virtual void SendPendingAsyncMessages();
virtual void SetAboutToSendAsyncMessages()
{
mAboutToSendAsyncMessages = true;
}
bool IsAboutToSendAsyncMessages()
{
return mAboutToSendAsyncMessages;
}
protected:
std::vector<AsyncParentMessageData> mPendingAsyncMessage;
bool mAboutToSendAsyncMessages = false;
};
/// Specific to the CompositorBridgeParent/CrossProcessCompositorBridgeParent.
class CompositorBridgeParentIPCAllocator : public HostIPCAllocator
{
public:
virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
};
/// An allocator can provide shared memory.
///

View File

@ -195,6 +195,9 @@ ImageBridgeChild::UseTextures(CompositableClient* aCompositable,
fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
t.mTimeStamp, t.mPictureRect,
t.mFrameID, t.mProducerID, t.mInputFrameID));
// Wait end of usage on host side if TextureFlags::RECYCLE is set or GrallocTextureData case
HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
}
mTxn->AddNoSwapEdit(CompositableOperation(nullptr, aCompositable->GetIPDLActor(),
OpUseTexture(textures)));
@ -218,6 +221,9 @@ ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
aTextureOnBlack->SerializeReadLock(readLockB);
aTextureOnWhite->SerializeReadLock(readLockW);
HoldUntilCompositableRefReleasedIfNecessary(aTextureOnBlack);
HoldUntilCompositableRefReleasedIfNecessary(aTextureOnWhite);
mTxn->AddNoSwapEdit(
CompositableOperation(
nullptr,
@ -249,6 +255,127 @@ ImageBridgeChild::UseOverlaySource(CompositableClient* aCompositable,
}
#endif
void
ImageBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient)
{
// Wait ReleaseCompositableRef only when TextureFlags::RECYCLE is set on ImageBridge.
if (!aClient ||
!(aClient->GetFlags() & TextureFlags::RECYCLE)) {
return;
}
aClient->SetLastFwdTransactionId(GetFwdTransactionId());
mTexturesWaitingRecycled.Put(aClient->GetSerial(), aClient);
}
void
ImageBridgeChild::NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId)
{
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
if (!client) {
return;
}
if (aFwdTransactionId < client->GetLastFwdTransactionId()) {
// Released on host side, but client already requested newer use texture.
return;
}
mTexturesWaitingRecycled.Remove(aTextureId);
}
void
ImageBridgeChild::DeliverFence(uint64_t aTextureId, FenceHandle& aReleaseFenceHandle)
{
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
if (!client) {
return;
}
client->SetReleaseFenceHandle(aReleaseFenceHandle);
}
void
ImageBridgeChild::HoldUntilFenceHandleDelivery(TextureClient* aClient, uint64_t aTransactionId)
{
MOZ_ASSERT(NS_IsMainThread());
#ifdef MOZ_WIDGET_GONK
if (!aClient) {
return;
}
MutexAutoLock lock(mWaitingFenceHandleMutex);
aClient->SetLastFwdTransactionId(aTransactionId);
aClient->WaitFenceHandleOnImageBridge(mWaitingFenceHandleMutex);
mTexturesWaitingFenceHandle.Put(aClient->GetSerial(), aClient);
#else
NS_RUNTIMEABORT("not reached");
#endif
}
void
ImageBridgeChild::DeliverFenceToNonRecycle(uint64_t aTextureId, FenceHandle& aReleaseFenceHandle)
{
#ifdef MOZ_WIDGET_GONK
MutexAutoLock lock(mWaitingFenceHandleMutex);
TextureClient* client = mTexturesWaitingFenceHandle.Get(aTextureId).get();
if (!client) {
return;
}
MOZ_ASSERT(aTextureId == client->GetSerial());
client->SetReleaseFenceHandle(aReleaseFenceHandle);
#else
NS_RUNTIMEABORT("not reached");
#endif
}
void
ImageBridgeChild::NotifyNotUsedToNonRecycle(uint64_t aTextureId, uint64_t aTransactionId)
{
#ifdef MOZ_WIDGET_GONK
MutexAutoLock lock(mWaitingFenceHandleMutex);
RefPtr<TextureClient> client = mTexturesWaitingFenceHandle.Get(aTextureId);
if (!client) {
return;
}
if (aTransactionId < client->GetLastFwdTransactionId()) {
return;
}
MOZ_ASSERT(aTextureId == client->GetSerial());
client->ClearWaitFenceHandleOnImageBridge(mWaitingFenceHandleMutex);
mTexturesWaitingFenceHandle.Remove(aTextureId);
// Release TextureClient on allocator's message loop.
TextureClientReleaseTask* task = new TextureClientReleaseTask(client);
RefPtr<ClientIPCAllocator> allocator = client->GetAllocator();
client = nullptr;
allocator->AsClientAllocator()->GetMessageLoop()->PostTask(FROM_HERE, task);
#else
NS_RUNTIMEABORT("not reached");
#endif
}
void
ImageBridgeChild::CancelWaitFenceHandle(TextureClient* aClient)
{
#ifdef MOZ_WIDGET_GONK
MutexAutoLock lock(mWaitingFenceHandleMutex);
aClient->ClearWaitFenceHandleOnImageBridge(mWaitingFenceHandleMutex);
mTexturesWaitingFenceHandle.Remove(aClient->GetSerial());
#else
NS_RUNTIMEABORT("not reached");
#endif
}
void
ImageBridgeChild::CancelWaitForRecycle(uint64_t aTextureId)
{
MOZ_ASSERT(InImageBridgeChildThread());
RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
if (!client) {
return;
}
mTexturesWaitingRecycled.Remove(aTextureId);
}
// Singleton
static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
@ -355,6 +482,10 @@ static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * par
ImageBridgeChild::ImageBridgeChild()
: mShuttingDown(false)
, mFwdTransactionId(0)
#ifdef MOZ_WIDGET_GONK
, mWaitingFenceHandleMutex("ImageBridgeChild::mWaitingFenceHandleMutex")
#endif
{
MOZ_ASSERT(NS_IsMainThread());
@ -378,6 +509,9 @@ void
ImageBridgeChild::MarkShutDown()
{
MOZ_ASSERT(!mShuttingDown);
mTexturesWaitingRecycled.Clear();
mTrackersHolder.DestroyAsyncTransactionTrackersHolder();
mShuttingDown = true;
}
@ -720,6 +854,7 @@ ImageBridgeChild::BeginTransaction()
{
MOZ_ASSERT(!mShuttingDown);
MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
UpdateFwdTransactionId();
mTxn->Begin();
}
@ -748,7 +883,7 @@ ImageBridgeChild::EndTransaction()
AutoTArray<EditReply, 10> replies;
if (mTxn->mSwapRequired) {
if (!SendUpdate(cset, mTxn->mDestroyedActors, &replies)) {
if (!SendUpdate(cset, mTxn->mDestroyedActors, GetFwdTransactionId(), &replies)) {
NS_WARNING("could not send async texture transaction");
mTxn->FallbackDestroyActors();
return;
@ -756,7 +891,7 @@ ImageBridgeChild::EndTransaction()
} else {
// If we don't require a swap we can call SendUpdateNoSwap which
// assumes that aReplies is empty (DEBUG assertion)
if (!SendUpdateNoSwap(cset, mTxn->mDestroyedActors)) {
if (!SendUpdateNoSwap(cset, mTxn->mDestroyedActors, GetFwdTransactionId())) {
NS_WARNING("could not send async texture transaction (no swap)");
mTxn->FallbackDestroyActors();
return;
@ -765,7 +900,6 @@ ImageBridgeChild::EndTransaction()
for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
NS_RUNTIMEABORT("not reached");
}
SendPendingAsyncMessges();
}
void
@ -1093,7 +1227,8 @@ ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
PTextureChild*
ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
const LayersBackend&,
const TextureFlags&)
const TextureFlags&,
const uint64_t& aSerial)
{
MOZ_ASSERT(!mShuttingDown);
return TextureClient::CreateIPDLActor();
@ -1145,28 +1280,40 @@ ImageBridgeChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageDat
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = message.get_OpDeliverFence();
FenceHandle fence = op.fence();
PTextureChild* child = op.textureChild();
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
if (texture) {
texture->SetReleaseFenceHandle(fence);
}
DeliverFence(op.TextureId(), fence);
break;
}
case AsyncParentMessageData::TOpDeliverFenceToTracker: {
const OpDeliverFenceToTracker& op = message.get_OpDeliverFenceToTracker();
FenceHandle fence = op.fence();
case AsyncParentMessageData::TOpDeliverFenceToNonRecycle: {
// Notify ReleaseCompositableRef to a TextureClient that belongs to
// LayerTransactionChild. It is used only on gonk to deliver fence to
// a TextureClient that does not have TextureFlags::RECYCLE.
// In this case, LayerTransactionChild's ipc could not be used to deliver fence.
AsyncTransactionTrackersHolder::SetReleaseFenceHandle(fence,
op.destHolderId(),
op.destTransactionId());
const OpDeliverFenceToNonRecycle& op = message.get_OpDeliverFenceToNonRecycle();
FenceHandle fence = op.fence();
DeliverFenceToNonRecycle(op.TextureId(), fence);
break;
}
case AsyncParentMessageData::TOpNotifyNotUsed: {
const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed();
NotifyNotUsed(op.TextureId(), op.fwdTransactionId());
break;
}
case AsyncParentMessageData::TOpNotifyNotUsedToNonRecycle: {
// Notify ReleaseCompositableRef to a TextureClient that belongs to
// LayerTransactionChild. It is used only on gonk to deliver fence to
// a TextureClient that does not have TextureFlags::RECYCLE.
// In this case, LayerTransactionChild's ipc could not be used to deliver fence.
const OpNotifyNotUsedToNonRecycle& op = message.get_OpNotifyNotUsedToNonRecycle();
NotifyNotUsedToNonRecycle(op.TextureId(), op.fwdTransactionId());
break;
}
case AsyncParentMessageData::TOpReplyRemoveTexture: {
const OpReplyRemoveTexture& op = message.get_OpReplyRemoveTexture();
AsyncTransactionTrackersHolder::TransactionCompleteted(op.holderId(),
op.transactionId());
MOZ_ASSERT(mTrackersHolder.GetId() == op.holderId());
mTrackersHolder.TransactionCompleteted(op.transactionId());
break;
}
default:
@ -1189,10 +1336,11 @@ ImageBridgeChild::RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&
PTextureChild*
ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags)
TextureFlags aFlags,
uint64_t aSerial)
{
MOZ_ASSERT(!mShuttingDown);
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags);
return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
}
static bool
@ -1263,15 +1411,14 @@ ImageBridgeChild::RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aA
CompositableOperation op(
nullptr, aCompositable->GetIPDLActor(),
OpRemoveTextureAsync(
CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
mTrackersHolder.GetId(),
aAsyncTransactionTracker->GetId(),
nullptr, aCompositable->GetIPDLActor(),
nullptr, aTexture->GetIPDLActor()));
mTxn->AddNoSwapEdit(op);
// Hold AsyncTransactionTracker until receving reply
CompositableClient::HoldUntilComplete(aCompositable->GetIPDLActor(),
aAsyncTransactionTracker);
mTrackersHolder.HoldUntilComplete(aAsyncTransactionTracker);
}
bool ImageBridgeChild::IsSameProcess() const
@ -1279,9 +1426,5 @@ bool ImageBridgeChild::IsSameProcess() const
return OtherPid() == base::GetCurrentProcId();
}
void ImageBridgeChild::SendPendingAsyncMessges()
{
}
} // namespace layers
} // namespace mozilla

View File

@ -17,6 +17,7 @@
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/PImageBridgeChild.h"
#include "mozilla/Mutex.h"
#include "nsDebug.h" // for NS_RUNTIMEABORT
#include "nsRegion.h" // for nsIntRegion
#include "mozilla/gfx/Rect.h"
@ -104,7 +105,6 @@ bool InImageBridgeChildThread();
*/
class ImageBridgeChild final : public PImageBridgeChild
, public CompositableForwarder
, public AsyncTransactionTrackersHolder
, public ShmemAllocator
{
friend class ImageContainer;
@ -200,7 +200,7 @@ public:
~ImageBridgeChild();
virtual PTextureChild*
AllocPTextureChild(const SurfaceDescriptor& aSharedData, const LayersBackend& aLayersBackend, const TextureFlags& aFlags) override;
AllocPTextureChild(const SurfaceDescriptor& aSharedData, const LayersBackend& aLayersBackend, const TextureFlags& aFlags, const uint64_t& aSerial) override;
virtual bool
DeallocPTextureChild(PTextureChild* actor) override;
@ -265,6 +265,30 @@ public:
const nsIntRect& aPictureRect) override;
#endif
/**
* Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
* Host side's usage is checked via CompositableRef.
*/
void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);
/**
* Notify id of Texture When host side end its use. Transaction id is used to
* make sure if there is no newer usage.
*/
void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
void DeliverFence(uint64_t aTextureId, FenceHandle& aReleaseFenceHandle);
void HoldUntilFenceHandleDelivery(TextureClient* aClient, uint64_t aTransactionId);
void DeliverFenceToNonRecycle(uint64_t aTextureId, FenceHandle& aReleaseFenceHandle);
void NotifyNotUsedToNonRecycle(uint64_t aTextureId, uint64_t aTransactionId);
void CancelWaitFenceHandle(TextureClient* aClient);
virtual void CancelWaitForRecycle(uint64_t aTextureId) override;
virtual bool DestroyInTransaction(PTextureChild* aTexture, bool synchronously) override;
virtual bool DestroyInTransaction(PCompositableChild* aCompositable, bool synchronously) override;
@ -312,11 +336,13 @@ public:
virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags) override;
TextureFlags aFlags,
uint64_t aSerial) override;
virtual bool IsSameProcess() const override;
virtual void SendPendingAsyncMessges() override;
virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; }
virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; }
void MarkShutDown();
@ -331,6 +357,25 @@ protected:
CompositableTransaction* mTxn;
Atomic<bool> mShuttingDown;
static Atomic<bool> sIsShutDown;
/**
* Transaction id of CompositableForwarder.
* It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
*/
uint64_t mFwdTransactionId;
/**
* Hold TextureClients refs until end of their usages on host side.
* It defer calling of TextureClient recycle callback.
*/
nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingRecycled;
AsyncTransactionTrackersHolder mTrackersHolder;
#ifdef MOZ_WIDGET_GONK
Mutex mWaitingFenceHandleMutex;
nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingFenceHandle;
#endif
};
} // namespace layers

View File

@ -134,7 +134,10 @@ public:
explicit AutoImageBridgeParentAsyncMessageSender(ImageBridgeParent* aImageBridge,
InfallibleTArray<OpDestroy>* aToDestroy = nullptr)
: mImageBridge(aImageBridge)
, mToDestroy(aToDestroy) {}
, mToDestroy(aToDestroy)
{
mImageBridge->SetAboutToSendAsyncMessages();
}
~AutoImageBridgeParentAsyncMessageSender()
{
@ -152,9 +155,11 @@ private:
bool
ImageBridgeParent::RecvUpdate(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
const uint64_t& aFwdTransactionId,
EditReplyArray* aReply)
{
AutoImageBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
UpdateFwdTransactionId(aFwdTransactionId);
EditReplyVector replyv;
for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) {
@ -179,10 +184,11 @@ ImageBridgeParent::RecvUpdate(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
}
bool
ImageBridgeParent::RecvUpdateNoSwap(EditArray&& aEdits, OpDestroyArray&& aToDestroy)
ImageBridgeParent::RecvUpdateNoSwap(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
const uint64_t& aFwdTransactionId)
{
InfallibleTArray<EditReply> noReplies;
bool success = RecvUpdate(Move(aEdits), Move(aToDestroy), &noReplies);
bool success = RecvUpdate(Move(aEdits), Move(aToDestroy), aFwdTransactionId, &noReplies);
MOZ_ASSERT(noReplies.Length() == 0, "RecvUpdateNoSwap requires a sync Update to carry Edits");
return success;
}
@ -251,9 +257,10 @@ bool ImageBridgeParent::DeallocPCompositableParent(PCompositableParent* aActor)
PTextureParent*
ImageBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags)
const TextureFlags& aFlags,
const uint64_t& aSerial)
{
return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags);
return TextureHost::CreateIPDLActor(this, aSharedData, aLayersBackend, aFlags, aSerial);
}
bool
@ -295,12 +302,6 @@ ImageBridgeParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageDat
mozilla::Unused << SendParentAsyncMessages(aMessage);
}
bool
ImageBridgeParent::RecvChildAsyncMessages(InfallibleTArray<AsyncChildMessageData>&& aMessages)
{
return true;
}
class ProcessIdComparator
{
public:
@ -335,6 +336,7 @@ ImageBridgeParent::NotifyImageComposites(nsTArray<ImageCompositeNotification>& a
notifications.AppendElement(aNotifications[end]);
++end;
}
GetInstance(pid)->SendPendingAsyncMessages();
if (!GetInstance(pid)->SendDidComposite(notifications)) {
ok = false;
}
@ -427,80 +429,76 @@ ImageBridgeParent::ReplyRemoveTexture(const OpReplyRemoveTexture& aReply)
mPendingAsyncMessage.push_back(aReply);
}
/*static*/ void
ImageBridgeParent::ReplyRemoveTexture(base::ProcessId aChildProcessId,
const OpReplyRemoveTexture& aReply)
{
ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
if (!imageBridge) {
return;
}
imageBridge->ReplyRemoveTexture(aReply);
}
void
ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture)
ImageBridgeParent::SendFenceHandleToNonRecycle(PTextureParent* aTexture)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture || !texture->NeedsFenceHandle()) {
if (!texture) {
return;
}
if (!(texture->GetFlags() & TextureFlags::RECYCLE) &&
!texture->NeedsFenceHandle()) {
return;
}
uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
// Send a ReleaseFence of CompositorOGL.
FenceHandle fence = texture->GetCompositorReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
mPendingAsyncMessage.push_back(OpDeliverFenceToNonRecycle(textureId, fence));
}
// Send a ReleaseFence that is set to TextureHost by HwcComposer2D.
fence = texture->GetAndResetReleaseFenceHandle();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
mPendingAsyncMessage.push_back(OpDeliverFenceToNonRecycle(textureId, fence));
}
}
void
ImageBridgeParent::AppendDeliverFenceMessage(uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture)
ImageBridgeParent::NotifyNotUsedToNonRecycle(PTextureParent* aTexture,
uint64_t aTransactionId)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture || !texture->NeedsFenceHandle()) {
if (!texture) {
return;
}
// Send a ReleaseFence of CompositorOGL.
FenceHandle fence = texture->GetCompositorReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId,
aTransactionId,
fence));
if (!(texture->GetFlags() & TextureFlags::RECYCLE) &&
!texture->NeedsFenceHandle()) {
return;
}
// Send a ReleaseFence that is set to TextureHost by HwcComposer2D.
fence = texture->GetAndResetReleaseFenceHandle();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(aDestHolderId,
aTransactionId,
fence));
}
SendFenceHandleToNonRecycle(aTexture);
uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
mPendingAsyncMessage.push_back(
OpNotifyNotUsedToNonRecycle(textureId, aTransactionId));
}
/*static*/ void
ImageBridgeParent::AppendDeliverFenceMessage(base::ProcessId aChildProcessId,
uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture)
ImageBridgeParent::NotifyNotUsedToNonRecycle(base::ProcessId aChildProcessId,
PTextureParent* aTexture,
uint64_t aTransactionId)
{
ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
if (!imageBridge) {
return;
}
imageBridge->AppendDeliverFenceMessage(aDestHolderId,
aTransactionId,
aTexture);
imageBridge->NotifyNotUsedToNonRecycle(aTexture, aTransactionId);
}
/*static*/ void
ImageBridgeParent::SetAboutToSendAsyncMessages(base::ProcessId aChildProcessId)
{
ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
if (!imageBridge) {
return;
}
imageBridge->SetAboutToSendAsyncMessages();
}
/*static*/ void
@ -513,5 +511,28 @@ ImageBridgeParent::SendPendingAsyncMessages(base::ProcessId aChildProcessId)
imageBridge->SendPendingAsyncMessages();
}
void
ImageBridgeParent::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture) {
return;
}
if (!(texture->GetFlags() & TextureFlags::RECYCLE) &&
!texture->NeedsFenceHandle()) {
return;
}
SendFenceHandleIfPresent(aTexture);
uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
mPendingAsyncMessage.push_back(
OpNotifyNotUsed(textureId, aTransactionId));
if (!IsAboutToSendAsyncMessages()) {
SendPendingAsyncMessages();
}
}
} // namespace layers
} // namespace mozilla

View File

@ -46,7 +46,6 @@ public:
typedef InfallibleTArray<CompositableOperation> EditArray;
typedef InfallibleTArray<OpDestroy> OpDestroyArray;
typedef InfallibleTArray<EditReply> EditReplyArray;
typedef InfallibleTArray<AsyncChildMessageData> AsyncChildMessageArray;
ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport, ProcessId aChildProcessId);
~ImageBridgeParent();
@ -59,10 +58,10 @@ public:
Create(Transport* aTransport, ProcessId aChildProcessId, ipc::GeckoChildProcessHost* aProcessHost);
// CompositableParentManager
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) override;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
virtual base::ProcessId GetChildProcessId() override
{
return OtherPid();
@ -71,8 +70,10 @@ public:
// PImageBridge
virtual bool RecvImageBridgeThreadId(const PlatformThreadId& aThreadId) override;
virtual bool RecvUpdate(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
const uint64_t& aFwdTransactionId,
EditReplyArray* aReply) override;
virtual bool RecvUpdateNoSwap(EditArray&& aEdits, OpDestroyArray&& aToDestroy) override;
virtual bool RecvUpdateNoSwap(EditArray&& aEdits, OpDestroyArray&& aToDestroy,
const uint64_t& aFwdTransactionId) override;
PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo,
PImageContainerParent* aImageContainer,
@ -81,7 +82,8 @@ public:
virtual PTextureParent* AllocPTextureParent(const SurfaceDescriptor& aSharedData,
const LayersBackend& aLayersBackend,
const TextureFlags& aFlags) override;
const TextureFlags& aFlags,
const uint64_t& aSerial) override;
virtual bool DeallocPTextureParent(PTextureParent* actor) override;
PMediaSystemResourceManagerParent* AllocPMediaSystemResourceManagerParent() override;
@ -89,9 +91,6 @@ public:
virtual PImageContainerParent* AllocPImageContainerParent() override;
virtual bool DeallocPImageContainerParent(PImageContainerParent* actor) override;
virtual bool
RecvChildAsyncMessages(InfallibleTArray<AsyncChildMessageData>&& aMessages) override;
// Shutdown step 1
virtual bool RecvWillClose() override;
@ -113,17 +112,17 @@ public:
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) override;
static void ReplyRemoveTexture(base::ProcessId aChildProcessId,
const OpReplyRemoveTexture& aReply);
void SendFenceHandleToNonRecycle(PTextureParent* aTexture);
void AppendDeliverFenceMessage(uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture);
void NotifyNotUsedToNonRecycle(PTextureParent* aTexture,
uint64_t aTransactionId);
static void AppendDeliverFenceMessage(base::ProcessId aChildProcessId,
uint64_t aDestHolderId,
uint64_t aTransactionId,
PTextureParent* aTexture);
static void NotifyNotUsedToNonRecycle(base::ProcessId aChildProcessId,
PTextureParent* aTexture,
uint64_t aTransactionId);
using CompositableParentManager::SetAboutToSendAsyncMessages;
static void SetAboutToSendAsyncMessages(base::ProcessId aChildProcessId);
using CompositableParentManager::SendPendingAsyncMessages;
static void SendPendingAsyncMessages(base::ProcessId aChildProcessId);

View File

@ -69,44 +69,10 @@ LayerTransactionChild::DeallocPCompositableChild(PCompositableChild* actor)
return CompositableClient::DestroyIPDLActor(actor);
}
bool
LayerTransactionChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
{
for (AsyncParentMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncParentMessageData& message = aMessages[i];
switch (message.type()) {
case AsyncParentMessageData::TOpDeliverFence: {
const OpDeliverFence& op = message.get_OpDeliverFence();
FenceHandle fence = op.fence();
PTextureChild* child = op.textureChild();
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
if (texture) {
texture->SetReleaseFenceHandle(fence);
}
break;
}
case AsyncParentMessageData::TOpReplyRemoveTexture: {
const OpReplyRemoveTexture& op = message.get_OpReplyRemoveTexture();
AsyncTransactionTrackersHolder::TransactionCompleteted(op.holderId(),
op.transactionId());
break;
}
default:
NS_ERROR("unknown AsyncParentMessageData type");
return false;
}
}
return true;
}
void
LayerTransactionChild::ActorDestroy(ActorDestroyReason why)
{
mDestroyed = true;
DestroyAsyncTransactionTrackersHolder();
#ifdef MOZ_B2G
// Due to poor lifetime management of gralloc (and possibly shmems) we will
// crash at some point in the future when we get destroyed due to abnormal

View File

@ -26,9 +26,7 @@ namespace layers {
class ShadowLayerForwarder;
class LayerTransactionChild : public PLayerTransactionChild
, public AsyncTransactionTrackersHolder
{
typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LayerTransactionChild)
/**
@ -65,9 +63,6 @@ protected:
virtual PCompositableChild* AllocPCompositableChild(const TextureInfo& aInfo) override;
virtual bool DeallocPCompositableChild(PCompositableChild* actor) override;
virtual bool
RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
virtual void ActorDestroy(ActorDestroyReason why) override;
void AddIPDLReference() {

View File

@ -184,6 +184,7 @@ LayerTransactionParent::Destroy()
bool
LayerTransactionParent::RecvUpdateNoSwap(InfallibleTArray<Edit>&& cset,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const TargetConfig& targetConfig,
PluginsArray&& aPlugins,
@ -194,7 +195,7 @@ LayerTransactionParent::RecvUpdateNoSwap(InfallibleTArray<Edit>&& cset,
const mozilla::TimeStamp& aTransactionStart,
const int32_t& aPaintSyncId)
{
return RecvUpdate(Move(cset), Move(aToDestroy),
return RecvUpdate(Move(cset), Move(aToDestroy), aFwdTransactionId,
aTransactionId, targetConfig, Move(aPlugins), isFirstPaint,
scheduleComposite, paintSequenceNumber, isRepeatTransaction,
aTransactionStart, aPaintSyncId, nullptr);
@ -207,7 +208,10 @@ public:
InfallibleTArray<OpDestroy>* aDestroyActors = nullptr)
: mLayerTransaction(aLayerTransaction)
, mActorsToDestroy(aDestroyActors)
{}
{
mLayerTransaction->SetAboutToSendAsyncMessages();
ImageBridgeParent::SetAboutToSendAsyncMessages(mLayerTransaction->GetChildProcessId());
}
~AutoLayerTransactionParentAsyncMessageSender()
{
@ -229,6 +233,7 @@ private:
bool
LayerTransactionParent::RecvUpdate(InfallibleTArray<Edit>&& cset,
InfallibleTArray<OpDestroy>&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const TargetConfig& targetConfig,
PluginsArray&& aPlugins,
@ -250,6 +255,8 @@ LayerTransactionParent::RecvUpdate(InfallibleTArray<Edit>&& cset,
MOZ_LAYERS_LOG(("[ParentSide] received txn with %d edits", cset.Length()));
UpdateFwdTransactionId(aFwdTransactionId);
if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
for (const auto& op : aToDestroy) {
DestroyActor(op);
@ -981,57 +988,6 @@ LayerTransactionParent::DeallocPCompositableParent(PCompositableParent* aActor)
return CompositableHost::DestroyIPDLActor(aActor);
}
bool
LayerTransactionParent::RecvChildAsyncMessages(InfallibleTArray<AsyncChildMessageData>&& aMessages)
{
AutoLayerTransactionParentAsyncMessageSender autoAsyncMessageSender(this);
for (AsyncChildMessageArray::index_type i = 0; i < aMessages.Length(); ++i) {
const AsyncChildMessageData& message = aMessages[i];
switch (message.type()) {
case AsyncChildMessageData::TCompositableOperation: {
const CompositableOperation& compositable_op =
message.get_CompositableOperation();
MOZ_ASSERT(compositable_op.detail().type() ==
CompositableOperationDetail::TOpRemoveTextureAsync);
const OpRemoveTextureAsync& op =
compositable_op.detail().get_OpRemoveTextureAsync();
CompositableHost* compositable = CompositableHost::FromIPDLActor(op.compositableParent());
RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
MOZ_ASSERT(tex.get());
compositable->RemoveTextureHost(tex);
MOZ_ASSERT(ImageBridgeParent::GetInstance(GetChildProcessId()));
if (ImageBridgeParent::GetInstance(GetChildProcessId())) {
// send FenceHandle if present via ImageBridge.
ImageBridgeParent::AppendDeliverFenceMessage(
GetChildProcessId(),
op.holderId(),
op.transactionId(),
op.textureParent());
// Send message back via PImageBridge.
ImageBridgeParent::ReplyRemoveTexture(
GetChildProcessId(),
OpReplyRemoveTexture(op.holderId(),
op.transactionId()));
} else {
NS_ERROR("ImageBridgeParent should exist");
}
break;
}
default:
NS_ERROR("unknown AsyncChildMessageData type");
return false;
}
}
return true;
}
void
LayerTransactionParent::ActorDestroy(ActorDestroyReason why)
{
@ -1074,41 +1030,28 @@ bool LayerTransactionParent::IsSameProcess() const
return OtherPid() == base::GetCurrentProcId();
}
void
LayerTransactionParent::SendFenceHandleIfPresent(PTextureParent* aTexture)
{
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
if (!texture || !texture->NeedsFenceHandle()) {
return;
}
// Send a ReleaseFence of CompositorOGL.
FenceHandle fence = texture->GetCompositorReleaseFence();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
}
// Send a ReleaseFence that is set to TextureHost by HwcComposer2D.
fence = texture->GetAndResetReleaseFenceHandle();
if (fence.IsValid()) {
mPendingAsyncMessage.push_back(OpDeliverFence(aTexture, nullptr,
fence));
}
}
void
LayerTransactionParent::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
{
mozilla::Unused << SendParentAsyncMessages(aMessage);
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
void
LayerTransactionParent::ReplyRemoveTexture(const OpReplyRemoveTexture& aReply)
LayerTransactionParent::SendPendingAsyncMessages()
{
InfallibleTArray<AsyncParentMessageData> messages;
messages.AppendElement(aReply);
mozilla::Unused << SendParentAsyncMessages(messages);
mShadowLayersManager->AsCompositorBridgeParentIPCAllocator()->SendPendingAsyncMessages();
}
void
LayerTransactionParent::SetAboutToSendAsyncMessages()
{
mShadowLayersManager->AsCompositorBridgeParentIPCAllocator()->SetAboutToSendAsyncMessages();
}
void
LayerTransactionParent::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
{
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
}
} // namespace layers

View File

@ -42,7 +42,6 @@ class LayerTransactionParent final : public PLayerTransactionParent,
typedef InfallibleTArray<Edit> EditArray;
typedef InfallibleTArray<OpDestroy> OpDestroyArray;
typedef InfallibleTArray<EditReply> EditReplyArray;
typedef InfallibleTArray<AsyncChildMessageData> AsyncChildMessageArray;
typedef InfallibleTArray<PluginWindowData> PluginsArray;
public:
@ -79,17 +78,19 @@ public:
void SetPendingTransactionId(uint64_t aId) { mPendingTransaction = aId; }
// CompositableParentManager
virtual void SendFenceHandleIfPresent(PTextureParent* aTexture) override;
virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
virtual void SendPendingAsyncMessages() override;
virtual void SetAboutToSendAsyncMessages() override;
virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
virtual base::ProcessId GetChildProcessId() override
{
return OtherPid();
}
virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) override;
void AddPendingCompositorUpdate() {
mPendingCompositorUpdates++;
}
@ -110,6 +111,7 @@ protected:
virtual bool RecvUpdate(EditArray&& cset,
OpDestroyArray&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const TargetConfig& targetConfig,
PluginsArray&& aPlugins,
@ -123,6 +125,7 @@ protected:
virtual bool RecvUpdateNoSwap(EditArray&& cset,
OpDestroyArray&& aToDestroy,
const uint64_t& aFwdTransactionId,
const uint64_t& aTransactionId,
const TargetConfig& targetConfig,
PluginsArray&& aPlugins,
@ -158,9 +161,6 @@ protected:
virtual PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo) override;
virtual bool DeallocPCompositableParent(PCompositableParent* actor) override;
virtual bool
RecvChildAsyncMessages(InfallibleTArray<AsyncChildMessageData>&& aMessages) override;
virtual void ActorDestroy(ActorDestroyReason why) override;
bool Attach(ShadowLayerParent* aLayerParent,

View File

@ -431,16 +431,25 @@ union MaybeRegion {
};
struct OpDeliverFence {
PTexture texture;
uint64_t TextureId;
FenceHandle fence;
};
struct OpDeliverFenceToTracker {
uint64_t destHolderId;
uint64_t destTransactionId;
struct OpDeliverFenceToNonRecycle {
uint64_t TextureId;
FenceHandle fence;
};
struct OpNotifyNotUsed {
uint64_t TextureId;
uint64_t fwdTransactionId;
};
struct OpNotifyNotUsedToNonRecycle {
uint64_t TextureId;
uint64_t fwdTransactionId;
};
union CompositableOperationDetail {
OpPaintTextureRegion;
@ -521,13 +530,11 @@ union EditReply {
union AsyncParentMessageData {
OpDeliverFence;
OpDeliverFenceToTracker;
OpDeliverFenceToNonRecycle;
OpNotifyNotUsed;
OpNotifyNotUsedToNonRecycle;
OpReplyRemoveTexture;
};
union AsyncChildMessageData {
CompositableOperation;
};
} // namespace
} // namespace

View File

@ -100,6 +100,8 @@ child:
*/
async ClearCachedResources(uint64_t id);
async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
parent:
/**
* Confirmation callback for UpdatePluginConfigurations and HideAllPlugins.
@ -192,7 +194,7 @@ parent:
ScrollableLayerGuid guid,
CSSIntRegion region);
async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t id);
async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t id, uint64_t aSerial);
child:
// Send back Compositor Frame Metrics from APZCs so tiled layers can

View File

@ -42,10 +42,10 @@ child:
parent:
async ImageBridgeThreadId(PlatformThreadId aTreahdId);
sync Update(CompositableOperation[] ops, OpDestroy[] toDestroy)
sync Update(CompositableOperation[] ops, OpDestroy[] toDestroy, uint64_t fwdTransactionId)
returns (EditReply[] reply);
async UpdateNoSwap(CompositableOperation[] ops, OpDestroy[] toDestroy);
async UpdateNoSwap(CompositableOperation[] ops, OpDestroy[] toDestroy, uint64_t fwdTransactionId);
// First step of the destruction sequence. This puts ImageBridge
// in a state in which it can't send asynchronous messages
@ -58,11 +58,10 @@ parent:
sync PCompositable(TextureInfo aInfo,
nullable PImageContainer aImageContainer) returns (uint64_t id);
async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags);
async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t aSerial);
async PMediaSystemResourceManager();
async PImageContainer();
async ChildAsyncMessages(AsyncChildMessageData[] aMessages);
};

View File

@ -43,9 +43,6 @@ sync protocol PLayerTransaction {
manages PLayer;
manages PCompositable;
child:
async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
parent:
async PLayer();
async PCompositable(TextureInfo aTextureInfo);
@ -53,6 +50,7 @@ parent:
// The isFirstPaint flag can be used to indicate that this is the first update
// for a particular document.
sync Update(Edit[] cset, OpDestroy[] toDestroy,
uint64_t fwdTransactionId,
uint64_t id, TargetConfig targetConfig,
PluginWindowData[] plugins, bool isFirstPaint,
bool scheduleComposite, uint32_t paintSequenceNumber,
@ -63,6 +61,7 @@ parent:
// We don't need to send a sync transaction if
// no transaction operate require a swap.
async UpdateNoSwap(Edit[] cset, OpDestroy[] toDestroy,
uint64_t fwdTransactionId,
uint64_t id, TargetConfig targetConfig,
PluginWindowData[] plugins, bool isFirstPaint,
bool scheduleComposite, uint32_t paintSequenceNumber,
@ -117,8 +116,6 @@ parent:
// input event.
async SetConfirmedTargetAPZC(uint64_t aInputBlockId, ScrollableLayerGuid[] aTargets);
async ChildAsyncMessages(AsyncChildMessageData[] aMessages);
async Shutdown();
sync SyncWithCompositor();

View File

@ -26,12 +26,7 @@ sync protocol PTexture {
child:
async __delete__();
async CompositorRecycle();
parent:
async ClientRecycle();
/**
* Asynchronously tell the compositor side to remove the texture.
*/

View File

@ -5,6 +5,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ClientLayerManager.h" // for ClientLayerManager
#include "ShadowLayers.h"
#include <set> // for _Rb_tree_const_iterator, etc
#include <vector> // for vector
@ -23,6 +24,7 @@
#include "mozilla/layers/CompositableClient.h" // for CompositableClient, etc
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/LayersMessages.h" // for Edit, etc
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
@ -382,8 +384,9 @@ CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIden
mSyncObject = SyncObject::CreateSyncObject(aIdentifier.mSyncHandle);
}
ShadowLayerForwarder::ShadowLayerForwarder()
: mMessageLoop(MessageLoop::current())
ShadowLayerForwarder::ShadowLayerForwarder(ClientLayerManager* aClientLayerManager)
: mClientLayerManager(aClientLayerManager)
, mMessageLoop(MessageLoop::current())
, mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
, mIsFirstPaint(false)
, mWindowOverlayChanged(false)
@ -417,6 +420,7 @@ ShadowLayerForwarder::BeginTransaction(const gfx::IntRect& aTargetBounds,
{
MOZ_ASSERT(HasShadowManager(), "no manager to forward to");
MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
UpdateFwdTransactionId();
mTxn->Begin(aTargetBounds, aRotation, aOrientation);
}
@ -563,6 +567,24 @@ ShadowLayerForwarder::UseTiledLayerBuffer(CompositableClient* aCompositable,
{
MOZ_ASSERT(aCompositable && aCompositable->IsConnected());
#ifdef MOZ_WIDGET_GONK
// GrallocTextureData alwasys requests fence delivery if ANDROID_VERSION >= 17.
const InfallibleTArray<TileDescriptor>& tileDescriptors = aTileLayerDescriptor.tiles();
for (size_t i = 0; i < tileDescriptors.Length(); i++) {
const TileDescriptor& tileDesc = tileDescriptors[i];
if (tileDesc.type() != TileDescriptor::TTexturedTileDescriptor) {
continue;
}
const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(texturedDesc.textureChild());
mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(texture);
if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureChild) {
texture = TextureClient::AsTextureClient(texturedDesc.textureOnWhite().get_PTextureChild());
mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(texture);
}
}
#endif
mTxn->AddNoSwapPaint(CompositableOperation(nullptr, aCompositable->GetIPDLActor(),
OpUseTiledLayerBuffer(aTileLayerDescriptor)));
}
@ -609,6 +631,7 @@ ShadowLayerForwarder::UseTextures(CompositableClient* aCompositable,
// to be synchronous.
mTxn->MarkSyncTransaction();
}
mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
}
mTxn->AddEdit(CompositableOperation(nullptr, aCompositable->GetIPDLActor(),
OpUseTexture(textures)));
@ -633,6 +656,9 @@ ShadowLayerForwarder::UseComponentAlphaTextures(CompositableClient* aCompositabl
aTextureOnBlack->SerializeReadLock(readLockB);
aTextureOnWhite->SerializeReadLock(readLockW);
mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnBlack);
mClientLayerManager->GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnWhite);
mTxn->AddEdit(
CompositableOperation(
nullptr, aCompositable->GetIPDLActor(),
@ -712,29 +738,7 @@ ShadowLayerForwarder::RemoveTextureFromCompositableAsync(AsyncTransactionTracker
CompositableClient* aCompositable,
TextureClient* aTexture)
{
MOZ_ASSERT(aCompositable);
MOZ_ASSERT(aTexture);
MOZ_ASSERT(aCompositable->IsConnected());
MOZ_ASSERT(aTexture->GetIPDLActor());
CompositableOperation op(
nullptr, aCompositable->GetIPDLActor(),
OpRemoveTextureAsync(CompositableClient::GetTrackersHolderId(aCompositable->GetIPDLActor()),
aAsyncTransactionTracker->GetId(),
nullptr, aCompositable->GetIPDLActor(),
nullptr, aTexture->GetIPDLActor()));
#ifdef MOZ_WIDGET_GONK
mPendingAsyncMessages.push_back(op);
#else
if (mTxn->Opened() && aCompositable->IsConnected()) {
mTxn->AddEdit(op);
} else {
NS_RUNTIMEABORT("not reached");
}
#endif
CompositableClient::HoldUntilComplete(aCompositable->GetIPDLActor(),
aAsyncTransactionTracker);
NS_RUNTIMEABORT("not reached");
}
bool
@ -923,6 +927,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
if (!HasShadowManager() ||
!mShadowManager->IPCOpen() ||
!mShadowManager->SendUpdate(cset, mTxn->mDestroyedActors,
GetFwdTransactionId(),
aId, targetConfig, mPluginWindowData,
mIsFirstPaint, aScheduleComposite,
aPaintSequenceNumber, aIsRepeatTransaction,
@ -939,6 +944,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
if (!HasShadowManager() ||
!mShadowManager->IPCOpen() ||
!mShadowManager->SendUpdateNoSwap(cset, mTxn->mDestroyedActors,
GetFwdTransactionId(),
aId, targetConfig, mPluginWindowData,
mIsFirstPaint, aScheduleComposite,
aPaintSequenceNumber, aIsRepeatTransaction,
@ -1083,14 +1089,15 @@ void ShadowLayerForwarder::AttachAsyncCompositable(uint64_t aCompositableID,
PTextureChild*
ShadowLayerForwarder::CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags)
TextureFlags aFlags,
uint64_t aSerial)
{
if (!HasShadowManager() ||
!mShadowManager->IPCOpen() ||
!mShadowManager->Manager()) {
return nullptr;
}
return mShadowManager->Manager()->SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, mShadowManager->GetId());
return mShadowManager->Manager()->SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, mShadowManager->GetId(), aSerial);
}
@ -1106,7 +1113,6 @@ void ShadowLayerForwarder::StopReceiveAsyncParentMessge()
!mShadowManager->IPCOpen()) {
return;
}
SendPendingAsyncMessges();
mShadowManager->SetForwarder(nullptr);
}
@ -1116,7 +1122,6 @@ void ShadowLayerForwarder::ClearCachedResources()
!mShadowManager->IPCOpen()) {
return;
}
SendPendingAsyncMessges();
mShadowManager->SendClearCachedResources();
}
@ -1129,27 +1134,6 @@ void ShadowLayerForwarder::Composite()
mShadowManager->SendForceComposite();
}
void ShadowLayerForwarder::SendPendingAsyncMessges()
{
if (!HasShadowManager() ||
!mShadowManager->IPCOpen()) {
mPendingAsyncMessages.clear();
return;
}
if (mPendingAsyncMessages.empty()) {
return;
}
InfallibleTArray<AsyncChildMessageData> replies;
// Prepare pending messages.
for (size_t i = 0; i < mPendingAsyncMessages.size(); i++) {
replies.AppendElement(mPendingAsyncMessages[i]);
}
mPendingAsyncMessages.clear();
mShadowManager->SendChildAsyncMessages(replies);
}
bool
IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface)
{
@ -1287,5 +1271,33 @@ ShadowLayerForwarder::DestroySurfaceDescriptor(SurfaceDescriptor* aSurface)
*aSurface = SurfaceDescriptor();
}
void
ShadowLayerForwarder::UpdateFwdTransactionId()
{
GetCompositorBridgeChild()->UpdateFwdTransactionId();
}
uint64_t
ShadowLayerForwarder::GetFwdTransactionId()
{
return GetCompositorBridgeChild()->GetFwdTransactionId();
}
void
ShadowLayerForwarder::CancelWaitForRecycle(uint64_t aTextureId)
{
GetCompositorBridgeChild()->CancelWaitForRecycle(aTextureId);
}
CompositorBridgeChild*
ShadowLayerForwarder::GetCompositorBridgeChild()
{
if (mCompositorBridgeChild) {
return mCompositorBridgeChild;
}
mCompositorBridgeChild = mClientLayerManager->GetCompositorBridgeChild();
return mCompositorBridgeChild;
}
} // namespace layers
} // namespace mozilla

View File

@ -27,6 +27,8 @@
namespace mozilla {
namespace layers {
class ClientLayerManager;
class CompositorBridgeChild;
class EditReply;
class FixedSizeSmallShmemSectionAllocator;
class ImageContainer;
@ -141,7 +143,8 @@ public:
virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
LayersBackend aLayersBackend,
TextureFlags aFlags) override;
TextureFlags aFlags,
uint64_t aSerial) override;
/**
* Adds an edit in the layers transaction in order to attach
@ -291,8 +294,6 @@ public:
void Composite();
virtual void SendPendingAsyncMessges() override;
/**
* True if this is forwarding to a LayerManagerComposite.
*/
@ -349,6 +350,8 @@ public:
virtual MessageLoop* GetMessageLoop() const override { return mMessageLoop; }
virtual void CancelWaitForRecycle(uint64_t aTextureId) override;
base::ProcessId GetParentPid() const;
/**
@ -377,11 +380,14 @@ public:
virtual void DestroySurfaceDescriptor(SurfaceDescriptor* aSurface) override;
virtual void UpdateFwdTransactionId() override;
virtual uint64_t GetFwdTransactionId() override;
// Returns true if aSurface wraps a Shmem.
static bool IsShmem(SurfaceDescriptor* aSurface);
protected:
ShadowLayerForwarder();
explicit ShadowLayerForwarder(ClientLayerManager* aClientLayerManager);
#ifdef DEBUG
void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const;
@ -391,13 +397,16 @@ protected:
bool InWorkerThread();
CompositorBridgeChild* GetCompositorBridgeChild();
RefPtr<LayerTransactionChild> mShadowManager;
RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
private:
ClientLayerManager* mClientLayerManager;
Transaction* mTxn;
MessageLoop* mMessageLoop;
std::vector<CompositableOperation> mPendingAsyncMessages;
DiagnosticTypes mDiagnosticTypes;
bool mIsFirstPaint;
bool mWindowOverlayChanged;

View File

@ -14,6 +14,7 @@ class TargetConfig;
class LayerTransactionParent;
class AsyncCompositionManager;
class APZTestData;
class CompositorBridgeParentIPCAllocator;
class ShadowLayersManager
{
@ -44,6 +45,7 @@ public:
virtual void SetConfirmedTargetAPZC(const LayerTransactionParent* aLayerTree,
const uint64_t& aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) = 0;
virtual CompositorBridgeParentIPCAllocator* AsCompositorBridgeParentIPCAllocator() { return nullptr; }
};
} // namespace layers

View File

@ -157,6 +157,8 @@ CompositorOGL::CreateContext()
void
CompositorOGL::Destroy()
{
Compositor::Destroy();
if (mTexturePool) {
mTexturePool->Clear();
mTexturePool = nullptr;

View File

@ -73,6 +73,8 @@ public:
virtual FenceHandle GetCompositorReleaseFence() override;
virtual GrallocTextureHostOGL* AsGrallocTextureHostOGL() override { return this; }
private:
void DestroyEGLImage();

View File

@ -3,7 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeChild.h"
@ -882,8 +881,6 @@ gfxPlatform::InitLayersIPC()
}
sLayersIPCIsUp = true;
AsyncTransactionTrackersHolder::Initialize();
if (XRE_IsParentProcess())
{
layers::CompositorThreadHolder::Start();

View File

@ -432,7 +432,7 @@ status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence,
ST_LOGE("dequeueBuffer: failed to alloc gralloc buffer");
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();
{ // Scope for the lock

View File

@ -452,7 +452,7 @@ status_t GonkBufferQueue::dequeueBuffer(int *outBuf, sp<Fence>* outFence, bool a
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
{ // Scope for the lock
Mutex::Autolock lock(mMutex);

View File

@ -352,7 +352,7 @@ status_t GonkBufferQueueProducer::dequeueBuffer(int *outSlot,
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = TextureClient::CreateWithData(
texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
sp<GraphicBuffer> graphicBuffer = texData->GetGraphicBuffer();

View File

@ -331,7 +331,7 @@ status_t GonkNativeWindow::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
return -ENOMEM;
}
RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::DEALLOCATE_CLIENT, allocator);
RefPtr<TextureClient> textureClient = new TextureClient(texData, TextureFlags::RECYCLE | TextureFlags::DEALLOCATE_CLIENT, allocator);
{ // Scope for the lock
Mutex::Autolock lock(mMutex);

View File

@ -18,7 +18,6 @@
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/AsyncTransactionTracker.h"
#include "mozilla/layers/SharedBufferManagerChild.h"
#include "prlink.h"
@ -966,8 +965,6 @@ ShutdownXPCOM(nsIServiceManager* aServMgr)
nsCycleCollector_shutdown();
layers::AsyncTransactionTrackersHolder::Finalize();
PROFILER_MARKER("Shutdown xpcom");
// If we are doing any shutdown checks, poison writes.
if (gShutdownChecks != SCM_NOTHING) {