summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/ISurfaceAllocator.h
blob: ea69b0fc2cb21af0a658f4c5428582df4a226635 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef GFX_LAYERS_ISURFACEDEALLOCATOR
#define GFX_LAYERS_ISURFACEDEALLOCATOR

#include <stddef.h>  // for size_t
#include <stdint.h>  // for uint32_t
#include "gfxTypes.h"
#include "mozilla/gfx/Point.h"         // for IntSize
#include "mozilla/ipc/SharedMemory.h"  // for SharedMemory, etc
#include "mozilla/RefPtr.h"
#include "nsIMemoryReporter.h"              // for nsIMemoryReporter
#include "mozilla/Atomics.h"                // for Atomic
#include "mozilla/layers/LayersMessages.h"  // for ShmemSection

namespace mozilla {
namespace ipc {
class Shmem;
class IShmemAllocator;
}  // namespace ipc
namespace gfx {
class DataSourceSurface;
}  // namespace gfx

namespace layers {

class CompositableForwarder;
class CompositorBridgeParentBase;
class TextureForwarder;

class ShmemSectionAllocator;
class LegacySurfaceDescriptorAllocator;
class ClientIPCAllocator;
class HostIPCAllocator;
class LayersIPCChannel;

enum BufferCapabilities {
  DEFAULT_BUFFER_CAPS = 0,
  /**
   * The allocated buffer must be efficiently mappable as a DataSourceSurface.
   */
  MAP_AS_IMAGE_SURFACE = 1 << 0,
  /**
   * The allocated buffer will be used for GL rendering only
   */
  USING_GL_RENDERING_ONLY = 1 << 1
};

class SurfaceDescriptor;

/**
 * An interface used to create and destroy surfaces that are shared with the
 * Compositor process (using shmem, or other platform specific memory)
 *
 * Most of the methods here correspond to methods that are implemented by IPDL
 * actors without a common polymorphic interface.
 * These methods should be only called in the ipdl implementor's thread, unless
 * specified otherwise in the implementing class.
 */
class ISurfaceAllocator {
 public:
  MOZ_DECLARE_REFCOUNTED_TYPENAME(ISurfaceAllocator)
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ISurfaceAllocator)

  ISurfaceAllocator() = default;

  // down-casting

  virtual mozilla::ipc::IShmemAllocator* AsShmemAllocator() { return nullptr; }

  virtual ShmemSectionAllocator* AsShmemSectionAllocator() { return nullptr; }

  virtual CompositableForwarder* AsCompositableForwarder() { return nullptr; }

  virtual TextureForwarder* GetTextureForwarder() { return nullptr; }

  virtual ClientIPCAllocator* AsClientAllocator() { return nullptr; }

  virtual HostIPCAllocator* AsHostIPCAllocator() { return nullptr; }

  virtual LegacySurfaceDescriptorAllocator*
  AsLegacySurfaceDescriptorAllocator() {
    return nullptr;
  }

  virtual CompositorBridgeParentBase* AsCompositorBridgeParentBase() {
    return nullptr;
  }

  // ipc info

  virtual bool IPCOpen() const { return true; }

  virtual bool IsSameProcess() const = 0;

  virtual bool UsesImageBridge() const { return false; }

  virtual bool UsesWebRenderBridge() const { return false; }

 protected:
  void Finalize() {}

  virtual ~ISurfaceAllocator() = default;
};

/// Methods that are specific to the client/child side.
class ClientIPCAllocator : public ISurfaceAllocator {
 public:
  ClientIPCAllocator() = default;

  ClientIPCAllocator* AsClientAllocator() override { return this; }

  virtual base::ProcessId GetParentPid() const = 0;

  virtual MessageLoop* GetMessageLoop() const = 0;

  virtual void CancelWaitForNotifyNotUsed(uint64_t aTextureId) = 0;
};

/// Methods that are specific to the host/parent side.
class HostIPCAllocator : public ISurfaceAllocator {
 public:
  HostIPCAllocator() = default;

  HostIPCAllocator* AsHostIPCAllocator() override { return this; }

  /**
   * Get child side's process Id.
   */
  virtual base::ProcessId GetChildProcessId() = 0;

  virtual void NotifyNotUsed(PTextureParent* aTexture,
                             uint64_t aTransactionId) = 0;

  virtual void SendAsyncMessage(
      const nsTArray<AsyncParentMessageData>& aMessage) = 0;

  virtual void SendPendingAsyncMessages();

  virtual void SetAboutToSendAsyncMessages() {
    mAboutToSendAsyncMessages = true;
  }

  bool IsAboutToSendAsyncMessages() { return mAboutToSendAsyncMessages; }

 protected:
  std::vector<AsyncParentMessageData> mPendingAsyncMessage;
  bool mAboutToSendAsyncMessages = false;
};

/// An allocator that can group allocations in bigger chunks of shared memory.
///
/// The allocated shmem sections can only be deallocated by the same allocator
/// instance (and only in the child process).
class ShmemSectionAllocator {
 public:
  virtual bool AllocShmemSection(uint32_t aSize,
                                 ShmemSection* aShmemSection) = 0;

  virtual void DeallocShmemSection(ShmemSection& aShmemSection) = 0;

  virtual void MemoryPressure() {}
};

/// Some old stuff that's still around and used for screenshots.
///
/// New code should not need this (see TextureClient).
class LegacySurfaceDescriptorAllocator {
 public:
  virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize,
                                      gfxContentType aContent,
                                      SurfaceDescriptor* aBuffer) = 0;

  virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
                                              gfxContentType aContent,
                                              uint32_t aCaps,
                                              SurfaceDescriptor* aBuffer) = 0;

  virtual void DestroySurfaceDescriptor(SurfaceDescriptor* aSurface) = 0;
};

bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface);

already_AddRefed<gfx::DataSourceSurface> GetSurfaceForDescriptor(
    const SurfaceDescriptor& aDescriptor);

uint8_t* GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor);

void DestroySurfaceDescriptor(mozilla::ipc::IShmemAllocator* aAllocator,
                              SurfaceDescriptor* aSurface);

class GfxMemoryImageReporter final : public nsIMemoryReporter {
  ~GfxMemoryImageReporter() = default;

 public:
  NS_DECL_ISUPPORTS

  GfxMemoryImageReporter() {
#ifdef DEBUG
    // There must be only one instance of this class, due to |sAmount|
    // being static.
    static bool hasRun = false;
    MOZ_ASSERT(!hasRun);
    hasRun = true;
#endif
  }

  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)

  static void DidAlloc(void* aPointer) {
    sAmount += MallocSizeOfOnAlloc(aPointer);
  }

  static void WillFree(void* aPointer) {
    sAmount -= MallocSizeOfOnFree(aPointer);
  }

  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize) override {
    MOZ_COLLECT_REPORT(
        "explicit/gfx/heap-textures", KIND_HEAP, UNITS_BYTES, sAmount,
        "Heap memory shared between threads by texture clients and hosts.");

    return NS_OK;
  }

 private:
  // Typically we use |size_t| in memory reporters, but in the past this
  // variable has sometimes gone negative due to missing DidAlloc() calls.
  // Therefore, we use a signed type so that any such negative values show up
  // as negative in about:memory, rather than as enormous positive numbers.
  static mozilla::Atomic<ptrdiff_t> sAmount;
};

/// A simple shmem section allocator that can only allocate small
/// fixed size elements (only intended to be used to store tile
/// copy-on-write locks for now).
class FixedSizeSmallShmemSectionAllocator final : public ShmemSectionAllocator {
 public:
  enum AllocationStatus { STATUS_ALLOCATED, STATUS_FREED };

  struct ShmemSectionHeapHeader {
    Atomic<uint32_t> mTotalBlocks;
    Atomic<uint32_t> mAllocatedBlocks;
  };

  struct ShmemSectionHeapAllocation {
    Atomic<uint32_t> mStatus;
    uint32_t mSize;
  };

  explicit FixedSizeSmallShmemSectionAllocator(LayersIPCChannel* aShmProvider);

  ~FixedSizeSmallShmemSectionAllocator();

  bool AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection) override;

  void DeallocShmemSection(ShmemSection& aShmemSection) override;

  void MemoryPressure() override { ShrinkShmemSectionHeap(); }

  // can be called on the compositor process.
  static void FreeShmemSection(ShmemSection& aShmemSection);

  void ShrinkShmemSectionHeap();

  bool IPCOpen() const;

 protected:
  std::vector<mozilla::ipc::Shmem> mUsedShmems;
  LayersIPCChannel* mShmProvider;
};

}  // namespace layers
}  // namespace mozilla

#endif