ISurfaceAllocator.h (9048B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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_LAYERS_ISURFACEDEALLOCATOR 8 #define GFX_LAYERS_ISURFACEDEALLOCATOR 9 10 #include <stddef.h> // for size_t 11 #include <stdint.h> // for uint32_t 12 #include "gfxTypes.h" 13 #include "mozilla/dom/ipc/IdType.h" 14 #include "mozilla/gfx/Point.h" // for IntSize 15 #include "nsIMemoryReporter.h" // for nsIMemoryReporter 16 #include "mozilla/Atomics.h" // for Atomic 17 #include "mozilla/layers/LayersMessages.h" // for ShmemSection 18 19 namespace mozilla { 20 namespace ipc { 21 class Shmem; 22 class IShmemAllocator; 23 } // namespace ipc 24 namespace gfx { 25 class DataSourceSurface; 26 } // namespace gfx 27 28 namespace layers { 29 30 class CompositableForwarder; 31 class CompositorBridgeParentBase; 32 class TextureForwarder; 33 34 class ShmemSectionAllocator; 35 class LegacySurfaceDescriptorAllocator; 36 class ClientIPCAllocator; 37 class HostIPCAllocator; 38 class LayersIPCChannel; 39 40 enum BufferCapabilities { 41 DEFAULT_BUFFER_CAPS = 0, 42 /** 43 * The allocated buffer must be efficiently mappable as a DataSourceSurface. 44 */ 45 MAP_AS_IMAGE_SURFACE = 1 << 0, 46 /** 47 * The allocated buffer will be used for GL rendering only 48 */ 49 USING_GL_RENDERING_ONLY = 1 << 1 50 }; 51 52 class SurfaceDescriptor; 53 54 /** 55 * An interface used to create and destroy surfaces that are shared with the 56 * Compositor process (using shmem, or other platform specific memory) 57 * 58 * Most of the methods here correspond to methods that are implemented by IPDL 59 * actors without a common polymorphic interface. 60 * These methods should be only called in the ipdl implementor's thread, unless 61 * specified otherwise in the implementing class. 62 */ 63 class ISurfaceAllocator { 64 public: 65 MOZ_DECLARE_REFCOUNTED_TYPENAME(ISurfaceAllocator) 66 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ISurfaceAllocator) 67 68 ISurfaceAllocator() = default; 69 70 // down-casting 71 72 virtual mozilla::ipc::IShmemAllocator* AsShmemAllocator() { return nullptr; } 73 74 virtual ShmemSectionAllocator* AsShmemSectionAllocator() { return nullptr; } 75 76 virtual CompositableForwarder* AsCompositableForwarder() { return nullptr; } 77 78 virtual TextureForwarder* GetTextureForwarder() { return nullptr; } 79 80 virtual ClientIPCAllocator* AsClientAllocator() { return nullptr; } 81 82 virtual HostIPCAllocator* AsHostIPCAllocator() { return nullptr; } 83 84 virtual LegacySurfaceDescriptorAllocator* 85 AsLegacySurfaceDescriptorAllocator() { 86 return nullptr; 87 } 88 89 virtual CompositorBridgeParentBase* AsCompositorBridgeParentBase() { 90 return nullptr; 91 } 92 93 // ipc info 94 95 virtual bool IPCOpen() const { return true; } 96 97 virtual bool IsSameProcess() const = 0; 98 99 virtual bool UsesImageBridge() const { return false; } 100 101 virtual bool UsesWebRenderBridge() const { return false; } 102 103 virtual dom::ContentParentId GetContentId() { return dom::ContentParentId(); } 104 105 protected: 106 void Finalize() {} 107 108 virtual ~ISurfaceAllocator() = default; 109 }; 110 111 /// Methods that are specific to the client/child side. 112 class ClientIPCAllocator : public ISurfaceAllocator { 113 public: 114 ClientIPCAllocator() = default; 115 116 ClientIPCAllocator* AsClientAllocator() override { return this; } 117 118 virtual base::ProcessId GetParentPid() const = 0; 119 120 virtual MessageLoop* GetMessageLoop() const = 0; 121 122 virtual void CancelWaitForNotifyNotUsed(uint64_t aTextureId) = 0; 123 }; 124 125 /// Methods that are specific to the host/parent side. 126 class HostIPCAllocator : public ISurfaceAllocator { 127 public: 128 HostIPCAllocator() = default; 129 130 HostIPCAllocator* AsHostIPCAllocator() override { return this; } 131 132 /** 133 * Get child side's process Id. 134 */ 135 virtual base::ProcessId GetChildProcessId() = 0; 136 137 virtual void NotifyNotUsed(PTextureParent* aTexture, 138 uint64_t aTransactionId) = 0; 139 140 virtual void SendAsyncMessage( 141 const nsTArray<AsyncParentMessageData>& aMessage) = 0; 142 143 virtual void SendPendingAsyncMessages(); 144 145 virtual void SetAboutToSendAsyncMessages() { 146 mAboutToSendAsyncMessages = true; 147 } 148 149 bool IsAboutToSendAsyncMessages() { return mAboutToSendAsyncMessages; } 150 151 protected: 152 std::vector<AsyncParentMessageData> mPendingAsyncMessage; 153 bool mAboutToSendAsyncMessages = false; 154 }; 155 156 class ShmemSection { 157 public: 158 static Maybe<ShmemSection> FromUntrusted( 159 const UntrustedShmemSection& aUntrusted); 160 bool Init(const mozilla::ipc::Shmem& aShm, uint32_t offset, uint32_t size); 161 UntrustedShmemSection AsUntrusted(); 162 163 uint32_t size() const { return mSize; } 164 uint32_t offset() const { return mOffset; } 165 const mozilla::ipc::Shmem& shmem() { return mShmem; } 166 167 private: 168 mozilla::ipc::Shmem mShmem; 169 uint32_t mOffset; 170 uint32_t mSize; 171 }; 172 173 /// An allocator that can group allocations in bigger chunks of shared memory. 174 /// 175 /// The allocated shmem sections can only be deallocated by the same allocator 176 /// instance (and only in the child process). 177 class ShmemSectionAllocator { 178 public: 179 virtual bool AllocShmemSection(uint32_t aSize, 180 ShmemSection* aShmemSection) = 0; 181 182 virtual void DeallocShmemSection(ShmemSection& aShmemSection) = 0; 183 184 virtual void MemoryPressure() {} 185 }; 186 187 /// Some old stuff that's still around and used for screenshots. 188 /// 189 /// New code should not need this (see TextureClient). 190 class LegacySurfaceDescriptorAllocator { 191 public: 192 virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize, 193 gfxContentType aContent, 194 SurfaceDescriptor* aBuffer) = 0; 195 196 virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize, 197 gfxContentType aContent, 198 uint32_t aCaps, 199 SurfaceDescriptor* aBuffer) = 0; 200 201 virtual void DestroySurfaceDescriptor(SurfaceDescriptor* aSurface) = 0; 202 }; 203 204 bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface); 205 206 already_AddRefed<gfx::DataSourceSurface> GetSurfaceForDescriptor( 207 const SurfaceDescriptor& aDescriptor); 208 209 uint8_t* GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor); 210 211 void DestroySurfaceDescriptor(mozilla::ipc::IShmemAllocator* aAllocator, 212 SurfaceDescriptor* aSurface); 213 214 class GfxMemoryImageReporter final : public nsIMemoryReporter { 215 ~GfxMemoryImageReporter() = default; 216 217 public: 218 NS_DECL_ISUPPORTS 219 220 GfxMemoryImageReporter() { 221 #ifdef DEBUG 222 // There must be only one instance of this class, due to |sAmount| 223 // being static. 224 static bool hasRun = false; 225 MOZ_ASSERT(!hasRun); 226 hasRun = true; 227 #endif 228 } 229 230 MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc) 231 MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree) 232 233 static void DidAlloc(void* aPointer) { 234 sAmount += MallocSizeOfOnAlloc(aPointer); 235 } 236 237 static void WillFree(void* aPointer) { 238 sAmount -= MallocSizeOfOnFree(aPointer); 239 } 240 241 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport, 242 nsISupports* aData, bool aAnonymize) override { 243 MOZ_COLLECT_REPORT( 244 "explicit/gfx/heap-textures", KIND_HEAP, UNITS_BYTES, sAmount, 245 "Heap memory shared between threads by texture clients and hosts."); 246 247 return NS_OK; 248 } 249 250 private: 251 // Typically we use |size_t| in memory reporters, but in the past this 252 // variable has sometimes gone negative due to missing DidAlloc() calls. 253 // Therefore, we use a signed type so that any such negative values show up 254 // as negative in about:memory, rather than as enormous positive numbers. 255 static mozilla::Atomic<ptrdiff_t> sAmount; 256 }; 257 258 /// A simple shmem section allocator that can only allocate small 259 /// fixed size elements (only intended to be used to store tile 260 /// copy-on-write locks for now). 261 class FixedSizeSmallShmemSectionAllocator final : public ShmemSectionAllocator { 262 public: 263 NS_DECL_OWNINGTHREAD 264 265 enum AllocationStatus { STATUS_ALLOCATED, STATUS_FREED }; 266 267 struct ShmemSectionHeapHeader { 268 Atomic<uint32_t> mTotalBlocks; 269 Atomic<uint32_t> mAllocatedBlocks; 270 }; 271 272 struct ShmemSectionHeapAllocation { 273 Atomic<uint32_t> mStatus; 274 uint32_t mSize; 275 }; 276 277 explicit FixedSizeSmallShmemSectionAllocator(LayersIPCChannel* aShmProvider); 278 279 ~FixedSizeSmallShmemSectionAllocator(); 280 281 bool AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection) override; 282 283 void DeallocShmemSection(ShmemSection& aShmemSection) override; 284 285 void MemoryPressure() override { ShrinkShmemSectionHeap(); } 286 287 // can be called on the compositor process. 288 static void FreeShmemSection(ShmemSection& aShmemSection); 289 290 void ShrinkShmemSectionHeap(); 291 292 bool IPCOpen() const; 293 294 protected: 295 std::vector<mozilla::ipc::Shmem> mUsedShmems; 296 LayersIPCChannel* mShmProvider; 297 }; 298 299 } // namespace layers 300 } // namespace mozilla 301 302 #endif