Coverage Report

Created: 2018-09-25 14:53

/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 */