gfx/thebes/gfxBaseSharedMemorySurface.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial