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