Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/layers/ImageBridgeChild.h
Line
Count
Source (jump to first uncovered line)
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 MOZILLA_GFX_IMAGEBRIDGECHILD_H
8
#define MOZILLA_GFX_IMAGEBRIDGECHILD_H
9
10
#include <stddef.h>                     // for size_t
11
#include <stdint.h>                     // for uint32_t, uint64_t
12
#include <unordered_map>
13
14
#include "mozilla/Attributes.h"         // for override
15
#include "mozilla/Atomics.h"
16
#include "mozilla/RefPtr.h"             // for already_AddRefed
17
#include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
18
#include "mozilla/layers/CanvasClient.h"
19
#include "mozilla/layers/CompositableForwarder.h"
20
#include "mozilla/layers/CompositorTypes.h"
21
#include "mozilla/layers/PImageBridgeChild.h"
22
#include "mozilla/Mutex.h"
23
#include "mozilla/webrender/WebRenderTypes.h"
24
#include "nsIObserver.h"
25
#include "nsRegion.h"                   // for nsIntRegion
26
#include "mozilla/gfx/Rect.h"
27
#include "mozilla/ReentrantMonitor.h"   // for ReentrantMonitor, etc
28
29
class MessageLoop;
30
31
namespace base {
32
class Thread;
33
} // namespace base
34
35
namespace mozilla {
36
namespace ipc {
37
class Shmem;
38
} // namespace ipc
39
40
namespace layers {
41
42
class AsyncCanvasRenderer;
43
class ImageClient;
44
class ImageContainer;
45
class ImageContainerListener;
46
class ImageBridgeParent;
47
class CompositableClient;
48
struct CompositableTransaction;
49
class Image;
50
class TextureClient;
51
class SynchronousTask;
52
struct AllocShmemParams;
53
54
/**
55
 * Returns true if the current thread is the ImageBrdigeChild's thread.
56
 *
57
 * Can be called from any thread.
58
 */
59
bool InImageBridgeChildThread();
60
61
/**
62
 * The ImageBridge protocol is meant to allow ImageContainers to forward images
63
 * directly to the compositor thread/process without using the main thread.
64
 *
65
 * ImageBridgeChild is a CompositableForwarder just like ShadowLayerForwarder.
66
 * This means it also does transactions with the compositor thread/process,
67
 * except that the transactions are restricted to operations on the Compositables
68
 * and cannot contain messages affecting layers directly.
69
 *
70
 * ImageBridgeChild is also a ISurfaceAllocator. It can be used to allocate or
71
 * deallocate data that is shared with the compositor. The main differerence
72
 * with other ISurfaceAllocators is that some of its overriden methods can be
73
 * invoked from any thread.
74
 *
75
 * There are three important phases in the ImageBridge protocol. These three steps
76
 * can do different things depending if (A) the ImageContainer uses ImageBridge
77
 * or (B) it does not use ImageBridge:
78
 *
79
 * - When an ImageContainer calls its method SetCurrentImage:
80
 *   - (A) The image is sent directly to the compositor process through the
81
 *   ImageBridge IPDL protocol.
82
 *   On the compositor side the image is stored in a global table that associates
83
 *   the image with an ID corresponding to the ImageContainer, and a composition is
84
 *   triggered.
85
 *   - (B) Since it does not have an ImageBridge, the image is not sent yet.
86
 *   instead the will be sent to the compositor during the next layer transaction
87
 *   (on the main thread).
88
 *
89
 * - During a Layer transaction:
90
 *   - (A) The ImageContainer uses ImageBridge. The image is already available to the
91
 *   compositor process because it has been sent with SetCurrentImage. Yet, the
92
 *   CompositableHost on the compositor side will needs the ID referring to the
93
 *   ImageContainer to access the Image. So during the Swap operation that happens
94
 *   in the transaction, we swap the container ID rather than the image data.
95
 *   - (B) Since the ImageContainer does not use ImageBridge, the image data is swaped.
96
 *
97
 * - During composition:
98
 *   - (A) The CompositableHost has an AsyncID, it looks up the ID in the
99
 *   global table to see if there is an image. If there is no image, nothing is rendered.
100
 *   - (B) The CompositableHost has image data rather than an ID (meaning it is not
101
 *   using ImageBridge), then it just composites the image data normally.
102
 *
103
 * This means that there might be a possibility for the ImageBridge to send the first
104
 * frame before the first layer transaction that will pass the container ID to the
105
 * CompositableHost happens. In this (unlikely) case the layer is not composited
106
 * until the layer transaction happens. This means this scenario is not harmful.
107
 *
108
 * Since sending an image through imageBridge triggers compositing, the main thread is
109
 * not used at all (except for the very first transaction that provides the
110
 * CompositableHost with an AsyncID).
111
 */
112
class ImageBridgeChild final : public PImageBridgeChild
113
                             , public CompositableForwarder
114
                             , public TextureForwarder
115
{
116
  friend class ImageContainer;
117
118
  typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
119
public:
120
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageBridgeChild, override);
121
122
0
  TextureForwarder* GetTextureForwarder() override { return this; }
123
0
  LayersIPCActor* GetLayersIPCActor() override { return this; }
124
125
  /**
126
   * Creates the image bridge with a dedicated thread for ImageBridgeChild.
127
   *
128
   * We may want to use a specifi thread in the future. In this case, use
129
   * CreateWithThread instead.
130
   */
131
  static void InitSameProcess(uint32_t aNamespace);
132
133
  static void InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint, uint32_t aNamespace);
134
  static bool InitForContent(Endpoint<PImageBridgeChild>&& aEndpoint, uint32_t aNamespace);
135
  static bool ReinitForContent(Endpoint<PImageBridgeChild>&& aEndpoint, uint32_t aNamespace);
136
137
  /**
138
   * Destroys the image bridge by calling DestroyBridge, and destroys the
139
   * ImageBridge's thread.
140
   *
141
   * If you don't want to destroy the thread, call DestroyBridge directly
142
   * instead.
143
   */
144
  static void ShutDown();
145
146
  /**
147
   * returns the singleton instance.
148
   *
149
   * can be called from any thread.
150
   */
151
  static RefPtr<ImageBridgeChild> GetSingleton();
152
153
154
  static void IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier);
155
156
  void BeginTransaction();
157
  void EndTransaction();
158
159
  /**
160
   * Returns the ImageBridgeChild's thread.
161
   *
162
   * Can be called from any thread.
163
   */
164
  base::Thread * GetThread() const;
165
166
  /**
167
   * Returns the ImageBridgeChild's message loop.
168
   *
169
   * Can be called from any thread.
170
   */
171
  virtual MessageLoop * GetMessageLoop() const override;
172
173
0
  virtual base::ProcessId GetParentPid() const override { return OtherPid(); }
174
175
  virtual PTextureChild*
176
  AllocPTextureChild(const SurfaceDescriptor& aSharedData,
177
                     const ReadLockDescriptor& aReadLock,
178
                     const LayersBackend& aLayersBackend,
179
                     const TextureFlags& aFlags,
180
                     const uint64_t& aSerial,
181
                     const wr::MaybeExternalImageId& aExternalImageId) override;
182
183
  virtual bool
184
  DeallocPTextureChild(PTextureChild* actor) override;
185
186
  PMediaSystemResourceManagerChild*
187
  AllocPMediaSystemResourceManagerChild() override;
188
  bool
189
  DeallocPMediaSystemResourceManagerChild(PMediaSystemResourceManagerChild* aActor) override;
190
191
  virtual mozilla::ipc::IPCResult
192
  RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
193
194
  virtual mozilla::ipc::IPCResult
195
  RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&& aNotifications) override;
196
197
  virtual mozilla::ipc::IPCResult
198
  RecvReportFramesDropped(const CompositableHandle& aHandle, const uint32_t& aFrames) override;
199
200
  // Create an ImageClient from any thread.
201
  RefPtr<ImageClient> CreateImageClient(
202
    CompositableType aType,
203
    ImageContainer* aImageContainer);
204
205
  // Create an ImageClient from the ImageBridge thread.
206
  RefPtr<ImageClient> CreateImageClientNow(
207
    CompositableType aType,
208
    ImageContainer* aImageContainer);
209
210
  already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClient::CanvasClientType aType,
211
                                                    TextureFlags aFlag);
212
  void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient);
213
  void UpdateImageClient(RefPtr<ImageContainer> aContainer);
214
215
  /**
216
   * Flush all Images sent to CompositableHost.
217
   */
218
  void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer);
219
220
0
  virtual bool IPCOpen() const override { return mCanSend; }
221
222
private:
223
224
  /**
225
   * This must be called by the static function DeleteImageBridgeSync defined
226
   * in ImageBridgeChild.cpp ONLY.
227
   */
228
  ~ImageBridgeChild();
229
230
  // Helpers for dispatching.
231
  already_AddRefed<CanvasClient> CreateCanvasClientNow(
232
    CanvasClient::CanvasClientType aType,
233
    TextureFlags aFlags);
234
  void CreateCanvasClientSync(
235
    SynchronousTask* aTask,
236
    CanvasClient::CanvasClientType aType,
237
    TextureFlags aFlags,
238
    RefPtr<CanvasClient>* const outResult);
239
240
  void CreateImageClientSync(
241
    SynchronousTask* aTask,
242
    RefPtr<ImageClient>* result,
243
    CompositableType aType,
244
    ImageContainer* aImageContainer);
245
246
  void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient);
247
  void UpdateAsyncCanvasRendererSync(
248
    SynchronousTask* aTask,
249
    AsyncCanvasRenderer* aWrapper);
250
251
  void FlushAllImagesSync(
252
    SynchronousTask* aTask,
253
    ImageClient* aClient,
254
    ImageContainer* aContainer);
255
256
  void ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams);
257
  void ProxyDeallocShmemNow(SynchronousTask* aTask, Shmem* aShmem, bool* aResult);
258
259
  void UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aIdentifier);
260
261
public:
262
  // CompositableForwarder
263
264
  virtual void Connect(CompositableClient* aCompositable,
265
                       ImageContainer* aImageContainer) override;
266
267
0
  virtual bool UsesImageBridge() const override { return true; }
268
269
  /**
270
   * See CompositableForwarder::UseTextures
271
   */
272
  virtual void UseTextures(CompositableClient* aCompositable,
273
                           const nsTArray<TimedTextureClient>& aTextures) override;
274
  virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
275
                                         TextureClient* aClientOnBlack,
276
                                         TextureClient* aClientOnWhite) override;
277
278
  void ReleaseCompositable(const CompositableHandle& aHandle) override;
279
280
  void ForgetImageContainer(const CompositableHandle& aHandle);
281
282
  /**
283
   * Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
284
   * Host side's usage is checked via CompositableRef.
285
   */
286
  void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);
287
288
  /**
289
   * Notify id of Texture When host side end its use. Transaction id is used to
290
   * make sure if there is no newer usage.
291
   */
292
  void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
293
294
  virtual void CancelWaitForRecycle(uint64_t aTextureId) override;
295
296
  virtual bool DestroyInTransaction(PTextureChild* aTexture) override;
297
  bool DestroyInTransaction(const CompositableHandle& aHandle);
298
299
  virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
300
                                             TextureClient* aTexture) override;
301
302
  virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
303
                                   const SurfaceDescriptorTiles& aTileLayerDescriptor) override
304
0
  {
305
0
    MOZ_CRASH("should not be called");
306
0
  }
307
308
  virtual void UpdateTextureRegion(CompositableClient* aCompositable,
309
                                   const ThebesBufferData& aThebesBufferData,
310
0
                                   const nsIntRegion& aUpdatedRegion) override {
311
0
    MOZ_CRASH("should not be called");
312
0
  }
313
314
  // ISurfaceAllocator
315
316
  /**
317
   * See ISurfaceAllocator.h
318
   * Can be used from any thread.
319
   * If used outside the ImageBridgeChild thread, it will proxy a synchronous
320
   * call on the ImageBridgeChild thread.
321
   */
322
  virtual bool AllocUnsafeShmem(size_t aSize,
323
                                mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
324
                                mozilla::ipc::Shmem* aShmem) override;
325
  virtual bool AllocShmem(size_t aSize,
326
                          mozilla::ipc::SharedMemory::SharedMemoryType aShmType,
327
                          mozilla::ipc::Shmem* aShmem) override;
328
329
  /**
330
   * See ISurfaceAllocator.h
331
   * Can be used from any thread.
332
   * If used outside the ImageBridgeChild thread, it will proxy a synchronous
333
   * call on the ImageBridgeChild thread.
334
   */
335
  virtual bool DeallocShmem(mozilla::ipc::Shmem& aShmem) override;
336
337
  virtual PTextureChild* CreateTexture(
338
    const SurfaceDescriptor& aSharedData,
339
    const ReadLockDescriptor& aReadLock,
340
    LayersBackend aLayersBackend,
341
    TextureFlags aFlags,
342
    uint64_t aSerial,
343
    wr::MaybeExternalImageId& aExternalImageId,
344
    nsIEventTarget* aTarget = nullptr) override;
345
346
  virtual bool IsSameProcess() const override;
347
348
0
  virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; }
349
0
  virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; }
350
351
0
  bool InForwarderThread() override {
352
0
    return InImageBridgeChildThread();
353
0
  }
354
355
  virtual void HandleFatalError(const char* aMsg) const override;
356
357
  virtual wr::MaybeExternalImageId GetNextExternalImageId() override;
358
359
protected:
360
  explicit ImageBridgeChild(uint32_t aNamespace);
361
  bool DispatchAllocShmemInternal(size_t aSize,
362
                                  SharedMemory::SharedMemoryType aType,
363
                                  Shmem* aShmem,
364
                                  bool aUnsafe);
365
366
  void Bind(Endpoint<PImageBridgeChild>&& aEndpoint);
367
  void BindSameProcess(RefPtr<ImageBridgeParent> aParent);
368
369
  void SendImageBridgeThreadId();
370
371
  void WillShutdown();
372
  void ShutdownStep1(SynchronousTask* aTask);
373
  void ShutdownStep2(SynchronousTask* aTask);
374
  void MarkShutDown();
375
376
  void ActorDestroy(ActorDestroyReason aWhy) override;
377
  void DeallocPImageBridgeChild() override;
378
379
  bool CanSend() const;
380
  bool CanPostTask() const;
381
382
  static void ShutdownSingleton();
383
384
private:
385
  uint32_t mNamespace;
386
387
  CompositableTransaction* mTxn;
388
389
  bool mCanSend;
390
  mozilla::Atomic<bool> mDestroyed;
391
392
  /**
393
   * Transaction id of CompositableForwarder.
394
   * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
395
   */
396
  uint64_t mFwdTransactionId;
397
398
  /**
399
   * Hold TextureClients refs until end of their usages on host side.
400
   * It defer calling of TextureClient recycle callback.
401
   */
402
  std::unordered_map<uint64_t, RefPtr<TextureClient>> mTexturesWaitingRecycled;
403
404
  /**
405
   * Mapping from async compositable IDs to image containers.
406
   */
407
  Mutex mContainerMapLock;
408
  std::unordered_map<uint64_t, RefPtr<ImageContainerListener>> mImageContainerListeners;
409
  RefPtr<ImageContainerListener> FindListener(const CompositableHandle& aHandle);
410
411
#if defined(XP_WIN)
412
  /**
413
   * Used for checking if D3D11Device is updated.
414
   */
415
  RefPtr<ID3D11Device> mImageDevice;
416
#endif
417
};
418
419
} // namespace layers
420
} // namespace mozilla
421
422
#endif