/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 |