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