1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxBaseSharedMemorySurface.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,198 @@ 1.4 +// vim:set ts=4 sts=4 sw=4 et cin: 1.5 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef GFX_SHARED_MEMORYSURFACE_H 1.11 +#define GFX_SHARED_MEMORYSURFACE_H 1.12 + 1.13 +#include "mozilla/ipc/Shmem.h" 1.14 +#include "mozilla/ipc/SharedMemory.h" 1.15 + 1.16 +#include "gfxASurface.h" 1.17 +#include "gfxImageSurface.h" 1.18 +#include "pratom.h" 1.19 + 1.20 +typedef struct _cairo_user_data_key cairo_user_data_key_t; 1.21 + 1.22 +struct SharedImageInfo { 1.23 + int32_t width; 1.24 + int32_t height; 1.25 + gfxImageFormat format; 1.26 + int32_t readCount; 1.27 +}; 1.28 + 1.29 +inline SharedImageInfo* 1.30 +GetShmInfoPtr(const mozilla::ipc::Shmem& aShmem) 1.31 +{ 1.32 + return reinterpret_cast<SharedImageInfo*> 1.33 + (aShmem.get<char>() + aShmem.Size<char>() - sizeof(SharedImageInfo)); 1.34 +} 1.35 + 1.36 +extern const cairo_user_data_key_t SHM_KEY; 1.37 + 1.38 +template <typename Base, typename Sub> 1.39 +class gfxBaseSharedMemorySurface : public Base { 1.40 + typedef mozilla::ipc::SharedMemory SharedMemory; 1.41 + typedef mozilla::ipc::Shmem Shmem; 1.42 + friend class gfxReusableSharedImageSurfaceWrapper; 1.43 + 1.44 +public: 1.45 + virtual ~gfxBaseSharedMemorySurface() 1.46 + { 1.47 + MOZ_COUNT_DTOR(gfxBaseSharedMemorySurface); 1.48 + } 1.49 + 1.50 + /** 1.51 + * Return a new gfxSharedImageSurface around a shmem segment newly 1.52 + * allocated by this function. |aAllocator| is the object used to 1.53 + * allocate the new shmem segment. Null is returned if creating 1.54 + * the surface failed. 1.55 + * 1.56 + * NB: the *caller* is responsible for freeing the Shmem allocated 1.57 + * by this function. 1.58 + */ 1.59 + template<class ShmemAllocator> 1.60 + static already_AddRefed<Sub> 1.61 + Create(ShmemAllocator* aAllocator, 1.62 + const gfxIntSize& aSize, 1.63 + gfxImageFormat aFormat, 1.64 + SharedMemory::SharedMemoryType aShmType = SharedMemory::TYPE_BASIC) 1.65 + { 1.66 + return Create<ShmemAllocator, false>(aAllocator, aSize, aFormat, aShmType); 1.67 + } 1.68 + 1.69 + /** 1.70 + * Return a new gfxSharedImageSurface that wraps a shmem segment 1.71 + * already created by the Create() above. Bad things will happen 1.72 + * if an attempt is made to wrap any other shmem segment. Null is 1.73 + * returned if creating the surface failed. 1.74 + */ 1.75 + static already_AddRefed<Sub> 1.76 + Open(const Shmem& aShmem) 1.77 + { 1.78 + SharedImageInfo* shmInfo = GetShmInfoPtr(aShmem); 1.79 + gfxIntSize size(shmInfo->width, shmInfo->height); 1.80 + if (!gfxASurface::CheckSurfaceSize(size)) 1.81 + return nullptr; 1.82 + 1.83 + gfxImageFormat format = (gfxImageFormat)shmInfo->format; 1.84 + long stride = gfxImageSurface::ComputeStride(size, format); 1.85 + 1.86 + nsRefPtr<Sub> s = 1.87 + new Sub(size, 1.88 + stride, 1.89 + format, 1.90 + aShmem); 1.91 + // We didn't create this Shmem and so don't free it on errors 1.92 + return (s->CairoStatus() != 0) ? nullptr : s.forget(); 1.93 + } 1.94 + 1.95 + template<class ShmemAllocator> 1.96 + static already_AddRefed<Sub> 1.97 + CreateUnsafe(ShmemAllocator* aAllocator, 1.98 + const gfxIntSize& aSize, 1.99 + gfxImageFormat aFormat, 1.100 + SharedMemory::SharedMemoryType aShmType = SharedMemory::TYPE_BASIC) 1.101 + { 1.102 + return Create<ShmemAllocator, true>(aAllocator, aSize, aFormat, aShmType); 1.103 + } 1.104 + 1.105 + Shmem& GetShmem() { return mShmem; } 1.106 + 1.107 + static bool IsSharedImage(gfxASurface *aSurface) 1.108 + { 1.109 + return (aSurface 1.110 + && aSurface->GetType() == gfxSurfaceType::Image 1.111 + && aSurface->GetData(&SHM_KEY)); 1.112 + } 1.113 + 1.114 +protected: 1.115 + gfxBaseSharedMemorySurface(const gfxIntSize& aSize, long aStride, 1.116 + gfxImageFormat aFormat, 1.117 + const Shmem& aShmem) 1.118 + : Base(aShmem.get<unsigned char>(), aSize, aStride, aFormat) 1.119 + { 1.120 + MOZ_COUNT_CTOR(gfxBaseSharedMemorySurface); 1.121 + 1.122 + mShmem = aShmem; 1.123 + this->SetData(&SHM_KEY, this, nullptr); 1.124 + } 1.125 + 1.126 +private: 1.127 + void WriteShmemInfo() 1.128 + { 1.129 + SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); 1.130 + shmInfo->width = this->mSize.width; 1.131 + shmInfo->height = this->mSize.height; 1.132 + shmInfo->format = this->mFormat; 1.133 + shmInfo->readCount = 0; 1.134 + } 1.135 + 1.136 + int32_t 1.137 + ReadLock() 1.138 + { 1.139 + SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); 1.140 + return PR_ATOMIC_INCREMENT(&shmInfo->readCount); 1.141 + } 1.142 + 1.143 + int32_t 1.144 + ReadUnlock() 1.145 + { 1.146 + SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); 1.147 + return PR_ATOMIC_DECREMENT(&shmInfo->readCount); 1.148 + } 1.149 + 1.150 + int32_t 1.151 + GetReadCount() 1.152 + { 1.153 + SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); 1.154 + return shmInfo->readCount; 1.155 + } 1.156 + 1.157 + static size_t GetAlignedSize(const gfxIntSize& aSize, long aStride) 1.158 + { 1.159 + #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3) 1.160 + return MOZ_ALIGN_WORD(sizeof(SharedImageInfo) + aSize.height * aStride); 1.161 + } 1.162 + 1.163 + template<class ShmemAllocator, bool Unsafe> 1.164 + static already_AddRefed<Sub> 1.165 + Create(ShmemAllocator* aAllocator, 1.166 + const gfxIntSize& aSize, 1.167 + gfxImageFormat aFormat, 1.168 + SharedMemory::SharedMemoryType aShmType) 1.169 + { 1.170 + if (!gfxASurface::CheckSurfaceSize(aSize)) 1.171 + return nullptr; 1.172 + 1.173 + Shmem shmem; 1.174 + long stride = gfxImageSurface::ComputeStride(aSize, aFormat); 1.175 + size_t size = GetAlignedSize(aSize, stride); 1.176 + if (!Unsafe) { 1.177 + if (!aAllocator->AllocShmem(size, aShmType, &shmem)) 1.178 + return nullptr; 1.179 + } else { 1.180 + if (!aAllocator->AllocUnsafeShmem(size, aShmType, &shmem)) 1.181 + return nullptr; 1.182 + } 1.183 + 1.184 + nsRefPtr<Sub> s = 1.185 + new Sub(aSize, stride, aFormat, shmem); 1.186 + if (s->CairoStatus() != 0) { 1.187 + aAllocator->DeallocShmem(shmem); 1.188 + return nullptr; 1.189 + } 1.190 + s->WriteShmemInfo(); 1.191 + return s.forget(); 1.192 + } 1.193 + 1.194 + Shmem mShmem; 1.195 + 1.196 + // Calling these is very bad, disallow it 1.197 + gfxBaseSharedMemorySurface(const gfxBaseSharedMemorySurface&); 1.198 + gfxBaseSharedMemorySurface& operator=(const gfxBaseSharedMemorySurface&); 1.199 +}; 1.200 + 1.201 +#endif /* GFX_SHARED_MEMORYSURFACE_H */