|
1 // vim:set ts=4 sts=4 sw=4 et cin: |
|
2 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
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/. */ |
|
6 |
|
7 #ifndef GFX_SHARED_MEMORYSURFACE_H |
|
8 #define GFX_SHARED_MEMORYSURFACE_H |
|
9 |
|
10 #include "mozilla/ipc/Shmem.h" |
|
11 #include "mozilla/ipc/SharedMemory.h" |
|
12 |
|
13 #include "gfxASurface.h" |
|
14 #include "gfxImageSurface.h" |
|
15 #include "pratom.h" |
|
16 |
|
17 typedef struct _cairo_user_data_key cairo_user_data_key_t; |
|
18 |
|
19 struct SharedImageInfo { |
|
20 int32_t width; |
|
21 int32_t height; |
|
22 gfxImageFormat format; |
|
23 int32_t readCount; |
|
24 }; |
|
25 |
|
26 inline SharedImageInfo* |
|
27 GetShmInfoPtr(const mozilla::ipc::Shmem& aShmem) |
|
28 { |
|
29 return reinterpret_cast<SharedImageInfo*> |
|
30 (aShmem.get<char>() + aShmem.Size<char>() - sizeof(SharedImageInfo)); |
|
31 } |
|
32 |
|
33 extern const cairo_user_data_key_t SHM_KEY; |
|
34 |
|
35 template <typename Base, typename Sub> |
|
36 class gfxBaseSharedMemorySurface : public Base { |
|
37 typedef mozilla::ipc::SharedMemory SharedMemory; |
|
38 typedef mozilla::ipc::Shmem Shmem; |
|
39 friend class gfxReusableSharedImageSurfaceWrapper; |
|
40 |
|
41 public: |
|
42 virtual ~gfxBaseSharedMemorySurface() |
|
43 { |
|
44 MOZ_COUNT_DTOR(gfxBaseSharedMemorySurface); |
|
45 } |
|
46 |
|
47 /** |
|
48 * Return a new gfxSharedImageSurface around a shmem segment newly |
|
49 * allocated by this function. |aAllocator| is the object used to |
|
50 * allocate the new shmem segment. Null is returned if creating |
|
51 * the surface failed. |
|
52 * |
|
53 * NB: the *caller* is responsible for freeing the Shmem allocated |
|
54 * by this function. |
|
55 */ |
|
56 template<class ShmemAllocator> |
|
57 static already_AddRefed<Sub> |
|
58 Create(ShmemAllocator* aAllocator, |
|
59 const gfxIntSize& aSize, |
|
60 gfxImageFormat aFormat, |
|
61 SharedMemory::SharedMemoryType aShmType = SharedMemory::TYPE_BASIC) |
|
62 { |
|
63 return Create<ShmemAllocator, false>(aAllocator, aSize, aFormat, aShmType); |
|
64 } |
|
65 |
|
66 /** |
|
67 * Return a new gfxSharedImageSurface that wraps a shmem segment |
|
68 * already created by the Create() above. Bad things will happen |
|
69 * if an attempt is made to wrap any other shmem segment. Null is |
|
70 * returned if creating the surface failed. |
|
71 */ |
|
72 static already_AddRefed<Sub> |
|
73 Open(const Shmem& aShmem) |
|
74 { |
|
75 SharedImageInfo* shmInfo = GetShmInfoPtr(aShmem); |
|
76 gfxIntSize size(shmInfo->width, shmInfo->height); |
|
77 if (!gfxASurface::CheckSurfaceSize(size)) |
|
78 return nullptr; |
|
79 |
|
80 gfxImageFormat format = (gfxImageFormat)shmInfo->format; |
|
81 long stride = gfxImageSurface::ComputeStride(size, format); |
|
82 |
|
83 nsRefPtr<Sub> s = |
|
84 new Sub(size, |
|
85 stride, |
|
86 format, |
|
87 aShmem); |
|
88 // We didn't create this Shmem and so don't free it on errors |
|
89 return (s->CairoStatus() != 0) ? nullptr : s.forget(); |
|
90 } |
|
91 |
|
92 template<class ShmemAllocator> |
|
93 static already_AddRefed<Sub> |
|
94 CreateUnsafe(ShmemAllocator* aAllocator, |
|
95 const gfxIntSize& aSize, |
|
96 gfxImageFormat aFormat, |
|
97 SharedMemory::SharedMemoryType aShmType = SharedMemory::TYPE_BASIC) |
|
98 { |
|
99 return Create<ShmemAllocator, true>(aAllocator, aSize, aFormat, aShmType); |
|
100 } |
|
101 |
|
102 Shmem& GetShmem() { return mShmem; } |
|
103 |
|
104 static bool IsSharedImage(gfxASurface *aSurface) |
|
105 { |
|
106 return (aSurface |
|
107 && aSurface->GetType() == gfxSurfaceType::Image |
|
108 && aSurface->GetData(&SHM_KEY)); |
|
109 } |
|
110 |
|
111 protected: |
|
112 gfxBaseSharedMemorySurface(const gfxIntSize& aSize, long aStride, |
|
113 gfxImageFormat aFormat, |
|
114 const Shmem& aShmem) |
|
115 : Base(aShmem.get<unsigned char>(), aSize, aStride, aFormat) |
|
116 { |
|
117 MOZ_COUNT_CTOR(gfxBaseSharedMemorySurface); |
|
118 |
|
119 mShmem = aShmem; |
|
120 this->SetData(&SHM_KEY, this, nullptr); |
|
121 } |
|
122 |
|
123 private: |
|
124 void WriteShmemInfo() |
|
125 { |
|
126 SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); |
|
127 shmInfo->width = this->mSize.width; |
|
128 shmInfo->height = this->mSize.height; |
|
129 shmInfo->format = this->mFormat; |
|
130 shmInfo->readCount = 0; |
|
131 } |
|
132 |
|
133 int32_t |
|
134 ReadLock() |
|
135 { |
|
136 SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); |
|
137 return PR_ATOMIC_INCREMENT(&shmInfo->readCount); |
|
138 } |
|
139 |
|
140 int32_t |
|
141 ReadUnlock() |
|
142 { |
|
143 SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); |
|
144 return PR_ATOMIC_DECREMENT(&shmInfo->readCount); |
|
145 } |
|
146 |
|
147 int32_t |
|
148 GetReadCount() |
|
149 { |
|
150 SharedImageInfo* shmInfo = GetShmInfoPtr(mShmem); |
|
151 return shmInfo->readCount; |
|
152 } |
|
153 |
|
154 static size_t GetAlignedSize(const gfxIntSize& aSize, long aStride) |
|
155 { |
|
156 #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3) |
|
157 return MOZ_ALIGN_WORD(sizeof(SharedImageInfo) + aSize.height * aStride); |
|
158 } |
|
159 |
|
160 template<class ShmemAllocator, bool Unsafe> |
|
161 static already_AddRefed<Sub> |
|
162 Create(ShmemAllocator* aAllocator, |
|
163 const gfxIntSize& aSize, |
|
164 gfxImageFormat aFormat, |
|
165 SharedMemory::SharedMemoryType aShmType) |
|
166 { |
|
167 if (!gfxASurface::CheckSurfaceSize(aSize)) |
|
168 return nullptr; |
|
169 |
|
170 Shmem shmem; |
|
171 long stride = gfxImageSurface::ComputeStride(aSize, aFormat); |
|
172 size_t size = GetAlignedSize(aSize, stride); |
|
173 if (!Unsafe) { |
|
174 if (!aAllocator->AllocShmem(size, aShmType, &shmem)) |
|
175 return nullptr; |
|
176 } else { |
|
177 if (!aAllocator->AllocUnsafeShmem(size, aShmType, &shmem)) |
|
178 return nullptr; |
|
179 } |
|
180 |
|
181 nsRefPtr<Sub> s = |
|
182 new Sub(aSize, stride, aFormat, shmem); |
|
183 if (s->CairoStatus() != 0) { |
|
184 aAllocator->DeallocShmem(shmem); |
|
185 return nullptr; |
|
186 } |
|
187 s->WriteShmemInfo(); |
|
188 return s.forget(); |
|
189 } |
|
190 |
|
191 Shmem mShmem; |
|
192 |
|
193 // Calling these is very bad, disallow it |
|
194 gfxBaseSharedMemorySurface(const gfxBaseSharedMemorySurface&); |
|
195 gfxBaseSharedMemorySurface& operator=(const gfxBaseSharedMemorySurface&); |
|
196 }; |
|
197 |
|
198 #endif /* GFX_SHARED_MEMORYSURFACE_H */ |