author | Nicolas Silva <nsilva@mozilla.com> |
Fri, 01 Jul 2016 10:58:16 +0200 | |
changeset 343434 | 31f3f2c5a759b92ac41f55c9616fb7a15700abf5 |
parent 343433 | 53487e6b475af7829d3aa14a9d99ffe9e443774e |
child 343435 | f51f78388224856591d67cebd26b46aed715287c |
push id | 6389 |
push user | raliiev@mozilla.com |
push date | Mon, 19 Sep 2016 13:38:22 +0000 |
treeherder | mozilla-beta@01d67bfe6c81 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Bas |
bugs | 1167235 |
milestone | 50.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/PersistentBufferProvider.cpp +++ b/gfx/layers/PersistentBufferProvider.cpp @@ -85,24 +85,26 @@ PersistentBufferProviderShared::Create(g { if (!aFwd || !aFwd->IPCOpen()) { return nullptr; } RefPtr<TextureClient> texture = TextureClient::CreateForDrawing( aFwd, aFormat, aSize, BackendSelector::Canvas, - TextureFlags::IMMEDIATE_UPLOAD, + TextureFlags::DEFAULT, TextureAllocationFlags::ALLOC_DEFAULT ); if (!texture) { return nullptr; } + texture->EnableReadLock(); + RefPtr<PersistentBufferProviderShared> provider = new PersistentBufferProviderShared(aSize, aFormat, aFwd, texture); return provider.forget(); } PersistentBufferProviderShared::PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, CompositableForwarder* aFwd, @@ -115,51 +117,79 @@ PersistentBufferProviderShared::Persiste { MOZ_COUNT_CTOR(PersistentBufferProviderShared); } PersistentBufferProviderShared::~PersistentBufferProviderShared() { MOZ_COUNT_DTOR(PersistentBufferProviderShared); + if (IsActivityTracked()) { + mFwd->GetActiveResourceTracker().RemoveObject(this); + } + mDrawTarget = nullptr; if (mBack && mBack->IsLocked()) { mBack->Unlock(); } if (mFront && mFront->IsLocked()) { mFront->Unlock(); } + if (mBuffer && mBuffer->IsLocked()) { + mBuffer->Unlock(); + } } already_AddRefed<gfx::DrawTarget> PersistentBufferProviderShared::BorrowDrawTarget(const gfx::IntRect& aPersistedRect) { if (!mFwd->IPCOpen()) { return nullptr; } + MOZ_ASSERT(!mSnapshot); + + if (IsActivityTracked()) { + mFwd->GetActiveResourceTracker().MarkUsed(this); + } else { + mFwd->GetActiveResourceTracker().AddObject(this); + } + if (!mDrawTarget) { - if (!mBack) { - mBack = TextureClient::CreateForDrawing( - mFwd, mFormat, mSize, - BackendSelector::Canvas, - TextureFlags::IMMEDIATE_UPLOAD, - TextureAllocationFlags::ALLOC_DEFAULT - ); + bool changedBackBuffer = false; + if (!mBack || mBack->IsReadLocked()) { + if (mBuffer && !mBuffer->IsReadLocked()) { + mBack.swap(mBuffer); + } else { + mBack = TextureClient::CreateForDrawing( + mFwd, mFormat, mSize, + BackendSelector::Canvas, + TextureFlags::DEFAULT, + TextureAllocationFlags::ALLOC_DEFAULT + ); + if (mBack) { + mBack->EnableReadLock(); + } + } + changedBackBuffer = true; + } else { + // Fast path, our front buffer is already writable because the texture upload + // has completed on the compositor side. + if (mBack->HasIntermediateBuffer()) { + // No need to keep an extra buffer around + mBuffer = nullptr; + } } - if (!mBack) { + if (!mBack || !mBack->Lock(OpenMode::OPEN_READ_WRITE)) { return nullptr; } - if (!mBack->Lock(OpenMode::OPEN_READ_WRITE)) { - return nullptr; - } - if (!aPersistedRect.IsEmpty() && mFront - && mFront->Lock(OpenMode::OPEN_READ)) { + if (changedBackBuffer && !aPersistedRect.IsEmpty() + && mFront && mFront->Lock(OpenMode::OPEN_READ)) { DebugOnly<bool> success = mFront->CopyToTextureClient(mBack, &aPersistedRect, nullptr); MOZ_ASSERT(success); mFront->Unlock(); } mDrawTarget = mBack->BorrowDrawTarget(); @@ -172,31 +202,39 @@ PersistentBufferProviderShared::BorrowDr return dt.forget(); } bool PersistentBufferProviderShared::ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) { RefPtr<gfx::DrawTarget> dt(aDT); MOZ_ASSERT(mDrawTarget == dt); + MOZ_ASSERT(!mSnapshot); mDrawTarget = nullptr; dt = nullptr; mBack->Unlock(); + if (!mBuffer && mFront && !mFront->IsLocked()) { + mBuffer.swap(mFront); + } + mFront = mBack; - mBack = nullptr; return true; } already_AddRefed<gfx::SourceSurface> PersistentBufferProviderShared::BorrowSnapshot() { + // TODO[nical] currently we can't snapshot while drawing, looks like it does + // the job but I am not sure whether we want to be able to do that. + MOZ_ASSERT(!mDrawTarget); + if (!mFront || mFront->IsLocked()) { MOZ_ASSERT(false); return nullptr; } if (!mFront->Lock(OpenMode::OPEN_READ)) { return nullptr; } @@ -222,10 +260,21 @@ PersistentBufferProviderShared::ReturnSn mSnapshot = nullptr; snapshot = nullptr; mDrawTarget = nullptr; mFront->Unlock(); } +void +PersistentBufferProviderShared::NotifyInactive() +{ + if (mBuffer && mBuffer->IsLocked()) { + // mBuffer should never be locked + MOZ_ASSERT(false); + mBuffer->Unlock(); + } + mBuffer = nullptr; +} + } // namespace layers } // namespace mozilla \ No newline at end of file
--- a/gfx/layers/PersistentBufferProvider.h +++ b/gfx/layers/PersistentBufferProvider.h @@ -91,16 +91,17 @@ private: }; /** * Provides access to a buffer which can be sent to the compositor without * requiring a copy. */ class PersistentBufferProviderShared : public PersistentBufferProvider + , public ActiveResource { public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PersistentBufferProviderShared, override) static already_AddRefed<PersistentBufferProviderShared> Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, CompositableForwarder* aFwd); @@ -113,28 +114,34 @@ public: virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() override; virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override; TextureClient* GetTextureClient() override { return mFront; } + virtual void NotifyInactive() override; + protected: PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, CompositableForwarder* aFwd, RefPtr<TextureClient>& aTexture); ~PersistentBufferProviderShared(); gfx::IntSize mSize; gfx::SurfaceFormat mFormat; RefPtr<CompositableForwarder> mFwd; + // The texture presented to the compositor. RefPtr<TextureClient> mFront; + // The texture that the canvas uses. RefPtr<TextureClient> mBack; + // An extra texture we keep around temporarily to avoid allocating. + RefPtr<TextureClient> mBuffer; RefPtr<gfx::DrawTarget> mDrawTarget; RefPtr<gfx::SourceSurface > mSnapshot; }; struct AutoReturnSnapshot { PersistentBufferProvider* mBufferProvider; RefPtr<gfx::SourceSurface>* mSnapshot;
--- a/gfx/layers/client/CanvasClient.h +++ b/gfx/layers/client/CanvasClient.h @@ -106,17 +106,16 @@ public: } virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override; virtual void UpdateFromTexture(TextureClient* aBuffer) override; virtual bool AddTextureClient(TextureClient* aTexture) override { - MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags); return CanvasClient::AddTextureClient(aTexture); } virtual void OnDetach() override { mBackBuffer = mFrontBuffer = nullptr; }
--- a/gfx/layers/ipc/CompositableForwarder.h +++ b/gfx/layers/ipc/CompositableForwarder.h @@ -13,47 +13,79 @@ #include "mozilla/layers/CompositableClient.h" // for CompositableClient #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator #include "mozilla/layers/LayersTypes.h" // for LayersBackend #include "mozilla/layers/TextureClient.h" // for TextureClient #include "mozilla/layers/TextureForwarder.h" // for TextureForwarder #include "nsRegion.h" // for nsIntRegion #include "mozilla/gfx/Rect.h" +#include "nsExpirationTracker.h" #include "nsHashKeys.h" #include "nsTHashtable.h" namespace mozilla { namespace layers { class CompositableClient; class AsyncTransactionTracker; class ImageContainer; struct TextureFactoryIdentifier; class SurfaceDescriptor; class SurfaceDescriptorTiles; class ThebesBufferData; class PTextureChild; /** + * See ActiveResourceTracker below. + */ +class ActiveResource +{ +public: + virtual void NotifyInactive() = 0; + nsExpirationState* GetExpirationState() { return &mExpirationState; } + bool IsActivityTracked() { return mExpirationState.IsTracked(); } +private: + nsExpirationState mExpirationState; +}; + +/** + * A convenience class on top of nsExpirationTracker + */ +class ActiveResourceTracker : public nsExpirationTracker<ActiveResource, 3> +{ +public: + ActiveResourceTracker(uint32_t aExpirationCycle, const char* aName) + : nsExpirationTracker(aExpirationCycle, aName) + {} + + virtual void NotifyExpired(ActiveResource* aResource) override + { + RemoveObject(aResource); + aResource->NotifyInactive(); + } +}; + +/** * A transaction is a set of changes that happenned on the content side, that * should be sent to the compositor side. * CompositableForwarder is an interface to manage a transaction of * compositable objetcs. * * ShadowLayerForwarder is an example of a CompositableForwarder (that can * additionally forward modifications of the Layer tree). * ImageBridgeChild is another CompositableForwarder. */ class CompositableForwarder : public TextureForwarder { public: CompositableForwarder(const char* aName) : TextureForwarder(aName) + , mActiveResourceTracker(1000, "CompositableForwarder") , mSerial(++sSerialCounter) {} /** * Setup the IPDL actor for aCompositable to be part of layers * transactions. */ virtual void Connect(CompositableClient* aCompositable, @@ -164,23 +196,27 @@ public: return mTextureFactoryIdentifier.mSupportsPartialUploads; } const TextureFactoryIdentifier& GetTextureFactoryIdentifier() const { return mTextureFactoryIdentifier; } + ActiveResourceTracker& GetActiveResourceTracker() { return mActiveResourceTracker; } + protected: TextureFactoryIdentifier mTextureFactoryIdentifier; nsTArray<RefPtr<TextureClient> > mTexturesToRemove; nsTArray<RefPtr<CompositableClient>> mCompositableClientsToRemove; RefPtr<SyncObject> mSyncObject; + ActiveResourceTracker mActiveResourceTracker; + const int32_t mSerial; static mozilla::Atomic<int32_t> sSerialCounter; }; } // namespace layers } // namespace mozilla #endif