1 // vim:set ts=4 sts=2 sw=2 et cin:
2 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef GFX_SHARED_MEMORYSURFACE_H
8 #define GFX_SHARED_MEMORYSURFACE_H
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/ipc/Shmem.h"
12 #include "mozilla/ipc/SharedMemory.h"
14 #include "gfxASurface.h"
15 #include "gfxImageSurface.h"
18 typedef struct _cairo_user_data_key cairo_user_data_key_t
;
20 struct SharedImageInfo
{
23 gfxImageFormat format
;
27 inline SharedImageInfo
* GetShmInfoPtr(const mozilla::ipc::Shmem
& aShmem
) {
28 return reinterpret_cast<SharedImageInfo
*>(
29 aShmem
.get
<char>() + aShmem
.Size
<char>() - sizeof(SharedImageInfo
));
32 extern const cairo_user_data_key_t SHM_KEY
;
34 template <typename Base
, typename Sub
>
35 class gfxBaseSharedMemorySurface
: public Base
{
36 typedef mozilla::ipc::SharedMemory SharedMemory
;
37 typedef mozilla::ipc::Shmem Shmem
;
40 virtual ~gfxBaseSharedMemorySurface() {
41 MOZ_COUNT_DTOR(gfxBaseSharedMemorySurface
);
46 * Return a new gfxSharedImageSurface around a shmem segment newly
47 * allocated by this function. |aAllocator| is the object used to
48 * allocate the new shmem segment. Null is returned if creating
51 * NB: the *caller* is responsible for freeing the Shmem allocated
54 template <class ShmemAllocator
>
55 static already_AddRefed
<Sub
> Create(ShmemAllocator
* aAllocator
,
56 const mozilla::gfx::IntSize
& aSize
,
57 gfxImageFormat aFormat
) {
58 return Create
<ShmemAllocator
, false>(aAllocator
, aSize
, aFormat
);
62 * Return a new gfxSharedImageSurface that wraps a shmem segment
63 * already created by the Create() above. Bad things will happen
64 * if an attempt is made to wrap any other shmem segment. Null is
65 * returned if creating the surface failed.
67 static already_AddRefed
<Sub
> Open(const Shmem
& aShmem
) {
68 SharedImageInfo
* shmInfo
= GetShmInfoPtr(aShmem
);
69 mozilla::gfx::IntSize
size(shmInfo
->width
, shmInfo
->height
);
70 if (!mozilla::gfx::Factory::CheckSurfaceSize(size
)) return nullptr;
72 gfxImageFormat format
= shmInfo
->format
;
73 long stride
= gfxImageSurface::ComputeStride(size
, format
);
75 RefPtr
<Sub
> s
= new Sub(size
, stride
, format
, aShmem
);
76 // We didn't create this Shmem and so don't free it on errors
77 return (s
->CairoStatus() != 0) ? nullptr : s
.forget();
80 template <class ShmemAllocator
>
81 static already_AddRefed
<Sub
> CreateUnsafe(ShmemAllocator
* aAllocator
,
82 const mozilla::gfx::IntSize
& aSize
,
83 gfxImageFormat aFormat
) {
84 return Create
<ShmemAllocator
, true>(aAllocator
, aSize
, aFormat
);
87 Shmem
& GetShmem() { return mShmem
; }
89 static bool IsSharedImage(gfxASurface
* aSurface
) {
90 return (aSurface
&& aSurface
->GetType() == gfxSurfaceType::Image
&&
91 aSurface
->GetData(&SHM_KEY
));
95 gfxBaseSharedMemorySurface(const mozilla::gfx::IntSize
& aSize
, long aStride
,
96 gfxImageFormat aFormat
, const Shmem
& aShmem
)
97 : Base(aShmem
.get
<unsigned char>(), aSize
, aStride
, aFormat
) {
98 MOZ_COUNT_CTOR(gfxBaseSharedMemorySurface
);
101 this->SetData(&SHM_KEY
, this, nullptr);
105 void WriteShmemInfo() {
106 SharedImageInfo
* shmInfo
= GetShmInfoPtr(mShmem
);
107 shmInfo
->width
= this->mSize
.width
;
108 shmInfo
->height
= this->mSize
.height
;
109 shmInfo
->format
= this->mFormat
;
110 shmInfo
->readCount
= 0;
114 SharedImageInfo
* shmInfo
= GetShmInfoPtr(mShmem
);
115 return PR_ATOMIC_INCREMENT(&shmInfo
->readCount
);
118 int32_t ReadUnlock() {
119 SharedImageInfo
* shmInfo
= GetShmInfoPtr(mShmem
);
120 return PR_ATOMIC_DECREMENT(&shmInfo
->readCount
);
123 int32_t GetReadCount() {
124 SharedImageInfo
* shmInfo
= GetShmInfoPtr(mShmem
);
125 return shmInfo
->readCount
;
128 static size_t GetAlignedSize(const mozilla::gfx::IntSize
& aSize
,
130 #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
131 return MOZ_ALIGN_WORD(sizeof(SharedImageInfo
) + aSize
.height
* aStride
);
134 template <class ShmemAllocator
, bool Unsafe
>
135 static already_AddRefed
<Sub
> Create(ShmemAllocator
* aAllocator
,
136 const mozilla::gfx::IntSize
& aSize
,
137 gfxImageFormat aFormat
) {
138 if (!mozilla::gfx::Factory::CheckSurfaceSize(aSize
)) return nullptr;
141 long stride
= gfxImageSurface::ComputeStride(aSize
, aFormat
);
142 size_t size
= GetAlignedSize(aSize
, stride
);
144 if (!aAllocator
->AllocShmem(size
, &shmem
)) return nullptr;
146 if (!aAllocator
->AllocUnsafeShmem(size
, &shmem
)) return nullptr;
149 RefPtr
<Sub
> s
= new Sub(aSize
, stride
, aFormat
, shmem
);
150 if (s
->CairoStatus() != 0) {
151 aAllocator
->DeallocShmem(shmem
);
160 // Calling these is very bad, disallow it
161 gfxBaseSharedMemorySurface(const gfxBaseSharedMemorySurface
&);
162 gfxBaseSharedMemorySurface
& operator=(const gfxBaseSharedMemorySurface
&);
165 #endif /* GFX_SHARED_MEMORYSURFACE_H */