michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "gfxReusableSharedImageSurfaceWrapper.h" michael@0: #include "gfxSharedImageSurface.h" michael@0: #include "mozilla/layers/ISurfaceAllocator.h" michael@0: michael@0: using mozilla::ipc::Shmem; michael@0: using mozilla::layers::ISurfaceAllocator; michael@0: michael@0: gfxReusableSharedImageSurfaceWrapper::gfxReusableSharedImageSurfaceWrapper(ISurfaceAllocator* aAllocator, michael@0: gfxSharedImageSurface* aSurface) michael@0: : mAllocator(aAllocator) michael@0: , mSurface(aSurface) michael@0: { michael@0: MOZ_COUNT_CTOR(gfxReusableSharedImageSurfaceWrapper); michael@0: ReadLock(); michael@0: } michael@0: michael@0: gfxReusableSharedImageSurfaceWrapper::~gfxReusableSharedImageSurfaceWrapper() michael@0: { michael@0: MOZ_COUNT_DTOR(gfxReusableSharedImageSurfaceWrapper); michael@0: ReadUnlock(); michael@0: } michael@0: michael@0: void michael@0: gfxReusableSharedImageSurfaceWrapper::ReadLock() michael@0: { michael@0: NS_ASSERT_OWNINGTHREAD(gfxReusableSharedImageSurfaceWrapper); michael@0: mSurface->ReadLock(); michael@0: } michael@0: michael@0: void michael@0: gfxReusableSharedImageSurfaceWrapper::ReadUnlock() michael@0: { michael@0: int32_t readCount = mSurface->ReadUnlock(); michael@0: NS_ABORT_IF_FALSE(readCount >= 0, "Read count should not be negative"); michael@0: michael@0: if (readCount == 0) { michael@0: mAllocator->DeallocShmem(mSurface->GetShmem()); michael@0: } michael@0: } michael@0: michael@0: gfxReusableSurfaceWrapper* michael@0: gfxReusableSharedImageSurfaceWrapper::GetWritable(gfxImageSurface** aSurface) michael@0: { michael@0: NS_ASSERT_OWNINGTHREAD(gfxReusableSharedImageSurfaceWrapper); michael@0: michael@0: int32_t readCount = mSurface->GetReadCount(); michael@0: NS_ABORT_IF_FALSE(readCount > 0, "A ReadLock must be held when calling GetWritable"); michael@0: if (readCount == 1) { michael@0: *aSurface = mSurface; michael@0: return this; michael@0: } michael@0: michael@0: // Something else is reading the surface, copy it michael@0: nsRefPtr copySurface = michael@0: gfxSharedImageSurface::CreateUnsafe(mAllocator.get(), mSurface->GetSize(), mSurface->Format()); michael@0: copySurface->CopyFrom(mSurface); michael@0: *aSurface = copySurface; michael@0: michael@0: // We need to create a new wrapper since this wrapper has an external ReadLock michael@0: gfxReusableSurfaceWrapper* wrapper = new gfxReusableSharedImageSurfaceWrapper(mAllocator, copySurface); michael@0: michael@0: // No need to release the ReadLock on the surface, this will happen when michael@0: // the wrapper is destroyed. michael@0: michael@0: return wrapper; michael@0: } michael@0: michael@0: const unsigned char* michael@0: gfxReusableSharedImageSurfaceWrapper::GetReadOnlyData() const michael@0: { michael@0: NS_ABORT_IF_FALSE(mSurface->GetReadCount() > 0, "Should have read lock"); michael@0: return mSurface->Data(); michael@0: } michael@0: michael@0: gfxImageFormat michael@0: gfxReusableSharedImageSurfaceWrapper::Format() michael@0: { michael@0: return mSurface->Format(); michael@0: } michael@0: michael@0: Shmem& michael@0: gfxReusableSharedImageSurfaceWrapper::GetShmem() michael@0: { michael@0: return mSurface->GetShmem(); michael@0: } michael@0: michael@0: /* static */ already_AddRefed michael@0: gfxReusableSharedImageSurfaceWrapper::Open(ISurfaceAllocator* aAllocator, const Shmem& aShmem) michael@0: { michael@0: nsRefPtr sharedImage = gfxSharedImageSurface::Open(aShmem); michael@0: nsRefPtr wrapper = new gfxReusableSharedImageSurfaceWrapper(aAllocator, sharedImage); michael@0: wrapper->ReadUnlock(); michael@0: return wrapper.forget(); michael@0: }