gfx/layers/ipc/ShadowLayers.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * vim: sw=2 ts=8 et :
michael@0 3 */
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #ifndef mozilla_layers_ShadowLayers_h
michael@0 9 #define mozilla_layers_ShadowLayers_h 1
michael@0 10
michael@0 11 #include <stddef.h> // for size_t
michael@0 12 #include <stdint.h> // for uint64_t
michael@0 13 #include "gfxTypes.h"
michael@0 14 #include "mozilla/Attributes.h" // for MOZ_OVERRIDE
michael@0 15 #include "mozilla/WidgetUtils.h" // for ScreenRotation
michael@0 16 #include "mozilla/dom/ScreenOrientation.h" // for ScreenOrientation
michael@0 17 #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
michael@0 18 #include "mozilla/layers/CompositableForwarder.h"
michael@0 19 #include "mozilla/layers/CompositorTypes.h" // for OpenMode, etc
michael@0 20 #include "nsCOMPtr.h" // for already_AddRefed
michael@0 21 #include "nsRegion.h" // for nsIntRegion
michael@0 22 #include "nsTArrayForwardDeclare.h" // for InfallibleTArray
michael@0 23
michael@0 24 struct nsIntPoint;
michael@0 25 struct nsIntRect;
michael@0 26
michael@0 27 namespace mozilla {
michael@0 28 namespace layers {
michael@0 29
michael@0 30 class ClientTiledLayerBuffer;
michael@0 31 class CanvasClient;
michael@0 32 class CanvasLayerComposite;
michael@0 33 class CanvasSurface;
michael@0 34 class ColorLayerComposite;
michael@0 35 class CompositableChild;
michael@0 36 class ContainerLayerComposite;
michael@0 37 class ContentClient;
michael@0 38 class ContentClientRemote;
michael@0 39 class EditReply;
michael@0 40 class ImageClient;
michael@0 41 class ImageLayerComposite;
michael@0 42 class Layer;
michael@0 43 class OptionalThebesBuffer;
michael@0 44 class PLayerChild;
michael@0 45 class PLayerTransactionChild;
michael@0 46 class PLayerTransactionParent;
michael@0 47 class LayerTransactionChild;
michael@0 48 class RefLayerComposite;
michael@0 49 class ShadowableLayer;
michael@0 50 class ShmemTextureClient;
michael@0 51 class SurfaceDescriptor;
michael@0 52 class TextureClient;
michael@0 53 class ThebesLayerComposite;
michael@0 54 class ThebesBuffer;
michael@0 55 class ThebesBufferData;
michael@0 56 class TiledLayerComposer;
michael@0 57 class Transaction;
michael@0 58
michael@0 59
michael@0 60 /**
michael@0 61 * We want to share layer trees across thread contexts and address
michael@0 62 * spaces for several reasons; chief among them
michael@0 63 *
michael@0 64 * - a parent process can paint a child process's layer tree while
michael@0 65 * the child process is blocked, say on content script. This is
michael@0 66 * important on mobile devices where UI responsiveness is key.
michael@0 67 *
michael@0 68 * - a dedicated "compositor" process can asynchronously (wrt the
michael@0 69 * browser process) composite and animate layer trees, allowing a
michael@0 70 * form of pipeline parallelism between compositor/browser/content
michael@0 71 *
michael@0 72 * - a dedicated "compositor" process can take all responsibility for
michael@0 73 * accessing the GPU, which is desirable on systems with
michael@0 74 * buggy/leaky drivers because the compositor process can die while
michael@0 75 * browser and content live on (and failover mechanisms can be
michael@0 76 * installed to quickly bring up a replacement compositor)
michael@0 77 *
michael@0 78 * The Layers model has a crisply defined API, which makes it easy to
michael@0 79 * safely "share" layer trees. The ShadowLayers API extends Layers to
michael@0 80 * allow a remote, parent process to access a child process's layer
michael@0 81 * tree.
michael@0 82 *
michael@0 83 * ShadowLayerForwarder publishes a child context's layer tree to a
michael@0 84 * parent context. This comprises recording layer-tree modifications
michael@0 85 * into atomic transactions and pushing them over IPC.
michael@0 86 *
michael@0 87 * LayerManagerComposite grafts layer subtrees published by child-context
michael@0 88 * ShadowLayerForwarder(s) into a parent-context layer tree.
michael@0 89 *
michael@0 90 * (Advanced note: because our process tree may have a height >2, a
michael@0 91 * non-leaf subprocess may both receive updates from child processes
michael@0 92 * and publish them to parent processes. Put another way,
michael@0 93 * LayerManagers may be both LayerManagerComposites and
michael@0 94 * ShadowLayerForwarders.)
michael@0 95 *
michael@0 96 * There are only shadow types for layers that have different shadow
michael@0 97 * vs. not-shadow behavior. ColorLayers and ContainerLayers behave
michael@0 98 * the same way in both regimes (so far).
michael@0 99 *
michael@0 100 *
michael@0 101 * The mecanism to shadow the layer tree on the compositor through IPC works as
michael@0 102 * follows:
michael@0 103 * The layer tree is managed on the content thread, and shadowed in the compositor
michael@0 104 * thread. The shadow layer tree is only kept in sync with whatever happens in
michael@0 105 * the content thread. To do this we use IPDL protocols. IPDL is a domain
michael@0 106 * specific language that describes how two processes or thread should
michael@0 107 * communicate. C++ code is generated from .ipdl files to implement the message
michael@0 108 * passing, synchronization and serialization logic. To use the generated code
michael@0 109 * we implement classes that inherit the generated IPDL actor. the ipdl actors
michael@0 110 * of a protocol PX are PXChild or PXParent (the generated class), and we
michael@0 111 * conventionally implement XChild and XParent. The Parent side of the protocol
michael@0 112 * is the one that lives on the compositor thread. Think of IPDL actors as
michael@0 113 * endpoints of communication. they are useful to send messages and also to
michael@0 114 * dispatch the message to the right actor on the other side. One nice property
michael@0 115 * of an IPDL actor is that when an actor, say PXChild is sent in a message, the
michael@0 116 * PXParent comes out in the other side. we use this property a lot to dispatch
michael@0 117 * messages to the right layers and compositable, each of which have their own
michael@0 118 * ipdl actor on both side.
michael@0 119 *
michael@0 120 * Most of the synchronization logic happens in layer transactions and
michael@0 121 * compositable transactions.
michael@0 122 * A transaction is a set of changes to the layers and/or the compositables
michael@0 123 * that are sent and applied together to the compositor thread to keep the
michael@0 124 * LayerComposite in a coherent state.
michael@0 125 * Layer transactions maintain the shape of the shadow layer tree, and
michael@0 126 * synchronize the texture data held by compositables. Layer transactions
michael@0 127 * are always between the content thread and the compositor thread.
michael@0 128 * Compositable transactions are subset of a layer transaction with which only
michael@0 129 * compositables and textures can be manipulated, and does not always originate
michael@0 130 * from the content thread. (See CompositableForwarder.h and ImageBridgeChild.h)
michael@0 131 */
michael@0 132
michael@0 133 class ShadowLayerForwarder : public CompositableForwarder
michael@0 134 {
michael@0 135 friend class ContentClientIncremental;
michael@0 136 friend class ClientLayerManager;
michael@0 137
michael@0 138 public:
michael@0 139 virtual ~ShadowLayerForwarder();
michael@0 140
michael@0 141 /**
michael@0 142 * Setup the IPDL actor for aCompositable to be part of layers
michael@0 143 * transactions.
michael@0 144 */
michael@0 145 void Connect(CompositableClient* aCompositable);
michael@0 146
michael@0 147 virtual PTextureChild* CreateTexture(const SurfaceDescriptor& aSharedData,
michael@0 148 TextureFlags aFlags) MOZ_OVERRIDE;
michael@0 149
michael@0 150 virtual void CreatedIncrementalBuffer(CompositableClient* aCompositable,
michael@0 151 const TextureInfo& aTextureInfo,
michael@0 152 const nsIntRect& aBufferRect) MOZ_OVERRIDE;
michael@0 153
michael@0 154 /**
michael@0 155 * Adds an edit in the layers transaction in order to attach
michael@0 156 * the corresponding compositable and layer on the compositor side.
michael@0 157 * Connect must have been called on aCompositable beforehand.
michael@0 158 */
michael@0 159 void Attach(CompositableClient* aCompositable,
michael@0 160 ShadowableLayer* aLayer);
michael@0 161
michael@0 162 /**
michael@0 163 * Adds an edit in the transaction in order to attach a Compositable that
michael@0 164 * is not managed by this ShadowLayerForwarder (for example, by ImageBridge
michael@0 165 * in the case of async-video).
michael@0 166 * Since the compositable is not managed by this forwarder, we can't use
michael@0 167 * the compositable or it's IPDL actor here, so we use an ID instead, that
michael@0 168 * is matched on the compositor side.
michael@0 169 */
michael@0 170 void AttachAsyncCompositable(uint64_t aCompositableID,
michael@0 171 ShadowableLayer* aLayer);
michael@0 172
michael@0 173 /**
michael@0 174 * Begin recording a transaction to be forwarded atomically to a
michael@0 175 * LayerManagerComposite.
michael@0 176 */
michael@0 177 void BeginTransaction(const nsIntRect& aTargetBounds,
michael@0 178 ScreenRotation aRotation,
michael@0 179 const nsIntRect& aClientBounds,
michael@0 180 mozilla::dom::ScreenOrientation aOrientation);
michael@0 181
michael@0 182 /**
michael@0 183 * The following methods may only be called after BeginTransaction()
michael@0 184 * but before EndTransaction(). They mirror the LayerManager
michael@0 185 * interface in Layers.h.
michael@0 186 */
michael@0 187
michael@0 188 /**
michael@0 189 * Notify the shadow manager that a new, "real" layer has been
michael@0 190 * created, and a corresponding shadow layer should be created in
michael@0 191 * the compositing process.
michael@0 192 */
michael@0 193 void CreatedThebesLayer(ShadowableLayer* aThebes);
michael@0 194 void CreatedContainerLayer(ShadowableLayer* aContainer);
michael@0 195 void CreatedImageLayer(ShadowableLayer* aImage);
michael@0 196 void CreatedColorLayer(ShadowableLayer* aColor);
michael@0 197 void CreatedCanvasLayer(ShadowableLayer* aCanvas);
michael@0 198 void CreatedRefLayer(ShadowableLayer* aRef);
michael@0 199
michael@0 200 /**
michael@0 201 * At least one attribute of |aMutant| has changed, and |aMutant|
michael@0 202 * needs to sync to its shadow layer. This initial implementation
michael@0 203 * forwards all attributes when any is mutated.
michael@0 204 */
michael@0 205 void Mutated(ShadowableLayer* aMutant);
michael@0 206
michael@0 207 void SetRoot(ShadowableLayer* aRoot);
michael@0 208 /**
michael@0 209 * Insert |aChild| after |aAfter| in |aContainer|. |aAfter| can be
michael@0 210 * nullptr to indicated that |aChild| should be appended to the end of
michael@0 211 * |aContainer|'s child list.
michael@0 212 */
michael@0 213 void InsertAfter(ShadowableLayer* aContainer,
michael@0 214 ShadowableLayer* aChild,
michael@0 215 ShadowableLayer* aAfter = nullptr);
michael@0 216 void RemoveChild(ShadowableLayer* aContainer,
michael@0 217 ShadowableLayer* aChild);
michael@0 218 void RepositionChild(ShadowableLayer* aContainer,
michael@0 219 ShadowableLayer* aChild,
michael@0 220 ShadowableLayer* aAfter = nullptr);
michael@0 221
michael@0 222 /**
michael@0 223 * Set aMaskLayer as the mask on aLayer.
michael@0 224 * Note that only image layers are properly supported
michael@0 225 * LayerTransactionParent::UpdateMask and accompanying ipdl
michael@0 226 * will need changing to update properties for other kinds
michael@0 227 * of mask layer.
michael@0 228 */
michael@0 229 void SetMask(ShadowableLayer* aLayer,
michael@0 230 ShadowableLayer* aMaskLayer);
michael@0 231
michael@0 232 /**
michael@0 233 * See CompositableForwarder::UseTiledLayerBuffer
michael@0 234 */
michael@0 235 virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
michael@0 236 const SurfaceDescriptorTiles& aTileLayerDescriptor) MOZ_OVERRIDE;
michael@0 237
michael@0 238 /**
michael@0 239 * Notify the compositor that a compositable will be updated asynchronously
michael@0 240 * through ImageBridge, using an ID to connect the protocols on the
michael@0 241 * compositor side.
michael@0 242 */
michael@0 243 void AttachAsyncCompositable(PLayerTransactionChild* aLayer, uint64_t aID);
michael@0 244
michael@0 245 virtual void RemoveTextureFromCompositable(CompositableClient* aCompositable,
michael@0 246 TextureClient* aTexture) MOZ_OVERRIDE;
michael@0 247
michael@0 248 virtual void RemoveTexture(TextureClient* aTexture) MOZ_OVERRIDE;
michael@0 249
michael@0 250 /**
michael@0 251 * Communicate to the compositor that aRegion in the texture identified by aLayer
michael@0 252 * and aIdentifier has been updated to aThebesBuffer.
michael@0 253 */
michael@0 254 virtual void UpdateTextureRegion(CompositableClient* aCompositable,
michael@0 255 const ThebesBufferData& aThebesBufferData,
michael@0 256 const nsIntRegion& aUpdatedRegion) MOZ_OVERRIDE;
michael@0 257
michael@0 258 virtual void UpdateTextureIncremental(CompositableClient* aCompositable,
michael@0 259 TextureIdentifier aTextureId,
michael@0 260 SurfaceDescriptor& aDescriptor,
michael@0 261 const nsIntRegion& aUpdatedRegion,
michael@0 262 const nsIntRect& aBufferRect,
michael@0 263 const nsIntPoint& aBufferRotation) MOZ_OVERRIDE;
michael@0 264
michael@0 265 /**
michael@0 266 * Communicate the picture rect of an image to the compositor
michael@0 267 */
michael@0 268 void UpdatePictureRect(CompositableClient* aCompositable,
michael@0 269 const nsIntRect& aRect);
michael@0 270
michael@0 271 /**
michael@0 272 * See CompositableForwarder::UpdatedTexture
michael@0 273 */
michael@0 274 virtual void UpdatedTexture(CompositableClient* aCompositable,
michael@0 275 TextureClient* aTexture,
michael@0 276 nsIntRegion* aRegion) MOZ_OVERRIDE;
michael@0 277
michael@0 278 /**
michael@0 279 * See CompositableForwarder::UseTexture
michael@0 280 */
michael@0 281 virtual void UseTexture(CompositableClient* aCompositable,
michael@0 282 TextureClient* aClient) MOZ_OVERRIDE;
michael@0 283 virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
michael@0 284 TextureClient* aClientOnBlack,
michael@0 285 TextureClient* aClientOnWhite) MOZ_OVERRIDE;
michael@0 286
michael@0 287 /**
michael@0 288 * End the current transaction and forward it to LayerManagerComposite.
michael@0 289 * |aReplies| are directions from the LayerManagerComposite to the
michael@0 290 * caller of EndTransaction().
michael@0 291 */
michael@0 292 bool EndTransaction(InfallibleTArray<EditReply>* aReplies,
michael@0 293 const nsIntRegion& aRegionToClear,
michael@0 294 bool aScheduleComposite,
michael@0 295 bool* aSent);
michael@0 296
michael@0 297 /**
michael@0 298 * Set an actor through which layer updates will be pushed.
michael@0 299 */
michael@0 300 void SetShadowManager(PLayerTransactionChild* aShadowManager);
michael@0 301
michael@0 302 /**
michael@0 303 * True if this is forwarding to a LayerManagerComposite.
michael@0 304 */
michael@0 305 bool HasShadowManager() const { return !!mShadowManager; }
michael@0 306 LayerTransactionChild* GetShadowManager() const { return mShadowManager.get(); }
michael@0 307
michael@0 308 virtual void WindowOverlayChanged() { mWindowOverlayChanged = true; }
michael@0 309
michael@0 310 /**
michael@0 311 * The following Alloc/Open/Destroy interfaces abstract over the
michael@0 312 * details of working with surfaces that are shared across
michael@0 313 * processes. They provide the glue between C++ Layers and the
michael@0 314 * LayerComposite IPC system.
michael@0 315 *
michael@0 316 * The basic lifecycle is
michael@0 317 *
michael@0 318 * - a Layer needs a buffer. Its ShadowableLayer subclass calls
michael@0 319 * AllocBuffer(), then calls one of the Created*Buffer() methods
michael@0 320 * above to transfer the (temporary) front buffer to its
michael@0 321 * LayerComposite in the other process. The Layer needs a
michael@0 322 * gfxASurface to paint, so the ShadowableLayer uses
michael@0 323 * OpenDescriptor(backBuffer) to get that surface, and hands it
michael@0 324 * out to the Layer.
michael@0 325 *
michael@0 326 * - a Layer has painted new pixels. Its ShadowableLayer calls one
michael@0 327 * of the Painted*Buffer() methods above with the back buffer
michael@0 328 * descriptor. This notification is forwarded to the LayerComposite,
michael@0 329 * which uses OpenDescriptor() to access the newly-painted pixels.
michael@0 330 * The LayerComposite then updates its front buffer in a Layer- and
michael@0 331 * platform-dependent way, and sends a surface descriptor back to
michael@0 332 * the ShadowableLayer that becomes its new back back buffer.
michael@0 333 *
michael@0 334 * - a Layer wants to destroy its buffers. Its ShadowableLayer
michael@0 335 * calls Destroyed*Buffer(), which gives up control of the back
michael@0 336 * buffer descriptor. The actual back buffer surface is then
michael@0 337 * destroyed using DestroySharedSurface() just before notifying
michael@0 338 * the parent process. When the parent process is notified, the
michael@0 339 * LayerComposite also calls DestroySharedSurface() on its front
michael@0 340 * buffer, and the double-buffer pair is gone.
michael@0 341 */
michael@0 342
michael@0 343 // ISurfaceAllocator
michael@0 344 virtual bool AllocUnsafeShmem(size_t aSize,
michael@0 345 mozilla::ipc::SharedMemory::SharedMemoryType aType,
michael@0 346 mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE;
michael@0 347 virtual bool AllocShmem(size_t aSize,
michael@0 348 mozilla::ipc::SharedMemory::SharedMemoryType aType,
michael@0 349 mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE;
michael@0 350 virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) MOZ_OVERRIDE;
michael@0 351
michael@0 352 virtual bool IPCOpen() const MOZ_OVERRIDE;
michael@0 353 virtual bool IsSameProcess() const MOZ_OVERRIDE;
michael@0 354
michael@0 355 /**
michael@0 356 * Construct a shadow of |aLayer| on the "other side", at the
michael@0 357 * LayerManagerComposite.
michael@0 358 */
michael@0 359 PLayerChild* ConstructShadowFor(ShadowableLayer* aLayer);
michael@0 360
michael@0 361 /**
michael@0 362 * Flag the next paint as the first for a document.
michael@0 363 */
michael@0 364 void SetIsFirstPaint() { mIsFirstPaint = true; }
michael@0 365
michael@0 366 static void PlatformSyncBeforeUpdate();
michael@0 367
michael@0 368 protected:
michael@0 369 ShadowLayerForwarder();
michael@0 370
michael@0 371 #ifdef DEBUG
michael@0 372 void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const;
michael@0 373 #else
michael@0 374 void CheckSurfaceDescriptor(const SurfaceDescriptor* aDescriptor) const {}
michael@0 375 #endif
michael@0 376
michael@0 377 RefPtr<LayerTransactionChild> mShadowManager;
michael@0 378
michael@0 379 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
michael@0 380 // from ISurfaceAllocator
michael@0 381 virtual PGrallocBufferChild* AllocGrallocBuffer(const gfx::IntSize& aSize,
michael@0 382 uint32_t aFormat,
michael@0 383 uint32_t aUsage,
michael@0 384 MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
michael@0 385
michael@0 386 virtual void DeallocGrallocBuffer(PGrallocBufferChild* aChild) MOZ_OVERRIDE;
michael@0 387 #endif
michael@0 388
michael@0 389 private:
michael@0 390
michael@0 391 Transaction* mTxn;
michael@0 392 DiagnosticTypes mDiagnosticTypes;
michael@0 393 bool mIsFirstPaint;
michael@0 394 bool mWindowOverlayChanged;
michael@0 395 };
michael@0 396
michael@0 397 class CompositableClient;
michael@0 398
michael@0 399 /**
michael@0 400 * A ShadowableLayer is a Layer can be shared with a parent context
michael@0 401 * through a ShadowLayerForwarder. A ShadowableLayer maps to a
michael@0 402 * Shadow*Layer in a parent context.
michael@0 403 *
michael@0 404 * Note that ShadowLayers can themselves be ShadowableLayers.
michael@0 405 */
michael@0 406 class ShadowableLayer
michael@0 407 {
michael@0 408 public:
michael@0 409 virtual ~ShadowableLayer() {}
michael@0 410
michael@0 411 virtual Layer* AsLayer() = 0;
michael@0 412
michael@0 413 /**
michael@0 414 * True if this layer has a shadow in a parent process.
michael@0 415 */
michael@0 416 bool HasShadow() { return !!mShadow; }
michael@0 417
michael@0 418 /**
michael@0 419 * Return the IPC handle to a Shadow*Layer referring to this if one
michael@0 420 * exists, nullptr if not.
michael@0 421 */
michael@0 422 PLayerChild* GetShadow() { return mShadow; }
michael@0 423
michael@0 424 virtual CompositableClient* GetCompositableClient() { return nullptr; }
michael@0 425 protected:
michael@0 426 ShadowableLayer() : mShadow(nullptr) {}
michael@0 427
michael@0 428 PLayerChild* mShadow;
michael@0 429 };
michael@0 430
michael@0 431 } // namespace layers
michael@0 432 } // namespace mozilla
michael@0 433
michael@0 434 #endif // ifndef mozilla_layers_ShadowLayers_h

mercurial