☠☠ backed out by 719f1c2189d2 ☠ ☠ | |
author | Andrew Osmond <aosmond@mozilla.com> |
Mon, 30 Oct 2017 09:10:44 -0400 | |
changeset 389005 | 7e1da430d9f9323ef4fd0690459fd87c8d1ba0ef |
parent 389004 | 97415d233c163fc85ca33edc0c9aaaf0a3d473a6 |
child 389006 | 83cc1f67e9f78482484d8945e6caed4517810dcf |
push id | 96759 |
push user | aosmond@gmail.com |
push date | Mon, 30 Oct 2017 13:11:04 +0000 |
treeherder | mozilla-inbound@7c56a10468d7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jrmuizel |
bugs | 1331944 |
milestone | 58.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
gfx/layers/SourceSurfaceSharedData.cpp | file | annotate | diff | comparison | revisions | |
gfx/layers/SourceSurfaceSharedData.h | file | annotate | diff | comparison | revisions |
--- a/gfx/layers/SourceSurfaceSharedData.cpp +++ b/gfx/layers/SourceSurfaceSharedData.cpp @@ -7,16 +7,53 @@ #include "mozilla/Likely.h" #include "mozilla/Types.h" // for decltype namespace mozilla { namespace gfx { bool +SourceSurfaceSharedDataWrapper::Init(const IntSize& aSize, + int32_t aStride, + SurfaceFormat aFormat, + const SharedMemoryBasic::Handle& aHandle, + base::ProcessId aCreatorPid) +{ + MOZ_ASSERT(!mBuf); + mSize = aSize; + mStride = aStride; + mFormat = aFormat; + mCreatorPid = aCreatorPid; + + size_t len = GetAlignedDataLength(); + mBuf = new SharedMemoryBasic(); + if (NS_WARN_IF(!mBuf->SetHandle(aHandle, ipc::SharedMemory::RightsReadOnly)) || + NS_WARN_IF(!mBuf->Map(len))) { + mBuf = nullptr; + return false; + } + + mBuf->CloseHandle(); + return true; +} + +void +SourceSurfaceSharedDataWrapper::Init(SourceSurfaceSharedData* aSurface) +{ + MOZ_ASSERT(!mBuf); + MOZ_ASSERT(aSurface); + mSize = aSurface->mSize; + mStride = aSurface->mStride; + mFormat = aSurface->mFormat; + mCreatorPid = base::GetCurrentProcId(); + mBuf = aSurface->mBuf; +} + +bool SourceSurfaceSharedData::Init(const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat) { mSize = aSize; mStride = aStride; mFormat = aFormat; @@ -62,16 +99,17 @@ SourceSurfaceSharedData::GetDataInternal return static_cast<uint8_t*>(mBuf->memory()); } nsresult SourceSurfaceSharedData::ShareToProcess(base::ProcessId aPid, SharedMemoryBasic::Handle& aHandle) { MutexAutoLock lock(mMutex); + MOZ_ASSERT(mHandleCount > 0); if (mClosed) { return NS_ERROR_NOT_AVAILABLE; } bool shared = mBuf->ShareToProcess(aPid, &aHandle); if (MOZ_UNLIKELY(!shared)) { return NS_ERROR_FAILURE; @@ -81,29 +119,33 @@ SourceSurfaceSharedData::ShareToProcess( } void SourceSurfaceSharedData::CloseHandleInternal() { mMutex.AssertCurrentThreadOwns(); if (mClosed) { + MOZ_ASSERT(mHandleCount == 0); + MOZ_ASSERT(mFinalized); + MOZ_ASSERT(mShared); return; } if (mFinalized && mShared) { mBuf->CloseHandle(); mClosed = true; } } bool SourceSurfaceSharedData::ReallocHandle() { MutexAutoLock lock(mMutex); + MOZ_ASSERT(mHandleCount > 0); MOZ_ASSERT(mClosed); MOZ_ASSERT(mFinalized); size_t len = GetAlignedDataLength(); RefPtr<SharedMemoryBasic> buf = new SharedMemoryBasic(); if (NS_WARN_IF(!buf->Create(len)) || NS_WARN_IF(!buf->Map(len))) { return false;
--- a/gfx/layers/SourceSurfaceSharedData.h +++ b/gfx/layers/SourceSurfaceSharedData.h @@ -8,39 +8,123 @@ #include "mozilla/gfx/2D.h" #include "mozilla/Mutex.h" #include "mozilla/ipc/SharedMemoryBasic.h" namespace mozilla { namespace gfx { +class SourceSurfaceSharedData; + +class SourceSurfaceSharedDataWrapper final : public DataSourceSurface +{ + typedef mozilla::ipc::SharedMemoryBasic SharedMemoryBasic; + +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedDataWrapper, override) + + SourceSurfaceSharedDataWrapper() + : mStride(0) + , mFormat(SurfaceFormat::UNKNOWN) + { } + + bool Init(const IntSize& aSize, + int32_t aStride, + SurfaceFormat aFormat, + const SharedMemoryBasic::Handle& aHandle, + base::ProcessId aCreatorPid); + + void Init(SourceSurfaceSharedData *aSurface); + + base::ProcessId GetCreatorPid() const + { + return mCreatorPid; + } + + int32_t Stride() override { return mStride; } + + SurfaceType GetType() const override { return SurfaceType::DATA; } + IntSize GetSize() const override { return mSize; } + SurfaceFormat GetFormat() const override { return mFormat; } + + uint8_t* GetData() override + { + return static_cast<uint8_t*>(mBuf->memory()); + } + + bool OnHeap() const override + { + return false; + } + + bool Map(MapType, MappedSurface *aMappedSurface) override + { + aMappedSurface->mData = GetData(); + aMappedSurface->mStride = mStride; + return true; + } + + void Unmap() override + { } + + bool AddConsumer() + { + return ++mConsumers == 1; + } + + bool RemoveConsumer() + { + MOZ_ASSERT(mConsumers > 0); + return --mConsumers == 0; + } + +private: + size_t GetDataLength() const + { + return static_cast<size_t>(mStride) * mSize.height; + } + + size_t GetAlignedDataLength() const + { + return mozilla::ipc::SharedMemory::PageAlignedSize(GetDataLength()); + } + + int32_t mStride; + uint32_t mConsumers; + IntSize mSize; + RefPtr<SharedMemoryBasic> mBuf; + SurfaceFormat mFormat; + base::ProcessId mCreatorPid; +}; + /** * This class is used to wrap shared (as in process) data buffers used by a * source surface. */ class SourceSurfaceSharedData final : public DataSourceSurface { typedef mozilla::ipc::SharedMemoryBasic SharedMemoryBasic; public: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceSharedData, override) SourceSurfaceSharedData() : mMutex("SourceSurfaceSharedData") , mStride(0) , mMapCount(0) + , mHandleCount(0) , mFormat(SurfaceFormat::UNKNOWN) , mClosed(false) , mFinalized(false) , mShared(false) { } - bool Init(const IntSize &aSize, + bool Init(const IntSize& aSize, int32_t aStride, SurfaceFormat aFormat); uint8_t* GetData() override { MutexAutoLock lock(mMutex); return GetDataInternal(); } @@ -128,27 +212,75 @@ public: * Allocate a new shared memory buffer so that we can get a new handle for * sharing to new processes. ShareToProcess must have failed with * NS_ERROR_NOT_AVAILABLE in order for this to be safe to call. Returns true * if the operation succeeds. If it fails, there is no state change. */ bool ReallocHandle(); /** - * Indicates we have finished writing to the buffer and it may be marked as + * Signals we have finished writing to the buffer and it may be marked as * read only. May release the handle if possible (see CloseHandleInternal). */ void Finalize(); + /** + * Indicates whether or not the buffer can change. If this returns true, it is + * guaranteed to continue to do so for the remainder of the surface's life. + */ + bool IsFinalized() const + { + MutexAutoLock lock(mMutex); + return mFinalized; + } + + /** + * While a HandleLock exists for the given surface, the shared memory handle + * cannot be released. + */ + class MOZ_STACK_CLASS HandleLock final { + public: + explicit HandleLock(SourceSurfaceSharedData* aSurface) + : mSurface(aSurface) + { + mSurface->LockHandle(); + } + + ~HandleLock() + { + mSurface->UnlockHandle(); + } + + private: + RefPtr<SourceSurfaceSharedData> mSurface; + }; + private: + friend class SourceSurfaceSharedDataWrapper; + ~SourceSurfaceSharedData() override { MOZ_ASSERT(mMapCount == 0); } + void LockHandle() + { + MutexAutoLock lock(mMutex); + ++mHandleCount; + } + + void UnlockHandle() + { + MutexAutoLock lock(mMutex); + MOZ_ASSERT(mHandleCount > 0); + --mHandleCount; + mShared = true; + CloseHandleInternal(); + } + uint8_t* GetDataInternal() const; size_t GetDataLength() const { return static_cast<size_t>(mStride) * mSize.height; } size_t GetAlignedDataLength() const @@ -160,16 +292,17 @@ private: * Attempt to close the handle. Only if the buffer has been both finalized * and we have completed sharing will it be released. */ void CloseHandleInternal(); mutable Mutex mMutex; int32_t mStride; int32_t mMapCount; + int32_t mHandleCount; IntSize mSize; RefPtr<SharedMemoryBasic> mBuf; RefPtr<SharedMemoryBasic> mOldBuf; SurfaceFormat mFormat; bool mClosed : 1; bool mFinalized : 1; bool mShared : 1; };