Bug 1331944 - Part 1. Add SourceSurfaceSharedDataWrapper and SourceSurfaceSharedData::HandleLock. r=jrmuizel

This commit is contained in:
Andrew Osmond 2017-10-30 13:10:28 -04:00
parent 7e4a6c3456
commit b8f42d8fa2
2 changed files with 192 additions and 2 deletions

View File

@ -11,6 +11,43 @@
namespace mozilla { namespace mozilla {
namespace gfx { 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 = MakeAndAddRef<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 bool
SourceSurfaceSharedData::Init(const IntSize &aSize, SourceSurfaceSharedData::Init(const IntSize &aSize,
int32_t aStride, int32_t aStride,
@ -67,6 +104,7 @@ SourceSurfaceSharedData::ShareToProcess(base::ProcessId aPid,
SharedMemoryBasic::Handle& aHandle) SharedMemoryBasic::Handle& aHandle)
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
MOZ_ASSERT(mHandleCount > 0);
if (mClosed) { if (mClosed) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
@ -86,6 +124,9 @@ SourceSurfaceSharedData::CloseHandleInternal()
mMutex.AssertCurrentThreadOwns(); mMutex.AssertCurrentThreadOwns();
if (mClosed) { if (mClosed) {
MOZ_ASSERT(mHandleCount == 0);
MOZ_ASSERT(mFinalized);
MOZ_ASSERT(mShared);
return; return;
} }
@ -99,6 +140,7 @@ bool
SourceSurfaceSharedData::ReallocHandle() SourceSurfaceSharedData::ReallocHandle()
{ {
MutexAutoLock lock(mMutex); MutexAutoLock lock(mMutex);
MOZ_ASSERT(mHandleCount > 0);
MOZ_ASSERT(mClosed); MOZ_ASSERT(mClosed);
MOZ_ASSERT(mFinalized); MOZ_ASSERT(mFinalized);

View File

@ -13,6 +13,104 @@
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
class SourceSurfaceSharedData;
/**
* This class is used to wrap shared (as in process) data buffers allocated by
* a SourceSurfaceSharedData object. It may live in the same process or a
* different process from the actual SourceSurfaceSharedData object.
*
* If it is in the same process, mBuf is the same object as that in the surface.
* It is a useful abstraction over just using the surface directly, because it
* can have a different lifetime from the surface; if the surface gets freed,
* consumers may continue accessing the data in the buffer. Releasing the
* original surface is a signal which feeds into SharedSurfacesParent to decide
* to release the SourceSurfaceSharedDataWrapper.
*
* If it is in a different process, mBuf is a new SharedMemoryBasic object which
* mapped in the given shared memory handle as read only memory.
*/
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 * This class is used to wrap shared (as in process) data buffers used by a
* source surface. * source surface.
@ -28,6 +126,7 @@ public:
: mMutex("SourceSurfaceSharedData") : mMutex("SourceSurfaceSharedData")
, mStride(0) , mStride(0)
, mMapCount(0) , mMapCount(0)
, mHandleCount(0)
, mFormat(SurfaceFormat::UNKNOWN) , mFormat(SurfaceFormat::UNKNOWN)
, mClosed(false) , mClosed(false)
, mFinalized(false) , mFinalized(false)
@ -35,7 +134,7 @@ public:
{ {
} }
bool Init(const IntSize &aSize, bool Init(const IntSize& aSize,
int32_t aStride, int32_t aStride,
SurfaceFormat aFormat); SurfaceFormat aFormat);
@ -133,17 +232,65 @@ public:
bool ReallocHandle(); 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). * read only. May release the handle if possible (see CloseHandleInternal).
*/ */
void Finalize(); 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: private:
friend class SourceSurfaceSharedDataWrapper;
~SourceSurfaceSharedData() override ~SourceSurfaceSharedData() override
{ {
MOZ_ASSERT(mMapCount == 0); 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; uint8_t* GetDataInternal() const;
size_t GetDataLength() const size_t GetDataLength() const
@ -165,6 +312,7 @@ private:
mutable Mutex mMutex; mutable Mutex mMutex;
int32_t mStride; int32_t mStride;
int32_t mMapCount; int32_t mMapCount;
int32_t mHandleCount;
IntSize mSize; IntSize mSize;
RefPtr<SharedMemoryBasic> mBuf; RefPtr<SharedMemoryBasic> mBuf;
RefPtr<SharedMemoryBasic> mOldBuf; RefPtr<SharedMemoryBasic> mOldBuf;