/work/obj-fuzz/dist/include/gfxBaseSharedMemorySurface.h
Line | Count | Source (jump to first uncovered line) |
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 | | GetShmInfoPtr(const mozilla::ipc::Shmem& aShmem) |
29 | 0 | { |
30 | 0 | return reinterpret_cast<SharedImageInfo*> |
31 | 0 | (aShmem.get<char>() + aShmem.Size<char>() - sizeof(SharedImageInfo)); |
32 | 0 | } |
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 | | virtual ~gfxBaseSharedMemorySurface() |
43 | 0 | { |
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 | | Open(const Shmem& aShmem) |
75 | 0 | { |
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 | 0 | |
81 | 0 | gfxImageFormat format = shmInfo->format; |
82 | 0 | long stride = gfxImageSurface::ComputeStride(size, format); |
83 | 0 |
|
84 | 0 | RefPtr<Sub> s = |
85 | 0 | new Sub(size, |
86 | 0 | stride, |
87 | 0 | format, |
88 | 0 | aShmem); |
89 | 0 | // We didn't create this Shmem and so don't free it on errors |
90 | 0 | return (s->CairoStatus() != 0) ? nullptr : s.forget(); |
91 | 0 | } |
92 | | |
93 | | template<class ShmemAllocator> |
94 | | static already_AddRefed<Sub> |
95 | | CreateUnsafe(ShmemAllocator* aAllocator, |
96 | | const mozilla::gfx::IntSize& aSize, |
97 | | gfxImageFormat aFormat, |
98 | | SharedMemory::SharedMemoryType aShmType = SharedMemory::TYPE_BASIC) |
99 | 0 | { |
100 | 0 | return Create<ShmemAllocator, true>(aAllocator, aSize, aFormat, aShmType); |
101 | 0 | } |
102 | | |
103 | 0 | Shmem& GetShmem() { return mShmem; } |
104 | | |
105 | | static bool IsSharedImage(gfxASurface *aSurface) |
106 | 0 | { |
107 | 0 | return (aSurface |
108 | 0 | && aSurface->GetType() == gfxSurfaceType::Image |
109 | 0 | && aSurface->GetData(&SHM_KEY)); |
110 | 0 | } |
111 | | |
112 | | protected: |
113 | | gfxBaseSharedMemorySurface(const mozilla::gfx::IntSize& aSize, long aStride, |
114 | | gfxImageFormat aFormat, |
115 | | const Shmem& aShmem) |
116 | | : Base(aShmem.get<unsigned char>(), aSize, aStride, aFormat) |
117 | 0 | { |
118 | 0 | MOZ_COUNT_CTOR(gfxBaseSharedMemorySurface); |
119 | 0 |
|
120 | 0 | mShmem = aShmem; |
121 | 0 | this->SetData(&SHM_KEY, this, nullptr); |
122 | 0 | } |
123 | | |
124 | | private: |
125 | | void WriteShmemInfo() |
126 | 0 | { |
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 | | static size_t GetAlignedSize(const mozilla::gfx::IntSize& aSize, long aStride) |
156 | 0 | { |
157 | 0 | #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3) |
158 | 0 | return MOZ_ALIGN_WORD(sizeof(SharedImageInfo) + aSize.height * aStride); |
159 | 0 | } |
160 | | |
161 | | template<class ShmemAllocator, bool Unsafe> |
162 | | static already_AddRefed<Sub> |
163 | | Create(ShmemAllocator* aAllocator, |
164 | | const mozilla::gfx::IntSize& aSize, |
165 | | gfxImageFormat aFormat, |
166 | | SharedMemory::SharedMemoryType aShmType) |
167 | 0 | { |
168 | 0 | if (!mozilla::gfx::Factory::CheckSurfaceSize(aSize)) |
169 | 0 | return nullptr; |
170 | 0 | |
171 | 0 | Shmem shmem; |
172 | 0 | long stride = gfxImageSurface::ComputeStride(aSize, aFormat); |
173 | 0 | size_t size = GetAlignedSize(aSize, stride); |
174 | 0 | if (!Unsafe) { |
175 | 0 | if (!aAllocator->AllocShmem(size, aShmType, &shmem)) |
176 | 0 | return nullptr; |
177 | 0 | } else { |
178 | 0 | if (!aAllocator->AllocUnsafeShmem(size, aShmType, &shmem)) |
179 | 0 | return nullptr; |
180 | 0 | } |
181 | 0 | |
182 | 0 | 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 | 0 | } |
188 | 0 | s->WriteShmemInfo(); |
189 | 0 | return s.forget(); |
190 | 0 | } |
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 */ |