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