diff -r 000000000000 -r 6474c204b198 gfx/thebes/gfxReusableSharedImageSurfaceWrapper.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/thebes/gfxReusableSharedImageSurfaceWrapper.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,98 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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 "gfxReusableSharedImageSurfaceWrapper.h" +#include "gfxSharedImageSurface.h" +#include "mozilla/layers/ISurfaceAllocator.h" + +using mozilla::ipc::Shmem; +using mozilla::layers::ISurfaceAllocator; + +gfxReusableSharedImageSurfaceWrapper::gfxReusableSharedImageSurfaceWrapper(ISurfaceAllocator* aAllocator, + gfxSharedImageSurface* aSurface) + : mAllocator(aAllocator) + , mSurface(aSurface) +{ + MOZ_COUNT_CTOR(gfxReusableSharedImageSurfaceWrapper); + ReadLock(); +} + +gfxReusableSharedImageSurfaceWrapper::~gfxReusableSharedImageSurfaceWrapper() +{ + MOZ_COUNT_DTOR(gfxReusableSharedImageSurfaceWrapper); + ReadUnlock(); +} + +void +gfxReusableSharedImageSurfaceWrapper::ReadLock() +{ + NS_ASSERT_OWNINGTHREAD(gfxReusableSharedImageSurfaceWrapper); + mSurface->ReadLock(); +} + +void +gfxReusableSharedImageSurfaceWrapper::ReadUnlock() +{ + int32_t readCount = mSurface->ReadUnlock(); + NS_ABORT_IF_FALSE(readCount >= 0, "Read count should not be negative"); + + if (readCount == 0) { + mAllocator->DeallocShmem(mSurface->GetShmem()); + } +} + +gfxReusableSurfaceWrapper* +gfxReusableSharedImageSurfaceWrapper::GetWritable(gfxImageSurface** aSurface) +{ + NS_ASSERT_OWNINGTHREAD(gfxReusableSharedImageSurfaceWrapper); + + int32_t readCount = mSurface->GetReadCount(); + NS_ABORT_IF_FALSE(readCount > 0, "A ReadLock must be held when calling GetWritable"); + if (readCount == 1) { + *aSurface = mSurface; + return this; + } + + // Something else is reading the surface, copy it + nsRefPtr copySurface = + gfxSharedImageSurface::CreateUnsafe(mAllocator.get(), mSurface->GetSize(), mSurface->Format()); + copySurface->CopyFrom(mSurface); + *aSurface = copySurface; + + // We need to create a new wrapper since this wrapper has an external ReadLock + gfxReusableSurfaceWrapper* wrapper = new gfxReusableSharedImageSurfaceWrapper(mAllocator, copySurface); + + // No need to release the ReadLock on the surface, this will happen when + // the wrapper is destroyed. + + return wrapper; +} + +const unsigned char* +gfxReusableSharedImageSurfaceWrapper::GetReadOnlyData() const +{ + NS_ABORT_IF_FALSE(mSurface->GetReadCount() > 0, "Should have read lock"); + return mSurface->Data(); +} + +gfxImageFormat +gfxReusableSharedImageSurfaceWrapper::Format() +{ + return mSurface->Format(); +} + +Shmem& +gfxReusableSharedImageSurfaceWrapper::GetShmem() +{ + return mSurface->GetShmem(); +} + +/* static */ already_AddRefed +gfxReusableSharedImageSurfaceWrapper::Open(ISurfaceAllocator* aAllocator, const Shmem& aShmem) +{ + nsRefPtr sharedImage = gfxSharedImageSurface::Open(aShmem); + nsRefPtr wrapper = new gfxReusableSharedImageSurfaceWrapper(aAllocator, sharedImage); + wrapper->ReadUnlock(); + return wrapper.forget(); +}