gfx/thebes/gfxBaseSharedMemorySurface.h

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:a1971bd53354
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 */

mercurial