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