Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=8 et :
3 : */
4 : /* This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #ifndef mozilla_layers_ShadowLayers_h
9 : #define mozilla_layers_ShadowLayers_h 1
10 :
11 : #include <stddef.h> // for size_t
12 : #include <stdint.h> // for uint64_t
13 : #include "gfxTypes.h"
14 : #include "mozilla/Attributes.h" // for override
15 : #include "mozilla/gfx/Rect.h"
16 : #include "mozilla/WidgetUtils.h" // for ScreenRotation
17 : #include "mozilla/dom/ScreenOrientation.h" // for ScreenOrientation
18 : #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
19 : #include "mozilla/layers/CompositableForwarder.h"
20 : #include "mozilla/layers/FocusTarget.h"
21 : #include "mozilla/layers/LayersTypes.h"
22 : #include "mozilla/layers/TextureForwarder.h"
23 : #include "mozilla/layers/CompositorTypes.h" // for OpenMode, etc
24 : #include "mozilla/layers/CompositorBridgeChild.h"
25 : #include "nsCOMPtr.h" // for already_AddRefed
26 : #include "nsRegion.h" // for nsIntRegion
27 : #include "nsTArrayForwardDeclare.h" // for InfallibleTArray
28 : #include "nsIWidget.h"
29 : #include <vector>
30 : #include "nsExpirationTracker.h"
31 :
32 : namespace mozilla {
33 : namespace layers {
34 :
35 : class ClientLayerManager;
36 : class CompositorBridgeChild;
37 : class FixedSizeSmallShmemSectionAllocator;
38 : class ImageContainer;
39 : class Layer;
40 : class PLayerTransactionChild;
41 : class LayerTransactionChild;
42 : class ShadowableLayer;
43 : class SurfaceDescriptor;
44 : class TextureClient;
45 : class ThebesBuffer;
46 : class ThebesBufferData;
47 : class Transaction;
48 :
49 : /**
50 : * See ActiveResourceTracker below.
51 : */
52 0 : class ActiveResource
53 : {
54 : public:
55 : virtual void NotifyInactive() = 0;
56 0 : nsExpirationState* GetExpirationState() { return &mExpirationState; }
57 0 : bool IsActivityTracked() { return mExpirationState.IsTracked(); }
58 : private:
59 : nsExpirationState mExpirationState;
60 : };
61 :
62 : /**
63 : * A convenience class on top of nsExpirationTracker
64 : */
65 0 : class ActiveResourceTracker : public nsExpirationTracker<ActiveResource, 3>
66 : {
67 : public:
68 2 : ActiveResourceTracker(uint32_t aExpirationCycle, const char* aName,
69 : nsIEventTarget* aEventTarget)
70 2 : : nsExpirationTracker(aExpirationCycle, aName, aEventTarget)
71 2 : {}
72 :
73 0 : virtual void NotifyExpired(ActiveResource* aResource) override
74 : {
75 0 : RemoveObject(aResource);
76 0 : aResource->NotifyInactive();
77 0 : }
78 : };
79 :
80 : /**
81 : * We want to share layer trees across thread contexts and address
82 : * spaces for several reasons; chief among them
83 : *
84 : * - a parent process can paint a child process's layer tree while
85 : * the child process is blocked, say on content script. This is
86 : * important on mobile devices where UI responsiveness is key.
87 : *
88 : * - a dedicated "compositor" process can asynchronously (wrt the
89 : * browser process) composite and animate layer trees, allowing a
90 : * form of pipeline parallelism between compositor/browser/content
91 : *
92 : * - a dedicated "compositor" process can take all responsibility for
93 : * accessing the GPU, which is desirable on systems with
94 : * buggy/leaky drivers because the compositor process can die while
95 : * browser and content live on (and failover mechanisms can be
96 : * installed to quickly bring up a replacement compositor)
97 : *
98 : * The Layers model has a crisply defined API, which makes it easy to
99 : * safely "share" layer trees. The ShadowLayers API extends Layers to
100 : * allow a remote, parent process to access a child process's layer
101 : * tree.
102 : *
103 : * ShadowLayerForwarder publishes a child context's layer tree to a
104 : * parent context. This comprises recording layer-tree modifications
105 : * into atomic transactions and pushing them over IPC.
106 : *
107 : * LayerManagerComposite grafts layer subtrees published by child-context
108 : * ShadowLayerForwarder(s) into a parent-context layer tree.
109 : *
110 : * (Advanced note: because our process tree may have a height >2, a
111 : * non-leaf subprocess may both receive updates from child processes
112 : * and publish them to parent processes. Put another way,
113 : * LayerManagers may be both LayerManagerComposites and
114 : * ShadowLayerForwarders.)
115 : *
116 : * There are only shadow types for layers that have different shadow
117 : * vs. not-shadow behavior. ColorLayers and ContainerLayers behave
118 : * the same way in both regimes (so far).
119 : *
120 : *
121 : * The mecanism to shadow the layer tree on the compositor through IPC works as
122 : * follows:
123 : * The layer tree is managed on the content thread, and shadowed in the compositor
124 : * thread. The shadow layer tree is only kept in sync with whatever happens in
125 : * the content thread. To do this we use IPDL protocols. IPDL is a domain
126 : * specific language that describes how two processes or thread should
127 : * communicate. C++ code is generated from .ipdl files to implement the message
128 : * passing, synchronization and serialization logic. To use the generated code
129 : * we implement classes that inherit the generated IPDL actor. the ipdl actors
130 : * of a protocol PX are PXChild or PXParent (the generated class), and we
131 : * conventionally implement XChild and XParent. The Parent side of the protocol
132 : * is the one that lives on the compositor thread. Think of IPDL actors as
133 : * endpoints of communication. they are useful to send messages and also to
134 : * dispatch the message to the right actor on the other side. One nice property
135 : * of an IPDL actor is that when an actor, say PXChild is sent in a message, the
136 : * PXParent comes out in the other side. we use this property a lot to dispatch
137 : * messages to the right layers and compositable, each of which have their own
138 : * ipdl actor on both side.
139 : *
140 : * Most of the synchronization logic happens in layer transactions and
141 : * compositable transactions.
142 : * A transaction is a set of changes to the layers and/or the compositables
143 : * that are sent and applied together to the compositor thread to keep the
144 : * LayerComposite in a coherent state.
145 : * Layer transactions maintain the shape of the shadow layer tree, and
146 : * synchronize the texture data held by compositables. Layer transactions
147 : * are always between the content thread and the compositor thread.
148 : * Compositable transactions are subset of a layer transaction with which only
149 : * compositables and textures can be manipulated, and does not always originate
150 : * from the content thread. (See CompositableForwarder.h and ImageBridgeChild.h)
151 : */
152 :
153 : class ShadowLayerForwarder final : public LayersIPCActor
154 : , public CompositableForwarder
155 : , public LegacySurfaceDescriptorAllocator
156 : {
157 : friend class ClientLayerManager;
158 :
159 : public:
160 112 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ShadowLayerForwarder, override);
161 :
162 : /**
163 : * Setup the IPDL actor for aCompositable to be part of layers
164 : * transactions.
165 : */
166 : void Connect(CompositableClient* aCompositable,
167 : ImageContainer* aImageContainer) override;
168 :
169 : /**
170 : * Adds an edit in the layers transaction in order to attach
171 : * the corresponding compositable and layer on the compositor side.
172 : * Connect must have been called on aCompositable beforehand.
173 : */
174 : void Attach(CompositableClient* aCompositable,
175 : ShadowableLayer* aLayer);
176 :
177 : /**
178 : * Adds an edit in the transaction in order to attach a Compositable that
179 : * is not managed by this ShadowLayerForwarder (for example, by ImageBridge
180 : * in the case of async-video).
181 : * Since the compositable is not managed by this forwarder, we can't use
182 : * the compositable or it's IPDL actor here, so we use an ID instead, that
183 : * is matched on the compositor side.
184 : */
185 : void AttachAsyncCompositable(const CompositableHandle& aHandle,
186 : ShadowableLayer* aLayer);
187 :
188 : /**
189 : * Begin recording a transaction to be forwarded atomically to a
190 : * LayerManagerComposite.
191 : */
192 : void BeginTransaction(const gfx::IntRect& aTargetBounds,
193 : ScreenRotation aRotation,
194 : mozilla::dom::ScreenOrientationInternal aOrientation);
195 :
196 : /**
197 : * The following methods may only be called after BeginTransaction()
198 : * but before EndTransaction(). They mirror the LayerManager
199 : * interface in Layers.h.
200 : */
201 :
202 : /**
203 : * Notify the shadow manager that a new, "real" layer has been
204 : * created, and a corresponding shadow layer should be created in
205 : * the compositing process.
206 : */
207 : void CreatedPaintedLayer(ShadowableLayer* aThebes);
208 : void CreatedContainerLayer(ShadowableLayer* aContainer);
209 : void CreatedImageLayer(ShadowableLayer* aImage);
210 : void CreatedColorLayer(ShadowableLayer* aColor);
211 : void CreatedCanvasLayer(ShadowableLayer* aCanvas);
212 : void CreatedRefLayer(ShadowableLayer* aRef);
213 : void CreatedTextLayer(ShadowableLayer* aRef);
214 : void CreatedBorderLayer(ShadowableLayer* aRef);
215 :
216 : /**
217 : * At least one attribute of |aMutant| has changed, and |aMutant|
218 : * needs to sync to its shadow layer. This initial implementation
219 : * forwards all attributes when any of the appropriate attribute
220 : * set is mutated.
221 : */
222 : void Mutated(ShadowableLayer* aMutant);
223 : void MutatedSimple(ShadowableLayer* aMutant);
224 :
225 : void SetRoot(ShadowableLayer* aRoot);
226 : /**
227 : * Insert |aChild| after |aAfter| in |aContainer|. |aAfter| can be
228 : * nullptr to indicated that |aChild| should be appended to the end of
229 : * |aContainer|'s child list.
230 : */
231 : void InsertAfter(ShadowableLayer* aContainer,
232 : ShadowableLayer* aChild,
233 : ShadowableLayer* aAfter = nullptr);
234 : void RemoveChild(ShadowableLayer* aContainer,
235 : ShadowableLayer* aChild);
236 : void RepositionChild(ShadowableLayer* aContainer,
237 : ShadowableLayer* aChild,
238 : ShadowableLayer* aAfter = nullptr);
239 :
240 : /**
241 : * Set aMaskLayer as the mask on aLayer.
242 : * Note that only image layers are properly supported
243 : * LayerTransactionParent::UpdateMask and accompanying ipdl
244 : * will need changing to update properties for other kinds
245 : * of mask layer.
246 : */
247 : void SetMask(ShadowableLayer* aLayer,
248 : ShadowableLayer* aMaskLayer);
249 :
250 : /**
251 : * See CompositableForwarder::UseTiledLayerBuffer
252 : */
253 : void UseTiledLayerBuffer(CompositableClient* aCompositable,
254 : const SurfaceDescriptorTiles& aTileLayerDescriptor) override;
255 :
256 : void ReleaseCompositable(const CompositableHandle& aHandle) override;
257 : bool DestroyInTransaction(PTextureChild* aTexture) override;
258 : bool DestroyInTransaction(const CompositableHandle& aHandle);
259 :
260 : virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
261 : TextureClient* aTexture) override;
262 :
263 : /**
264 : * Communicate to the compositor that aRegion in the texture identified by aLayer
265 : * and aIdentifier has been updated to aThebesBuffer.
266 : */
267 : virtual void UpdateTextureRegion(CompositableClient* aCompositable,
268 : const ThebesBufferData& aThebesBufferData,
269 : const nsIntRegion& aUpdatedRegion) override;
270 :
271 : /**
272 : * See CompositableForwarder::UseTextures
273 : */
274 : virtual void UseTextures(CompositableClient* aCompositable,
275 : const nsTArray<TimedTextureClient>& aTextures) override;
276 : virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
277 : TextureClient* aClientOnBlack,
278 : TextureClient* aClientOnWhite) override;
279 :
280 : /**
281 : * Used for debugging to tell the compositor how long this frame took to paint.
282 : */
283 : void SendPaintTime(uint64_t aId, TimeDuration aPaintTime);
284 :
285 : /**
286 : * End the current transaction and forward it to LayerManagerComposite.
287 : * |aReplies| are directions from the LayerManagerComposite to the
288 : * caller of EndTransaction().
289 : */
290 : bool EndTransaction(const nsIntRegion& aRegionToClear,
291 : uint64_t aId,
292 : bool aScheduleComposite,
293 : uint32_t aPaintSequenceNumber,
294 : bool aIsRepeatTransaction,
295 : const mozilla::TimeStamp& aTransactionStart,
296 : bool* aSent);
297 :
298 : /**
299 : * Set an actor through which layer updates will be pushed.
300 : */
301 : void SetShadowManager(PLayerTransactionChild* aShadowManager);
302 :
303 : /**
304 : * Layout calls here to cache current plugin widget configuration
305 : * data. We ship this across with the rest of the layer updates when
306 : * we update. Chrome handles applying these changes.
307 : */
308 : void StorePluginWidgetConfigurations(const nsTArray<nsIWidget::Configuration>&
309 : aConfigurations);
310 :
311 : void StopReceiveAsyncParentMessge();
312 :
313 : void ClearCachedResources();
314 :
315 : void Composite();
316 :
317 : /**
318 : * True if this is forwarding to a LayerManagerComposite.
319 : */
320 829 : bool HasShadowManager() const { return !!mShadowManager; }
321 0 : LayerTransactionChild* GetShadowManager() const { return mShadowManager.get(); }
322 :
323 : // Send a synchronous message asking the LayerTransactionParent in the
324 : // compositor to shutdown.
325 : void SynchronouslyShutdown();
326 :
327 0 : virtual void WindowOverlayChanged() { mWindowOverlayChanged = true; }
328 :
329 : /**
330 : * The following Alloc/Open/Destroy interfaces abstract over the
331 : * details of working with surfaces that are shared across
332 : * processes. They provide the glue between C++ Layers and the
333 : * LayerComposite IPC system.
334 : *
335 : * The basic lifecycle is
336 : *
337 : * - a Layer needs a buffer. Its ShadowableLayer subclass calls
338 : * AllocBuffer(), then calls one of the Created*Buffer() methods
339 : * above to transfer the (temporary) front buffer to its
340 : * LayerComposite in the other process. The Layer needs a
341 : * gfxASurface to paint, so the ShadowableLayer uses
342 : * OpenDescriptor(backBuffer) to get that surface, and hands it
343 : * out to the Layer.
344 : *
345 : * - a Layer has painted new pixels. Its ShadowableLayer calls one
346 : * of the Painted*Buffer() methods above with the back buffer
347 : * descriptor. This notification is forwarded to the LayerComposite,
348 : * which uses OpenDescriptor() to access the newly-painted pixels.
349 : * The LayerComposite then updates its front buffer in a Layer- and
350 : * platform-dependent way, and sends a surface descriptor back to
351 : * the ShadowableLayer that becomes its new back back buffer.
352 : *
353 : * - a Layer wants to destroy its buffers. Its ShadowableLayer
354 : * calls Destroyed*Buffer(), which gives up control of the back
355 : * buffer descriptor. The actual back buffer surface is then
356 : * destroyed using DestroySharedSurface() just before notifying
357 : * the parent process. When the parent process is notified, the
358 : * LayerComposite also calls DestroySharedSurface() on its front
359 : * buffer, and the double-buffer pair is gone.
360 : */
361 :
362 : virtual bool IPCOpen() const override;
363 :
364 : /**
365 : * Construct a shadow of |aLayer| on the "other side", at the
366 : * LayerManagerComposite.
367 : */
368 : LayerHandle ConstructShadowFor(ShadowableLayer* aLayer);
369 :
370 : /**
371 : * Flag the next paint as the first for a document.
372 : */
373 3 : void SetIsFirstPaint() { mIsFirstPaint = true; }
374 :
375 : /**
376 : * Set the current focus target to be sent with the next paint.
377 : */
378 29 : void SetFocusTarget(const FocusTarget& aFocusTarget) { mFocusTarget = aFocusTarget; }
379 :
380 : void SetLayerObserverEpoch(uint64_t aLayerObserverEpoch);
381 :
382 : static void PlatformSyncBeforeUpdate();
383 :
384 : virtual bool AllocSurfaceDescriptor(const gfx::IntSize& aSize,
385 : gfxContentType aContent,
386 : SurfaceDescriptor* aBuffer) override;
387 :
388 : virtual bool AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
389 : gfxContentType aContent,
390 : uint32_t aCaps,
391 : SurfaceDescriptor* aBuffer) override;
392 :
393 : virtual void DestroySurfaceDescriptor(SurfaceDescriptor* aSurface) override;
394 :
395 : virtual void UpdateFwdTransactionId() override;
396 : virtual uint64_t GetFwdTransactionId() override;
397 :
398 : void ReleaseLayer(const LayerHandle& aHandle);
399 :
400 129 : bool InForwarderThread() override {
401 129 : return NS_IsMainThread();
402 : }
403 :
404 0 : PaintTiming& GetPaintTiming() {
405 0 : return mPaintTiming;
406 : }
407 :
408 9 : ShadowLayerForwarder* AsLayerForwarder() override { return this; }
409 :
410 : // Returns true if aSurface wraps a Shmem.
411 : static bool IsShmem(SurfaceDescriptor* aSurface);
412 :
413 : /**
414 : * Sends a synchronous ping to the compsoitor.
415 : *
416 : * This is bad for performance and should only be called as a last resort if the
417 : * compositor may be blocked for a long period of time, to avoid that the content
418 : * process accumulates resource allocations that the compositor is not consuming
419 : * and releasing.
420 : */
421 : void SyncWithCompositor();
422 :
423 179 : TextureForwarder* GetTextureForwarder() override { return GetCompositorBridgeChild(); }
424 0 : LayersIPCActor* GetLayersIPCActor() override { return this; }
425 :
426 0 : ActiveResourceTracker& GetActiveResourceTracker() { return *mActiveResourceTracker.get(); }
427 :
428 : CompositorBridgeChild* GetCompositorBridgeChild();
429 :
430 9 : nsIEventTarget* GetEventTarget() { return mEventTarget; };
431 :
432 : protected:
433 : virtual ~ShadowLayerForwarder();
434 :
435 : explicit ShadowLayerForwarder(ClientLayerManager* aClientLayerManager);
436 :
437 : #ifdef DEBUG
438 : void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const;
439 : #else
440 : void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const {}
441 : #endif
442 :
443 : RefPtr<CompositableClient> FindCompositable(const CompositableHandle& aHandle);
444 :
445 : bool InWorkerThread();
446 :
447 : RefPtr<LayerTransactionChild> mShadowManager;
448 : RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
449 :
450 : private:
451 :
452 : ClientLayerManager* mClientLayerManager;
453 : Transaction* mTxn;
454 : MessageLoop* mMessageLoop;
455 : DiagnosticTypes mDiagnosticTypes;
456 : bool mIsFirstPaint;
457 : FocusTarget mFocusTarget;
458 : bool mWindowOverlayChanged;
459 : InfallibleTArray<PluginWindowData> mPluginWindowData;
460 : UniquePtr<ActiveResourceTracker> mActiveResourceTracker;
461 : uint64_t mNextLayerHandle;
462 : nsDataHashtable<nsUint64HashKey, CompositableClient*> mCompositables;
463 : PaintTiming mPaintTiming;
464 : /**
465 : * ShadowLayerForwarder might dispatch tasks to main while puppet widget and
466 : * tabChild don't exist anymore; therefore we hold the event target since its
467 : * lifecycle is independent of these objects.
468 : */
469 : nsCOMPtr<nsIEventTarget> mEventTarget;
470 : };
471 :
472 : class CompositableClient;
473 :
474 : /**
475 : * A ShadowableLayer is a Layer can be shared with a parent context
476 : * through a ShadowLayerForwarder. A ShadowableLayer maps to a
477 : * Shadow*Layer in a parent context.
478 : *
479 : * Note that ShadowLayers can themselves be ShadowableLayers.
480 : */
481 : class ShadowableLayer
482 : {
483 : public:
484 : virtual ~ShadowableLayer();
485 :
486 : virtual Layer* AsLayer() = 0;
487 :
488 : /**
489 : * True if this layer has a shadow in a parent process.
490 : */
491 218 : bool HasShadow() { return mShadow.IsValid(); }
492 :
493 : /**
494 : * Return the IPC handle to a Shadow*Layer referring to this if one
495 : * exists, nullptr if not.
496 : */
497 345 : const LayerHandle& GetShadow() { return mShadow; }
498 :
499 31 : void SetShadow(ShadowLayerForwarder* aForwarder, const LayerHandle& aShadow) {
500 31 : MOZ_ASSERT(!mShadow, "can't have two shadows (yet)");
501 31 : mForwarder = aForwarder;
502 31 : mShadow = aShadow;
503 31 : }
504 :
505 0 : virtual CompositableClient* GetCompositableClient() { return nullptr; }
506 :
507 : protected:
508 31 : ShadowableLayer() {}
509 :
510 : private:
511 : RefPtr<ShadowLayerForwarder> mForwarder;
512 : LayerHandle mShadow;
513 : };
514 :
515 : } // namespace layers
516 : } // namespace mozilla
517 :
518 : #endif // ifndef mozilla_layers_ShadowLayers_h
|