gfx/layers/Layers.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: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #ifndef GFX_LAYERS_H
michael@0 7 #define GFX_LAYERS_H
michael@0 8
michael@0 9 #include <stdint.h> // for uint32_t, uint64_t, uint8_t
michael@0 10 #include <stdio.h> // for FILE
michael@0 11 #include <sys/types.h> // for int32_t, int64_t
michael@0 12 #include "FrameMetrics.h" // for FrameMetrics
michael@0 13 #include "Units.h" // for LayerMargin, LayerPoint
michael@0 14 #include "gfxContext.h" // for GraphicsOperator
michael@0 15 #include "gfxTypes.h"
michael@0 16 #include "gfxColor.h" // for gfxRGBA
michael@0 17 #include "gfxMatrix.h" // for gfxMatrix
michael@0 18 #include "GraphicsFilter.h" // for GraphicsFilter
michael@0 19 #include "gfxPoint.h" // for gfxPoint
michael@0 20 #include "gfxRect.h" // for gfxRect
michael@0 21 #include "gfx2DGlue.h"
michael@0 22 #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2, etc
michael@0 23 #include "mozilla/DebugOnly.h" // for DebugOnly
michael@0 24 #include "mozilla/EventForwards.h" // for nsPaintEvent
michael@0 25 #include "mozilla/RefPtr.h" // for TemporaryRef
michael@0 26 #include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
michael@0 27 #include "mozilla/gfx/BaseMargin.h" // for BaseMargin
michael@0 28 #include "mozilla/gfx/BasePoint.h" // for BasePoint
michael@0 29 #include "mozilla/gfx/Point.h" // for IntSize
michael@0 30 #include "mozilla/gfx/Types.h" // for SurfaceFormat
michael@0 31 #include "mozilla/gfx/UserData.h" // for UserData, etc
michael@0 32 #include "mozilla/layers/LayersTypes.h"
michael@0 33 #include "mozilla/mozalloc.h" // for operator delete, etc
michael@0 34 #include "nsAutoPtr.h" // for nsAutoPtr, nsRefPtr, etc
michael@0 35 #include "nsCOMPtr.h" // for already_AddRefed
michael@0 36 #include "nsCSSProperty.h" // for nsCSSProperty
michael@0 37 #include "nsDebug.h" // for NS_ASSERTION
michael@0 38 #include "nsISupportsImpl.h" // for Layer::Release, etc
michael@0 39 #include "nsRect.h" // for nsIntRect
michael@0 40 #include "nsRegion.h" // for nsIntRegion
michael@0 41 #include "nsSize.h" // for nsIntSize
michael@0 42 #include "nsString.h" // for nsCString
michael@0 43 #include "nsStyleAnimation.h" // for nsStyleAnimation::Value, etc
michael@0 44 #include "nsTArray.h" // for nsTArray
michael@0 45 #include "nsTArrayForwardDeclare.h" // for InfallibleTArray
michael@0 46 #include "nscore.h" // for nsACString, nsAString
michael@0 47 #include "prlog.h" // for PRLogModuleInfo
michael@0 48 #include "gfx2DGlue.h"
michael@0 49
michael@0 50 class gfxContext;
michael@0 51
michael@0 52 extern uint8_t gLayerManagerLayerBuilder;
michael@0 53
michael@0 54 namespace mozilla {
michael@0 55
michael@0 56 class FrameLayerBuilder;
michael@0 57 class WebGLContext;
michael@0 58
michael@0 59 namespace gl {
michael@0 60 class GLContext;
michael@0 61 }
michael@0 62
michael@0 63 namespace gfx {
michael@0 64 class DrawTarget;
michael@0 65 class SurfaceStream;
michael@0 66 }
michael@0 67
michael@0 68 namespace css {
michael@0 69 class ComputedTimingFunction;
michael@0 70 }
michael@0 71
michael@0 72 namespace layers {
michael@0 73
michael@0 74 class Animation;
michael@0 75 class AnimationData;
michael@0 76 class AsyncPanZoomController;
michael@0 77 class CommonLayerAttributes;
michael@0 78 class Layer;
michael@0 79 class ThebesLayer;
michael@0 80 class ContainerLayer;
michael@0 81 class ImageLayer;
michael@0 82 class ColorLayer;
michael@0 83 class ImageContainer;
michael@0 84 class CanvasLayer;
michael@0 85 class ReadbackLayer;
michael@0 86 class ReadbackProcessor;
michael@0 87 class RefLayer;
michael@0 88 class LayerComposite;
michael@0 89 class ShadowableLayer;
michael@0 90 class ShadowLayerForwarder;
michael@0 91 class LayerManagerComposite;
michael@0 92 class SpecificLayerAttributes;
michael@0 93 class SurfaceDescriptor;
michael@0 94 class Compositor;
michael@0 95 struct TextureFactoryIdentifier;
michael@0 96 struct EffectMask;
michael@0 97
michael@0 98 #define MOZ_LAYER_DECL_NAME(n, e) \
michael@0 99 virtual const char* Name() const { return n; } \
michael@0 100 virtual LayerType GetType() const { return e; }
michael@0 101
michael@0 102 /**
michael@0 103 * Base class for userdata objects attached to layers and layer managers.
michael@0 104 */
michael@0 105 class LayerUserData {
michael@0 106 public:
michael@0 107 virtual ~LayerUserData() {}
michael@0 108 };
michael@0 109
michael@0 110 /*
michael@0 111 * Motivation: For truly smooth animation and video playback, we need to
michael@0 112 * be able to compose frames and render them on a dedicated thread (i.e.
michael@0 113 * off the main thread where DOM manipulation, script execution and layout
michael@0 114 * induce difficult-to-bound latency). This requires Gecko to construct
michael@0 115 * some kind of persistent scene structure (graph or tree) that can be
michael@0 116 * safely transmitted across threads. We have other scenarios (e.g. mobile
michael@0 117 * browsing) where retaining some rendered data between paints is desired
michael@0 118 * for performance, so again we need a retained scene structure.
michael@0 119 *
michael@0 120 * Our retained scene structure is a layer tree. Each layer represents
michael@0 121 * content which can be composited onto a destination surface; the root
michael@0 122 * layer is usually composited into a window, and non-root layers are
michael@0 123 * composited into their parent layers. Layers have attributes (e.g.
michael@0 124 * opacity and clipping) that influence their compositing.
michael@0 125 *
michael@0 126 * We want to support a variety of layer implementations, including
michael@0 127 * a simple "immediate mode" implementation that doesn't retain any
michael@0 128 * rendered data between paints (i.e. uses cairo in just the way that
michael@0 129 * Gecko used it before layers were introduced). But we also don't want
michael@0 130 * to have bifurcated "layers"/"non-layers" rendering paths in Gecko.
michael@0 131 * Therefore the layers API is carefully designed to permit maximally
michael@0 132 * efficient implementation in an "immediate mode" style. See the
michael@0 133 * BasicLayerManager for such an implementation.
michael@0 134 */
michael@0 135
michael@0 136 static void LayerManagerUserDataDestroy(void *data)
michael@0 137 {
michael@0 138 delete static_cast<LayerUserData*>(data);
michael@0 139 }
michael@0 140
michael@0 141 /**
michael@0 142 * A LayerManager controls a tree of layers. All layers in the tree
michael@0 143 * must use the same LayerManager.
michael@0 144 *
michael@0 145 * All modifications to a layer tree must happen inside a transaction.
michael@0 146 * Only the state of the layer tree at the end of a transaction is
michael@0 147 * rendered. Transactions cannot be nested
michael@0 148 *
michael@0 149 * Each transaction has two phases:
michael@0 150 * 1) Construction: layers are created, inserted, removed and have
michael@0 151 * properties set on them in this phase.
michael@0 152 * BeginTransaction and BeginTransactionWithTarget start a transaction in
michael@0 153 * the Construction phase. When the client has finished constructing the layer
michael@0 154 * tree, it should call EndConstruction() to enter the drawing phase.
michael@0 155 * 2) Drawing: ThebesLayers are rendered into in this phase, in tree
michael@0 156 * order. When the client has finished drawing into the ThebesLayers, it should
michael@0 157 * call EndTransaction to complete the transaction.
michael@0 158 *
michael@0 159 * All layer API calls happen on the main thread.
michael@0 160 *
michael@0 161 * Layers are refcounted. The layer manager holds a reference to the
michael@0 162 * root layer, and each container layer holds a reference to its children.
michael@0 163 */
michael@0 164 class LayerManager {
michael@0 165 NS_INLINE_DECL_REFCOUNTING(LayerManager)
michael@0 166
michael@0 167 protected:
michael@0 168 typedef mozilla::gfx::DrawTarget DrawTarget;
michael@0 169 typedef mozilla::gfx::IntSize IntSize;
michael@0 170 typedef mozilla::gfx::SurfaceFormat SurfaceFormat;
michael@0 171
michael@0 172 public:
michael@0 173 LayerManager()
michael@0 174 : mDestroyed(false)
michael@0 175 , mSnapEffectiveTransforms(true)
michael@0 176 , mId(0)
michael@0 177 , mInTransaction(false)
michael@0 178 {
michael@0 179 InitLog();
michael@0 180 }
michael@0 181
michael@0 182 /**
michael@0 183 * Release layers and resources held by this layer manager, and mark
michael@0 184 * it as destroyed. Should do any cleanup necessary in preparation
michael@0 185 * for its widget going away. After this call, only user data calls
michael@0 186 * are valid on the layer manager.
michael@0 187 */
michael@0 188 virtual void Destroy()
michael@0 189 {
michael@0 190 mDestroyed = true;
michael@0 191 mUserData.Destroy();
michael@0 192 mRoot = nullptr;
michael@0 193 }
michael@0 194 bool IsDestroyed() { return mDestroyed; }
michael@0 195
michael@0 196 virtual ShadowLayerForwarder* AsShadowForwarder()
michael@0 197 { return nullptr; }
michael@0 198
michael@0 199 virtual LayerManagerComposite* AsLayerManagerComposite()
michael@0 200 { return nullptr; }
michael@0 201
michael@0 202 /**
michael@0 203 * Returns true if this LayerManager is owned by an nsIWidget,
michael@0 204 * and is used for drawing into the widget.
michael@0 205 */
michael@0 206 virtual bool IsWidgetLayerManager() { return true; }
michael@0 207
michael@0 208 /**
michael@0 209 * Start a new transaction. Nested transactions are not allowed so
michael@0 210 * there must be no transaction currently in progress.
michael@0 211 * This transaction will update the state of the window from which
michael@0 212 * this LayerManager was obtained.
michael@0 213 */
michael@0 214 virtual void BeginTransaction() = 0;
michael@0 215 /**
michael@0 216 * Start a new transaction. Nested transactions are not allowed so
michael@0 217 * there must be no transaction currently in progress.
michael@0 218 * This transaction will render the contents of the layer tree to
michael@0 219 * the given target context. The rendering will be complete when
michael@0 220 * EndTransaction returns.
michael@0 221 */
michael@0 222 virtual void BeginTransactionWithTarget(gfxContext* aTarget) = 0;
michael@0 223
michael@0 224 enum EndTransactionFlags {
michael@0 225 END_DEFAULT = 0,
michael@0 226 END_NO_IMMEDIATE_REDRAW = 1 << 0, // Do not perform the drawing phase
michael@0 227 END_NO_COMPOSITE = 1 << 1, // Do not composite after drawing thebes layer contents.
michael@0 228 END_NO_REMOTE_COMPOSITE = 1 << 2 // Do not schedule a composition with a remote Compositor, if one exists.
michael@0 229 };
michael@0 230
michael@0 231 FrameLayerBuilder* GetLayerBuilder() {
michael@0 232 return reinterpret_cast<FrameLayerBuilder*>(GetUserData(&gLayerManagerLayerBuilder));
michael@0 233 }
michael@0 234
michael@0 235 /**
michael@0 236 * Attempts to end an "empty transaction". There must have been no
michael@0 237 * changes to the layer tree since the BeginTransaction().
michael@0 238 * It's possible for this to fail; ThebesLayers may need to be updated
michael@0 239 * due to VRAM data being lost, for example. In such cases this method
michael@0 240 * returns false, and the caller must proceed with a normal layer tree
michael@0 241 * update and EndTransaction.
michael@0 242 */
michael@0 243 virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) = 0;
michael@0 244
michael@0 245 /**
michael@0 246 * Function called to draw the contents of each ThebesLayer.
michael@0 247 * aRegionToDraw contains the region that needs to be drawn.
michael@0 248 * This would normally be a subregion of the visible region.
michael@0 249 * The callee must draw all of aRegionToDraw. Drawing outside
michael@0 250 * aRegionToDraw will be clipped out or ignored.
michael@0 251 * The callee must draw all of aRegionToDraw.
michael@0 252 * This region is relative to 0,0 in the ThebesLayer.
michael@0 253 *
michael@0 254 * aRegionToInvalidate contains a region whose contents have been
michael@0 255 * changed by the layer manager and which must therefore be invalidated.
michael@0 256 * For example, this could be non-empty if a retained layer internally
michael@0 257 * switches from RGBA to RGB or back ... we might want to repaint it to
michael@0 258 * consistently use subpixel-AA or not.
michael@0 259 * This region is relative to 0,0 in the ThebesLayer.
michael@0 260 * aRegionToInvalidate may contain areas that are outside
michael@0 261 * aRegionToDraw; the callee must ensure that these areas are repainted
michael@0 262 * in the current layer manager transaction or in a later layer
michael@0 263 * manager transaction.
michael@0 264 *
michael@0 265 * aContext must not be used after the call has returned.
michael@0 266 * We guarantee that buffered contents in the visible
michael@0 267 * region are valid once drawing is complete.
michael@0 268 *
michael@0 269 * The origin of aContext is 0,0 in the ThebesLayer.
michael@0 270 */
michael@0 271 typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer,
michael@0 272 gfxContext* aContext,
michael@0 273 const nsIntRegion& aRegionToDraw,
michael@0 274 DrawRegionClip aClip,
michael@0 275 const nsIntRegion& aRegionToInvalidate,
michael@0 276 void* aCallbackData);
michael@0 277
michael@0 278 /**
michael@0 279 * Finish the construction phase of the transaction, perform the
michael@0 280 * drawing phase, and end the transaction.
michael@0 281 * During the drawing phase, all ThebesLayers in the tree are
michael@0 282 * drawn in tree order, exactly once each, except for those layers
michael@0 283 * where it is known that the visible region is empty.
michael@0 284 */
michael@0 285 virtual void EndTransaction(DrawThebesLayerCallback aCallback,
michael@0 286 void* aCallbackData,
michael@0 287 EndTransactionFlags aFlags = END_DEFAULT) = 0;
michael@0 288
michael@0 289 /**
michael@0 290 * Schedule a composition with the remote Compositor, if one exists
michael@0 291 * for this LayerManager. Useful in conjunction with the END_NO_REMOTE_COMPOSITE
michael@0 292 * flag to EndTransaction.
michael@0 293 */
michael@0 294 virtual void Composite() {}
michael@0 295
michael@0 296 virtual bool HasShadowManagerInternal() const { return false; }
michael@0 297 bool HasShadowManager() const { return HasShadowManagerInternal(); }
michael@0 298
michael@0 299 bool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; }
michael@0 300
michael@0 301 /**
michael@0 302 * Returns true if this LayerManager can properly support layers with
michael@0 303 * SurfaceMode::SURFACE_COMPONENT_ALPHA. This can include disabling component
michael@0 304 * alpha if required.
michael@0 305 */
michael@0 306 virtual bool AreComponentAlphaLayersEnabled() { return true; }
michael@0 307
michael@0 308 /**
michael@0 309 * CONSTRUCTION PHASE ONLY
michael@0 310 * Set the root layer. The root layer is initially null. If there is
michael@0 311 * no root layer, EndTransaction won't draw anything.
michael@0 312 */
michael@0 313 virtual void SetRoot(Layer* aLayer) = 0;
michael@0 314 /**
michael@0 315 * Can be called anytime
michael@0 316 */
michael@0 317 Layer* GetRoot() { return mRoot; }
michael@0 318
michael@0 319 /**
michael@0 320 * Does a breadth-first search from the root layer to find the first
michael@0 321 * scrollable layer.
michael@0 322 * Can be called any time.
michael@0 323 */
michael@0 324 Layer* GetPrimaryScrollableLayer();
michael@0 325
michael@0 326 /**
michael@0 327 * Returns a list of all descendant layers for which
michael@0 328 * GetFrameMetrics().IsScrollable() is true.
michael@0 329 */
michael@0 330 void GetScrollableLayers(nsTArray<Layer*>& aArray);
michael@0 331
michael@0 332 /**
michael@0 333 * CONSTRUCTION PHASE ONLY
michael@0 334 * Called when a managee has mutated.
michael@0 335 * Subclasses overriding this method must first call their
michael@0 336 * superclass's impl
michael@0 337 */
michael@0 338 #ifdef DEBUG
michael@0 339 // In debug builds, we check some properties of |aLayer|.
michael@0 340 virtual void Mutated(Layer* aLayer);
michael@0 341 #else
michael@0 342 virtual void Mutated(Layer* aLayer) { }
michael@0 343 #endif
michael@0 344
michael@0 345 /**
michael@0 346 * Hints that can be used during Thebes layer creation to influence the type
michael@0 347 * or properties of the layer created.
michael@0 348 *
michael@0 349 * NONE: No hint.
michael@0 350 * SCROLLABLE: This layer may represent scrollable content.
michael@0 351 */
michael@0 352 enum ThebesLayerCreationHint {
michael@0 353 NONE, SCROLLABLE
michael@0 354 };
michael@0 355
michael@0 356 /**
michael@0 357 * CONSTRUCTION PHASE ONLY
michael@0 358 * Create a ThebesLayer for this manager's layer tree.
michael@0 359 */
michael@0 360 virtual already_AddRefed<ThebesLayer> CreateThebesLayer() = 0;
michael@0 361 /**
michael@0 362 * CONSTRUCTION PHASE ONLY
michael@0 363 * Create a ThebesLayer for this manager's layer tree, with a creation hint
michael@0 364 * parameter to help optimise the type of layer created.
michael@0 365 */
michael@0 366 virtual already_AddRefed<ThebesLayer> CreateThebesLayerWithHint(ThebesLayerCreationHint) {
michael@0 367 return CreateThebesLayer();
michael@0 368 }
michael@0 369 /**
michael@0 370 * CONSTRUCTION PHASE ONLY
michael@0 371 * Create a ContainerLayer for this manager's layer tree.
michael@0 372 */
michael@0 373 virtual already_AddRefed<ContainerLayer> CreateContainerLayer() = 0;
michael@0 374 /**
michael@0 375 * CONSTRUCTION PHASE ONLY
michael@0 376 * Create an ImageLayer for this manager's layer tree.
michael@0 377 */
michael@0 378 virtual already_AddRefed<ImageLayer> CreateImageLayer() = 0;
michael@0 379 /**
michael@0 380 * CONSTRUCTION PHASE ONLY
michael@0 381 * Create a ColorLayer for this manager's layer tree.
michael@0 382 */
michael@0 383 virtual already_AddRefed<ColorLayer> CreateColorLayer() = 0;
michael@0 384 /**
michael@0 385 * CONSTRUCTION PHASE ONLY
michael@0 386 * Create a CanvasLayer for this manager's layer tree.
michael@0 387 */
michael@0 388 virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() = 0;
michael@0 389 /**
michael@0 390 * CONSTRUCTION PHASE ONLY
michael@0 391 * Create a ReadbackLayer for this manager's layer tree.
michael@0 392 */
michael@0 393 virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() { return nullptr; }
michael@0 394 /**
michael@0 395 * CONSTRUCTION PHASE ONLY
michael@0 396 * Create a RefLayer for this manager's layer tree.
michael@0 397 */
michael@0 398 virtual already_AddRefed<RefLayer> CreateRefLayer() { return nullptr; }
michael@0 399
michael@0 400
michael@0 401 /**
michael@0 402 * Can be called anytime, from any thread.
michael@0 403 *
michael@0 404 * Creates an Image container which forwards its images to the compositor within
michael@0 405 * layer transactions on the main thread.
michael@0 406 */
michael@0 407 static already_AddRefed<ImageContainer> CreateImageContainer();
michael@0 408
michael@0 409 /**
michael@0 410 * Can be called anytime, from any thread.
michael@0 411 *
michael@0 412 * Tries to create an Image container which forwards its images to the compositor
michael@0 413 * asynchronously using the ImageBridge IPDL protocol. If the protocol is not
michael@0 414 * available, the returned ImageContainer will forward images within layer
michael@0 415 * transactions, just like if it was created with CreateImageContainer().
michael@0 416 */
michael@0 417 static already_AddRefed<ImageContainer> CreateAsynchronousImageContainer();
michael@0 418
michael@0 419 /**
michael@0 420 * Type of layer manager his is. This is to be used sparsely in order to
michael@0 421 * avoid a lot of Layers backend specific code. It should be used only when
michael@0 422 * Layers backend specific functionality is necessary.
michael@0 423 */
michael@0 424 virtual LayersBackend GetBackendType() = 0;
michael@0 425
michael@0 426 /**
michael@0 427 * Type of layers backend that will be used to composite this layer tree.
michael@0 428 * When compositing is done remotely, then this returns the layers type
michael@0 429 * of the compositor.
michael@0 430 */
michael@0 431 virtual LayersBackend GetCompositorBackendType() { return GetBackendType(); }
michael@0 432
michael@0 433 /**
michael@0 434 * Creates a DrawTarget which is optimized for inter-operating with this
michael@0 435 * layer manager.
michael@0 436 */
michael@0 437 virtual TemporaryRef<DrawTarget>
michael@0 438 CreateOptimalDrawTarget(const IntSize &aSize,
michael@0 439 SurfaceFormat imageFormat);
michael@0 440
michael@0 441 /**
michael@0 442 * Creates a DrawTarget for alpha masks which is optimized for inter-
michael@0 443 * operating with this layer manager. In contrast to CreateOptimalDrawTarget,
michael@0 444 * this surface is optimised for drawing alpha only and we assume that
michael@0 445 * drawing the mask is fairly simple.
michael@0 446 */
michael@0 447 virtual TemporaryRef<DrawTarget>
michael@0 448 CreateOptimalMaskDrawTarget(const IntSize &aSize);
michael@0 449
michael@0 450 /**
michael@0 451 * Creates a DrawTarget for use with canvas which is optimized for
michael@0 452 * inter-operating with this layermanager.
michael@0 453 */
michael@0 454 virtual TemporaryRef<mozilla::gfx::DrawTarget>
michael@0 455 CreateDrawTarget(const mozilla::gfx::IntSize &aSize,
michael@0 456 mozilla::gfx::SurfaceFormat aFormat);
michael@0 457
michael@0 458 virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) { return true; }
michael@0 459
michael@0 460 /**
michael@0 461 * returns the maximum texture size on this layer backend, or INT32_MAX
michael@0 462 * if there is no maximum
michael@0 463 */
michael@0 464 virtual int32_t GetMaxTextureSize() const = 0;
michael@0 465
michael@0 466 /**
michael@0 467 * Return the name of the layer manager's backend.
michael@0 468 */
michael@0 469 virtual void GetBackendName(nsAString& aName) = 0;
michael@0 470
michael@0 471 /**
michael@0 472 * This setter can be used anytime. The user data for all keys is
michael@0 473 * initially null. Ownership pases to the layer manager.
michael@0 474 */
michael@0 475 void SetUserData(void* aKey, LayerUserData* aData)
michael@0 476 {
michael@0 477 mUserData.Add(static_cast<gfx::UserDataKey*>(aKey), aData, LayerManagerUserDataDestroy);
michael@0 478 }
michael@0 479 /**
michael@0 480 * This can be used anytime. Ownership passes to the caller!
michael@0 481 */
michael@0 482 nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
michael@0 483 {
michael@0 484 nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
michael@0 485 return d;
michael@0 486 }
michael@0 487 /**
michael@0 488 * This getter can be used anytime.
michael@0 489 */
michael@0 490 bool HasUserData(void* aKey)
michael@0 491 {
michael@0 492 return mUserData.Has(static_cast<gfx::UserDataKey*>(aKey));
michael@0 493 }
michael@0 494 /**
michael@0 495 * This getter can be used anytime. Ownership is retained by the layer
michael@0 496 * manager.
michael@0 497 */
michael@0 498 LayerUserData* GetUserData(void* aKey) const
michael@0 499 {
michael@0 500 return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
michael@0 501 }
michael@0 502
michael@0 503 /**
michael@0 504 * Must be called outside of a layers transaction.
michael@0 505 *
michael@0 506 * For the subtree rooted at |aSubtree|, this attempts to free up
michael@0 507 * any free-able resources like retained buffers, but may do nothing
michael@0 508 * at all. After this call, the layer tree is left in an undefined
michael@0 509 * state; the layers in |aSubtree|'s subtree may no longer have
michael@0 510 * buffers with valid content and may no longer be able to draw
michael@0 511 * their visible and valid regions.
michael@0 512 *
michael@0 513 * In general, a painting or forwarding transaction on |this| must
michael@0 514 * complete on the tree before it returns to a valid state.
michael@0 515 *
michael@0 516 * Resource freeing begins from |aSubtree| or |mRoot| if |aSubtree|
michael@0 517 * is null. |aSubtree|'s manager must be this.
michael@0 518 */
michael@0 519 virtual void ClearCachedResources(Layer* aSubtree = nullptr) {}
michael@0 520
michael@0 521 /**
michael@0 522 * Flag the next paint as the first for a document.
michael@0 523 */
michael@0 524 virtual void SetIsFirstPaint() {}
michael@0 525
michael@0 526 /**
michael@0 527 * Make sure that the previous transaction has been entirely
michael@0 528 * completed.
michael@0 529 *
michael@0 530 * Note: This may sychronously wait on a remote compositor
michael@0 531 * to complete rendering.
michael@0 532 */
michael@0 533 virtual void FlushRendering() { }
michael@0 534
michael@0 535 /**
michael@0 536 * Checks if we need to invalidate the OS widget to trigger
michael@0 537 * painting when updating this layer manager.
michael@0 538 */
michael@0 539 virtual bool NeedsWidgetInvalidation() { return true; }
michael@0 540
michael@0 541 virtual const char* Name() const { return "???"; }
michael@0 542
michael@0 543 /**
michael@0 544 * Dump information about this layer manager and its managed tree to
michael@0 545 * aFile, which defaults to stderr.
michael@0 546 */
michael@0 547 void Dump(FILE* aFile=nullptr, const char* aPrefix="", bool aDumpHtml=false);
michael@0 548 /**
michael@0 549 * Dump information about just this layer manager itself to aFile,
michael@0 550 * which defaults to stderr.
michael@0 551 */
michael@0 552 void DumpSelf(FILE* aFile=nullptr, const char* aPrefix="");
michael@0 553
michael@0 554 /**
michael@0 555 * Log information about this layer manager and its managed tree to
michael@0 556 * the NSPR log (if enabled for "Layers").
michael@0 557 */
michael@0 558 void Log(const char* aPrefix="");
michael@0 559 /**
michael@0 560 * Log information about just this layer manager itself to the NSPR
michael@0 561 * log (if enabled for "Layers").
michael@0 562 */
michael@0 563 void LogSelf(const char* aPrefix="");
michael@0 564
michael@0 565 /**
michael@0 566 * Record (and return) frame-intervals and paint-times for frames which were presented
michael@0 567 * between calling StartFrameTimeRecording and StopFrameTimeRecording.
michael@0 568 *
michael@0 569 * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is called too late
michael@0 570 * (elements were overwritten since Start), result is considered invalid and hence empty.
michael@0 571 * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were less frequent).
michael@0 572 * Can be changed (up to 1 hour) via pref: toolkit.framesRecording.bufferSize.
michael@0 573 * - Note: the first frame-interval may be longer than expected because last frame
michael@0 574 * might have been presented some time before calling StartFrameTimeRecording.
michael@0 575 */
michael@0 576
michael@0 577 /**
michael@0 578 * Returns a handle which represents current recording start position.
michael@0 579 */
michael@0 580 virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize);
michael@0 581
michael@0 582 /**
michael@0 583 * Clears, then populates aFrameIntervals with the recorded frame timing
michael@0 584 * data. The array will be empty if data was overwritten since
michael@0 585 * aStartIndex was obtained.
michael@0 586 */
michael@0 587 virtual void StopFrameTimeRecording(uint32_t aStartIndex,
michael@0 588 nsTArray<float>& aFrameIntervals);
michael@0 589
michael@0 590 void RecordFrame();
michael@0 591 void PostPresent();
michael@0 592
michael@0 593 void BeginTabSwitch();
michael@0 594
michael@0 595 static bool IsLogEnabled();
michael@0 596 static PRLogModuleInfo* GetLog() { return sLog; }
michael@0 597
michael@0 598 bool IsCompositingCheap(LayersBackend aBackend)
michael@0 599 {
michael@0 600 // LayersBackend::LAYERS_NONE is an error state, but in that case we should try to
michael@0 601 // avoid loading the compositor!
michael@0 602 return LayersBackend::LAYERS_BASIC != aBackend && LayersBackend::LAYERS_NONE != aBackend;
michael@0 603 }
michael@0 604
michael@0 605 virtual bool IsCompositingCheap() { return true; }
michael@0 606
michael@0 607 bool IsInTransaction() const { return mInTransaction; }
michael@0 608
michael@0 609 virtual void SetRegionToClear(const nsIntRegion& aRegion)
michael@0 610 {
michael@0 611 mRegionToClear = aRegion;
michael@0 612 }
michael@0 613
michael@0 614 protected:
michael@0 615 nsRefPtr<Layer> mRoot;
michael@0 616 gfx::UserData mUserData;
michael@0 617 bool mDestroyed;
michael@0 618 bool mSnapEffectiveTransforms;
michael@0 619
michael@0 620 nsIntRegion mRegionToClear;
michael@0 621
michael@0 622 // Protected destructor, to discourage deletion outside of Release():
michael@0 623 virtual ~LayerManager() {}
michael@0 624
michael@0 625 // Print interesting information about this into aTo. Internally
michael@0 626 // used to implement Dump*() and Log*().
michael@0 627 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 628
michael@0 629 static void InitLog();
michael@0 630 static PRLogModuleInfo* sLog;
michael@0 631 uint64_t mId;
michael@0 632 bool mInTransaction;
michael@0 633 private:
michael@0 634 struct FramesTimingRecording
michael@0 635 {
michael@0 636 // Stores state and data for frame intervals and paint times recording.
michael@0 637 // see LayerManager::StartFrameTimeRecording() at Layers.cpp for more details.
michael@0 638 FramesTimingRecording()
michael@0 639 : mIsPaused(true)
michael@0 640 , mNextIndex(0)
michael@0 641 {}
michael@0 642 bool mIsPaused;
michael@0 643 uint32_t mNextIndex;
michael@0 644 TimeStamp mLastFrameTime;
michael@0 645 nsTArray<float> mIntervals;
michael@0 646 uint32_t mLatestStartIndex;
michael@0 647 uint32_t mCurrentRunStartIndex;
michael@0 648 };
michael@0 649 FramesTimingRecording mRecording;
michael@0 650
michael@0 651 TimeStamp mTabSwitchStart;
michael@0 652 };
michael@0 653
michael@0 654 typedef InfallibleTArray<Animation> AnimationArray;
michael@0 655
michael@0 656 struct AnimData {
michael@0 657 InfallibleTArray<nsStyleAnimation::Value> mStartValues;
michael@0 658 InfallibleTArray<nsStyleAnimation::Value> mEndValues;
michael@0 659 InfallibleTArray<nsAutoPtr<mozilla::css::ComputedTimingFunction> > mFunctions;
michael@0 660 };
michael@0 661
michael@0 662 /**
michael@0 663 * A Layer represents anything that can be rendered onto a destination
michael@0 664 * surface.
michael@0 665 */
michael@0 666 class Layer {
michael@0 667 NS_INLINE_DECL_REFCOUNTING(Layer)
michael@0 668
michael@0 669 public:
michael@0 670 // Keep these in alphabetical order
michael@0 671 enum LayerType {
michael@0 672 TYPE_CANVAS,
michael@0 673 TYPE_COLOR,
michael@0 674 TYPE_CONTAINER,
michael@0 675 TYPE_IMAGE,
michael@0 676 TYPE_READBACK,
michael@0 677 TYPE_REF,
michael@0 678 TYPE_SHADOW,
michael@0 679 TYPE_THEBES
michael@0 680 };
michael@0 681
michael@0 682 /**
michael@0 683 * Returns the LayerManager this Layer belongs to. Note that the layer
michael@0 684 * manager might be in a destroyed state, at which point it's only
michael@0 685 * valid to set/get user data from it.
michael@0 686 */
michael@0 687 LayerManager* Manager() { return mManager; }
michael@0 688
michael@0 689 enum {
michael@0 690 /**
michael@0 691 * If this is set, the caller is promising that by the end of this
michael@0 692 * transaction the entire visible region (as specified by
michael@0 693 * SetVisibleRegion) will be filled with opaque content.
michael@0 694 */
michael@0 695 CONTENT_OPAQUE = 0x01,
michael@0 696 /**
michael@0 697 * If this is set, the caller is notifying that the contents of this layer
michael@0 698 * require per-component alpha for optimal fidelity. However, there is no
michael@0 699 * guarantee that component alpha will be supported for this layer at
michael@0 700 * paint time.
michael@0 701 * This should never be set at the same time as CONTENT_OPAQUE.
michael@0 702 */
michael@0 703 CONTENT_COMPONENT_ALPHA = 0x02,
michael@0 704
michael@0 705 /**
michael@0 706 * If this is set then this layer is part of a preserve-3d group, and should
michael@0 707 * be sorted with sibling layers that are also part of the same group.
michael@0 708 */
michael@0 709 CONTENT_PRESERVE_3D = 0x04,
michael@0 710 /**
michael@0 711 * This indicates that the transform may be changed on during an empty
michael@0 712 * transaction where there is no possibility of redrawing the content, so the
michael@0 713 * implementation should be ready for that.
michael@0 714 */
michael@0 715 CONTENT_MAY_CHANGE_TRANSFORM = 0x08,
michael@0 716
michael@0 717 /**
michael@0 718 * Disable subpixel AA for this layer. This is used if the display isn't suited
michael@0 719 * for subpixel AA like hidpi or rotated content.
michael@0 720 */
michael@0 721 CONTENT_DISABLE_SUBPIXEL_AA = 0x10
michael@0 722 };
michael@0 723 /**
michael@0 724 * CONSTRUCTION PHASE ONLY
michael@0 725 * This lets layout make some promises about what will be drawn into the
michael@0 726 * visible region of the ThebesLayer. This enables internal quality
michael@0 727 * and performance optimizations.
michael@0 728 */
michael@0 729 void SetContentFlags(uint32_t aFlags)
michael@0 730 {
michael@0 731 NS_ASSERTION((aFlags & (CONTENT_OPAQUE | CONTENT_COMPONENT_ALPHA)) !=
michael@0 732 (CONTENT_OPAQUE | CONTENT_COMPONENT_ALPHA),
michael@0 733 "Can't be opaque and require component alpha");
michael@0 734 if (mContentFlags != aFlags) {
michael@0 735 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ContentFlags", this));
michael@0 736 mContentFlags = aFlags;
michael@0 737 Mutated();
michael@0 738 }
michael@0 739 }
michael@0 740 /**
michael@0 741 * CONSTRUCTION PHASE ONLY
michael@0 742 * Tell this layer which region will be visible. The visible region
michael@0 743 * is a region which contains all the contents of the layer that can
michael@0 744 * actually affect the rendering of the window. It can exclude areas
michael@0 745 * that are covered by opaque contents of other layers, and it can
michael@0 746 * exclude areas where this layer simply contains no content at all.
michael@0 747 * (This can be an overapproximation to the "true" visible region.)
michael@0 748 *
michael@0 749 * There is no general guarantee that drawing outside the bounds of the
michael@0 750 * visible region will be ignored. So if a layer draws outside the bounds
michael@0 751 * of its visible region, it needs to ensure that what it draws is valid.
michael@0 752 */
michael@0 753 virtual void SetVisibleRegion(const nsIntRegion& aRegion)
michael@0 754 {
michael@0 755 if (!mVisibleRegion.IsEqual(aRegion)) {
michael@0 756 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) VisibleRegion was %s is %s", this,
michael@0 757 mVisibleRegion.ToString().get(), aRegion.ToString().get()));
michael@0 758 mVisibleRegion = aRegion;
michael@0 759 Mutated();
michael@0 760 }
michael@0 761 }
michael@0 762
michael@0 763 /*
michael@0 764 * Compositor event handling
michael@0 765 * =========================
michael@0 766 * When a touch-start event (or similar) is sent to the AsyncPanZoomController,
michael@0 767 * it needs to decide whether the event should be sent to the main thread.
michael@0 768 * Each layer has a list of event handling regions. When the compositor needs
michael@0 769 * to determine how to handle a touch event, it scans the layer tree from top
michael@0 770 * to bottom in z-order (traversing children before their parents). Points
michael@0 771 * outside the clip region for a layer cause that layer (and its subtree)
michael@0 772 * to be ignored. If a layer has a mask layer, and that mask layer's alpha
michael@0 773 * value is zero at the event point, then the layer and its subtree should
michael@0 774 * be ignored.
michael@0 775 * For each layer, if the point is outside its hit region, we ignore the layer
michael@0 776 * and move onto the next. If the point is inside its hit region but
michael@0 777 * outside the dispatch-to-content region, we can initiate a gesture without
michael@0 778 * consulting the content thread. Otherwise we must dispatch the event to
michael@0 779 * content.
michael@0 780 */
michael@0 781 /**
michael@0 782 * CONSTRUCTION PHASE ONLY
michael@0 783 * Set the event handling region.
michael@0 784 */
michael@0 785 void SetEventRegions(const EventRegions& aRegions)
michael@0 786 {
michael@0 787 if (mEventRegions != aRegions) {
michael@0 788 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) eventregions were %s, now %s", this,
michael@0 789 mEventRegions.ToString().get(), aRegions.ToString().get()));
michael@0 790 mEventRegions = aRegions;
michael@0 791 Mutated();
michael@0 792 }
michael@0 793 }
michael@0 794
michael@0 795 /**
michael@0 796 * CONSTRUCTION PHASE ONLY
michael@0 797 * Set the opacity which will be applied to this layer as it
michael@0 798 * is composited to the destination.
michael@0 799 */
michael@0 800 void SetOpacity(float aOpacity)
michael@0 801 {
michael@0 802 if (mOpacity != aOpacity) {
michael@0 803 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) Opacity", this));
michael@0 804 mOpacity = aOpacity;
michael@0 805 Mutated();
michael@0 806 }
michael@0 807 }
michael@0 808
michael@0 809 void SetMixBlendMode(gfx::CompositionOp aMixBlendMode)
michael@0 810 {
michael@0 811 if (mMixBlendMode != aMixBlendMode) {
michael@0 812 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) MixBlendMode", this));
michael@0 813 mMixBlendMode = aMixBlendMode;
michael@0 814 Mutated();
michael@0 815 }
michael@0 816 }
michael@0 817
michael@0 818 void DeprecatedSetMixBlendMode(gfxContext::GraphicsOperator aMixBlendMode)
michael@0 819 {
michael@0 820 SetMixBlendMode(gfx::CompositionOpForOp(aMixBlendMode));
michael@0 821 }
michael@0 822
michael@0 823 void SetForceIsolatedGroup(bool aForceIsolatedGroup)
michael@0 824 {
michael@0 825 if(mForceIsolatedGroup != aForceIsolatedGroup) {
michael@0 826 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ForceIsolatedGroup", this));
michael@0 827 mForceIsolatedGroup = aForceIsolatedGroup;
michael@0 828 Mutated();
michael@0 829 }
michael@0 830 }
michael@0 831
michael@0 832 bool GetForceIsolatedGroup() const
michael@0 833 {
michael@0 834 return mForceIsolatedGroup;
michael@0 835 }
michael@0 836
michael@0 837 /**
michael@0 838 * CONSTRUCTION PHASE ONLY
michael@0 839 * Set a clip rect which will be applied to this layer as it is
michael@0 840 * composited to the destination. The coordinates are relative to
michael@0 841 * the parent layer (i.e. the contents of this layer
michael@0 842 * are transformed before this clip rect is applied).
michael@0 843 * For the root layer, the coordinates are relative to the widget,
michael@0 844 * in device pixels.
michael@0 845 * If aRect is null no clipping will be performed.
michael@0 846 */
michael@0 847 void SetClipRect(const nsIntRect* aRect)
michael@0 848 {
michael@0 849 if (mUseClipRect) {
michael@0 850 if (!aRect) {
michael@0 851 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ClipRect was %d,%d,%d,%d is <none>", this,
michael@0 852 mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height));
michael@0 853 mUseClipRect = false;
michael@0 854 Mutated();
michael@0 855 } else {
michael@0 856 if (!aRect->IsEqualEdges(mClipRect)) {
michael@0 857 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ClipRect was %d,%d,%d,%d is %d,%d,%d,%d", this,
michael@0 858 mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height,
michael@0 859 aRect->x, aRect->y, aRect->width, aRect->height));
michael@0 860 mClipRect = *aRect;
michael@0 861 Mutated();
michael@0 862 }
michael@0 863 }
michael@0 864 } else {
michael@0 865 if (aRect) {
michael@0 866 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ClipRect was <none> is %d,%d,%d,%d", this,
michael@0 867 aRect->x, aRect->y, aRect->width, aRect->height));
michael@0 868 mUseClipRect = true;
michael@0 869 mClipRect = *aRect;
michael@0 870 Mutated();
michael@0 871 }
michael@0 872 }
michael@0 873 }
michael@0 874
michael@0 875 /**
michael@0 876 * CONSTRUCTION PHASE ONLY
michael@0 877 * Set a layer to mask this layer.
michael@0 878 *
michael@0 879 * The mask layer should be applied using its effective transform (after it
michael@0 880 * is calculated by ComputeEffectiveTransformForMaskLayer), this should use
michael@0 881 * this layer's parent's transform and the mask layer's transform, but not
michael@0 882 * this layer's. That is, the mask layer is specified relative to this layer's
michael@0 883 * position in it's parent layer's coord space.
michael@0 884 * Currently, only 2D translations are supported for the mask layer transform.
michael@0 885 *
michael@0 886 * Ownership of aMaskLayer passes to this.
michael@0 887 * Typical use would be an ImageLayer with an alpha image used for masking.
michael@0 888 * See also ContainerState::BuildMaskLayer in FrameLayerBuilder.cpp.
michael@0 889 */
michael@0 890 void SetMaskLayer(Layer* aMaskLayer)
michael@0 891 {
michael@0 892 #ifdef DEBUG
michael@0 893 if (aMaskLayer) {
michael@0 894 bool maskIs2D = aMaskLayer->GetTransform().CanDraw2D();
michael@0 895 NS_ASSERTION(maskIs2D, "Mask layer has invalid transform.");
michael@0 896 }
michael@0 897 #endif
michael@0 898
michael@0 899 if (mMaskLayer != aMaskLayer) {
michael@0 900 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) MaskLayer", this));
michael@0 901 mMaskLayer = aMaskLayer;
michael@0 902 Mutated();
michael@0 903 }
michael@0 904 }
michael@0 905
michael@0 906 /**
michael@0 907 * CONSTRUCTION PHASE ONLY
michael@0 908 * Tell this layer what its transform should be. The transformation
michael@0 909 * is applied when compositing the layer into its parent container.
michael@0 910 */
michael@0 911 void SetBaseTransform(const gfx::Matrix4x4& aMatrix)
michael@0 912 {
michael@0 913 NS_ASSERTION(!aMatrix.IsSingular(),
michael@0 914 "Shouldn't be trying to draw with a singular matrix!");
michael@0 915 mPendingTransform = nullptr;
michael@0 916 if (mTransform == aMatrix) {
michael@0 917 return;
michael@0 918 }
michael@0 919 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) BaseTransform", this));
michael@0 920 mTransform = aMatrix;
michael@0 921 Mutated();
michael@0 922 }
michael@0 923
michael@0 924 /**
michael@0 925 * Can be called at any time.
michael@0 926 *
michael@0 927 * Like SetBaseTransform(), but can be called before the next
michael@0 928 * transform (i.e. outside an open transaction). Semantically, this
michael@0 929 * method enqueues a new transform value to be set immediately after
michael@0 930 * the next transaction is opened.
michael@0 931 */
michael@0 932 void SetBaseTransformForNextTransaction(const gfx::Matrix4x4& aMatrix)
michael@0 933 {
michael@0 934 mPendingTransform = new gfx::Matrix4x4(aMatrix);
michael@0 935 }
michael@0 936
michael@0 937 void SetPostScale(float aXScale, float aYScale)
michael@0 938 {
michael@0 939 if (mPostXScale == aXScale && mPostYScale == aYScale) {
michael@0 940 return;
michael@0 941 }
michael@0 942 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PostScale", this));
michael@0 943 mPostXScale = aXScale;
michael@0 944 mPostYScale = aYScale;
michael@0 945 Mutated();
michael@0 946 }
michael@0 947
michael@0 948 /**
michael@0 949 * CONSTRUCTION PHASE ONLY
michael@0 950 * A layer is "fixed position" when it draws content from a content
michael@0 951 * (not chrome) document, the topmost content document has a root scrollframe
michael@0 952 * with a displayport, but the layer does not move when that displayport scrolls.
michael@0 953 */
michael@0 954 void SetIsFixedPosition(bool aFixedPosition)
michael@0 955 {
michael@0 956 if (mIsFixedPosition != aFixedPosition) {
michael@0 957 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) IsFixedPosition", this));
michael@0 958 mIsFixedPosition = aFixedPosition;
michael@0 959 Mutated();
michael@0 960 }
michael@0 961 }
michael@0 962
michael@0 963 // Call AddAnimation to add a new animation to this layer from layout code.
michael@0 964 // Caller must fill in all the properties of the returned animation.
michael@0 965 Animation* AddAnimation();
michael@0 966 // ClearAnimations clears animations on this layer.
michael@0 967 void ClearAnimations();
michael@0 968 // This is only called when the layer tree is updated. Do not call this from
michael@0 969 // layout code. To add an animation to this layer, use AddAnimation.
michael@0 970 void SetAnimations(const AnimationArray& aAnimations);
michael@0 971
michael@0 972 // These are a parallel to AddAnimation and clearAnimations, except
michael@0 973 // they add pending animations that apply only when the next
michael@0 974 // transaction is begun. (See also
michael@0 975 // SetBaseTransformForNextTransaction.)
michael@0 976 Animation* AddAnimationForNextTransaction();
michael@0 977 void ClearAnimationsForNextTransaction();
michael@0 978
michael@0 979 /**
michael@0 980 * CONSTRUCTION PHASE ONLY
michael@0 981 * If a layer is "fixed position", this determines which point on the layer
michael@0 982 * is considered the "anchor" point, that is, the point which remains in the
michael@0 983 * same position when compositing the layer tree with a transformation
michael@0 984 * (such as when asynchronously scrolling and zooming).
michael@0 985 */
michael@0 986 void SetFixedPositionAnchor(const LayerPoint& aAnchor)
michael@0 987 {
michael@0 988 if (mAnchor != aAnchor) {
michael@0 989 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FixedPositionAnchor", this));
michael@0 990 mAnchor = aAnchor;
michael@0 991 Mutated();
michael@0 992 }
michael@0 993 }
michael@0 994
michael@0 995 /**
michael@0 996 * CONSTRUCTION PHASE ONLY
michael@0 997 * If a layer represents a fixed position element or elements that are on
michael@0 998 * a document that has had fixed position element margins set on it, these
michael@0 999 * will be mirrored here. This allows for asynchronous animation of the
michael@0 1000 * margins by reconciling the difference between this value and a value that
michael@0 1001 * is updated more frequently.
michael@0 1002 * If the left or top margins are negative, it means that the elements this
michael@0 1003 * layer represents are auto-positioned, and so fixed position margins should
michael@0 1004 * not have an effect on the corresponding axis.
michael@0 1005 */
michael@0 1006 void SetFixedPositionMargins(const LayerMargin& aMargins)
michael@0 1007 {
michael@0 1008 if (mMargins != aMargins) {
michael@0 1009 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FixedPositionMargins", this));
michael@0 1010 mMargins = aMargins;
michael@0 1011 Mutated();
michael@0 1012 }
michael@0 1013 }
michael@0 1014
michael@0 1015 /**
michael@0 1016 * CONSTRUCTION PHASE ONLY
michael@0 1017 * If a layer is "sticky position", |aScrollId| holds the scroll identifier
michael@0 1018 * of the scrollable content that contains it. The difference between the two
michael@0 1019 * rectangles |aOuter| and |aInner| is treated as two intervals in each
michael@0 1020 * dimension, with the current scroll position at the origin. For each
michael@0 1021 * dimension, while that component of the scroll position lies within either
michael@0 1022 * interval, the layer should not move relative to its scrolling container.
michael@0 1023 */
michael@0 1024 void SetStickyPositionData(FrameMetrics::ViewID aScrollId, LayerRect aOuter,
michael@0 1025 LayerRect aInner)
michael@0 1026 {
michael@0 1027 if (!mStickyPositionData ||
michael@0 1028 !mStickyPositionData->mOuter.IsEqualEdges(aOuter) ||
michael@0 1029 !mStickyPositionData->mInner.IsEqualEdges(aInner)) {
michael@0 1030 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) StickyPositionData", this));
michael@0 1031 if (!mStickyPositionData) {
michael@0 1032 mStickyPositionData = new StickyPositionData;
michael@0 1033 }
michael@0 1034 mStickyPositionData->mScrollId = aScrollId;
michael@0 1035 mStickyPositionData->mOuter = aOuter;
michael@0 1036 mStickyPositionData->mInner = aInner;
michael@0 1037 Mutated();
michael@0 1038 }
michael@0 1039 }
michael@0 1040
michael@0 1041 enum ScrollDirection {
michael@0 1042 NONE,
michael@0 1043 VERTICAL,
michael@0 1044 HORIZONTAL
michael@0 1045 };
michael@0 1046
michael@0 1047 /**
michael@0 1048 * CONSTRUCTION PHASE ONLY
michael@0 1049 * If a layer is a scrollbar layer, |aScrollId| holds the scroll identifier
michael@0 1050 * of the scrollable content that the scrollbar is for.
michael@0 1051 */
michael@0 1052 void SetScrollbarData(FrameMetrics::ViewID aScrollId, ScrollDirection aDir)
michael@0 1053 {
michael@0 1054 if (mScrollbarTargetId != aScrollId ||
michael@0 1055 mScrollbarDirection != aDir) {
michael@0 1056 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollbarData", this));
michael@0 1057 mScrollbarTargetId = aScrollId;
michael@0 1058 mScrollbarDirection = aDir;
michael@0 1059 Mutated();
michael@0 1060 }
michael@0 1061 }
michael@0 1062
michael@0 1063 // These getters can be used anytime.
michael@0 1064 float GetOpacity() { return mOpacity; }
michael@0 1065 gfx::CompositionOp GetMixBlendMode() const { return mMixBlendMode; }
michael@0 1066 const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; }
michael@0 1067 uint32_t GetContentFlags() { return mContentFlags; }
michael@0 1068 const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
michael@0 1069 const EventRegions& GetEventRegions() const { return mEventRegions; }
michael@0 1070 ContainerLayer* GetParent() { return mParent; }
michael@0 1071 Layer* GetNextSibling() { return mNextSibling; }
michael@0 1072 const Layer* GetNextSibling() const { return mNextSibling; }
michael@0 1073 Layer* GetPrevSibling() { return mPrevSibling; }
michael@0 1074 const Layer* GetPrevSibling() const { return mPrevSibling; }
michael@0 1075 virtual Layer* GetFirstChild() const { return nullptr; }
michael@0 1076 virtual Layer* GetLastChild() const { return nullptr; }
michael@0 1077 const gfx::Matrix4x4 GetTransform() const;
michael@0 1078 const gfx::Matrix4x4& GetBaseTransform() const { return mTransform; }
michael@0 1079 float GetPostXScale() const { return mPostXScale; }
michael@0 1080 float GetPostYScale() const { return mPostYScale; }
michael@0 1081 bool GetIsFixedPosition() { return mIsFixedPosition; }
michael@0 1082 bool GetIsStickyPosition() { return mStickyPositionData; }
michael@0 1083 LayerPoint GetFixedPositionAnchor() { return mAnchor; }
michael@0 1084 const LayerMargin& GetFixedPositionMargins() { return mMargins; }
michael@0 1085 FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
michael@0 1086 const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
michael@0 1087 const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
michael@0 1088 FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
michael@0 1089 ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
michael@0 1090 Layer* GetMaskLayer() const { return mMaskLayer; }
michael@0 1091
michael@0 1092 // Note that all lengths in animation data are either in CSS pixels or app
michael@0 1093 // units and must be converted to device pixels by the compositor.
michael@0 1094 AnimationArray& GetAnimations() { return mAnimations; }
michael@0 1095 InfallibleTArray<AnimData>& GetAnimationData() { return mAnimationData; }
michael@0 1096
michael@0 1097 uint64_t GetAnimationGeneration() { return mAnimationGeneration; }
michael@0 1098 void SetAnimationGeneration(uint64_t aCount) { mAnimationGeneration = aCount; }
michael@0 1099
michael@0 1100 /**
michael@0 1101 * Returns the local transform for this layer: either mTransform or,
michael@0 1102 * for shadow layers, GetShadowTransform()
michael@0 1103 */
michael@0 1104 const gfx::Matrix4x4 GetLocalTransform();
michael@0 1105
michael@0 1106 /**
michael@0 1107 * Returns the local opacity for this layer: either mOpacity or,
michael@0 1108 * for shadow layers, GetShadowOpacity()
michael@0 1109 */
michael@0 1110 const float GetLocalOpacity();
michael@0 1111
michael@0 1112 /**
michael@0 1113 * DRAWING PHASE ONLY
michael@0 1114 *
michael@0 1115 * Apply pending changes to layers before drawing them, if those
michael@0 1116 * pending changes haven't been overridden by later changes.
michael@0 1117 */
michael@0 1118 void ApplyPendingUpdatesToSubtree();
michael@0 1119
michael@0 1120 /**
michael@0 1121 * DRAWING PHASE ONLY
michael@0 1122 *
michael@0 1123 * Write layer-subtype-specific attributes into aAttrs. Used to
michael@0 1124 * synchronize layer attributes to their shadows'.
michael@0 1125 */
michael@0 1126 virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { }
michael@0 1127
michael@0 1128 // Returns true if it's OK to save the contents of aLayer in an
michael@0 1129 // opaque surface (a surface without an alpha channel).
michael@0 1130 // If we can use a surface without an alpha channel, we should, because
michael@0 1131 // it will often make painting of antialiased text faster and higher
michael@0 1132 // quality.
michael@0 1133 bool CanUseOpaqueSurface();
michael@0 1134
michael@0 1135 SurfaceMode GetSurfaceMode()
michael@0 1136 {
michael@0 1137 if (CanUseOpaqueSurface())
michael@0 1138 return SurfaceMode::SURFACE_OPAQUE;
michael@0 1139 if (mContentFlags & CONTENT_COMPONENT_ALPHA)
michael@0 1140 return SurfaceMode::SURFACE_COMPONENT_ALPHA;
michael@0 1141 return SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
michael@0 1142 }
michael@0 1143
michael@0 1144 /**
michael@0 1145 * This setter can be used anytime. The user data for all keys is
michael@0 1146 * initially null. Ownership pases to the layer manager.
michael@0 1147 */
michael@0 1148 void SetUserData(void* aKey, LayerUserData* aData)
michael@0 1149 {
michael@0 1150 mUserData.Add(static_cast<gfx::UserDataKey*>(aKey), aData, LayerManagerUserDataDestroy);
michael@0 1151 }
michael@0 1152 /**
michael@0 1153 * This can be used anytime. Ownership passes to the caller!
michael@0 1154 */
michael@0 1155 nsAutoPtr<LayerUserData> RemoveUserData(void* aKey)
michael@0 1156 {
michael@0 1157 nsAutoPtr<LayerUserData> d(static_cast<LayerUserData*>(mUserData.Remove(static_cast<gfx::UserDataKey*>(aKey))));
michael@0 1158 return d;
michael@0 1159 }
michael@0 1160 /**
michael@0 1161 * This getter can be used anytime.
michael@0 1162 */
michael@0 1163 bool HasUserData(void* aKey)
michael@0 1164 {
michael@0 1165 return mUserData.Has(static_cast<gfx::UserDataKey*>(aKey));
michael@0 1166 }
michael@0 1167 /**
michael@0 1168 * This getter can be used anytime. Ownership is retained by the layer
michael@0 1169 * manager.
michael@0 1170 */
michael@0 1171 LayerUserData* GetUserData(void* aKey) const
michael@0 1172 {
michael@0 1173 return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
michael@0 1174 }
michael@0 1175
michael@0 1176 /**
michael@0 1177 * |Disconnect()| is used by layers hooked up over IPC. It may be
michael@0 1178 * called at any time, and may not be called at all. Using an
michael@0 1179 * IPC-enabled layer after Destroy() (drawing etc.) results in a
michael@0 1180 * safe no-op; no crashy or uaf etc.
michael@0 1181 *
michael@0 1182 * XXX: this interface is essentially LayerManager::Destroy, but at
michael@0 1183 * Layer granularity. It might be beneficial to unify them.
michael@0 1184 */
michael@0 1185 virtual void Disconnect() {}
michael@0 1186
michael@0 1187 /**
michael@0 1188 * Dynamic downcast to a Thebes layer. Returns null if this is not
michael@0 1189 * a ThebesLayer.
michael@0 1190 */
michael@0 1191 virtual ThebesLayer* AsThebesLayer() { return nullptr; }
michael@0 1192
michael@0 1193 /**
michael@0 1194 * Dynamic cast to a ContainerLayer. Returns null if this is not
michael@0 1195 * a ContainerLayer.
michael@0 1196 */
michael@0 1197 virtual ContainerLayer* AsContainerLayer() { return nullptr; }
michael@0 1198 virtual const ContainerLayer* AsContainerLayer() const { return nullptr; }
michael@0 1199
michael@0 1200 /**
michael@0 1201 * Dynamic cast to a RefLayer. Returns null if this is not a
michael@0 1202 * RefLayer.
michael@0 1203 */
michael@0 1204 virtual RefLayer* AsRefLayer() { return nullptr; }
michael@0 1205
michael@0 1206 /**
michael@0 1207 * Dynamic cast to a Color. Returns null if this is not a
michael@0 1208 * ColorLayer.
michael@0 1209 */
michael@0 1210 virtual ColorLayer* AsColorLayer() { return nullptr; }
michael@0 1211
michael@0 1212 /**
michael@0 1213 * Dynamic cast to a LayerComposite. Return null if this is not a
michael@0 1214 * LayerComposite. Can be used anytime.
michael@0 1215 */
michael@0 1216 virtual LayerComposite* AsLayerComposite() { return nullptr; }
michael@0 1217
michael@0 1218 /**
michael@0 1219 * Dynamic cast to a ShadowableLayer. Return null if this is not a
michael@0 1220 * ShadowableLayer. Can be used anytime.
michael@0 1221 */
michael@0 1222 virtual ShadowableLayer* AsShadowableLayer() { return nullptr; }
michael@0 1223
michael@0 1224 // These getters can be used anytime. They return the effective
michael@0 1225 // values that should be used when drawing this layer to screen,
michael@0 1226 // accounting for this layer possibly being a shadow.
michael@0 1227 const nsIntRect* GetEffectiveClipRect();
michael@0 1228 const nsIntRegion& GetEffectiveVisibleRegion();
michael@0 1229
michael@0 1230 /**
michael@0 1231 * Returns the product of the opacities of this layer and all ancestors up
michael@0 1232 * to and excluding the nearest ancestor that has UseIntermediateSurface() set.
michael@0 1233 */
michael@0 1234 float GetEffectiveOpacity();
michael@0 1235
michael@0 1236 /**
michael@0 1237 * Returns the blendmode of this layer.
michael@0 1238 */
michael@0 1239 gfx::CompositionOp GetEffectiveMixBlendMode();
michael@0 1240 gfxContext::GraphicsOperator DeprecatedGetEffectiveMixBlendMode();
michael@0 1241
michael@0 1242 /**
michael@0 1243 * This returns the effective transform computed by
michael@0 1244 * ComputeEffectiveTransforms. Typically this is a transform that transforms
michael@0 1245 * this layer all the way to some intermediate surface or destination
michael@0 1246 * surface. For non-BasicLayers this will be a transform to the nearest
michael@0 1247 * ancestor with UseIntermediateSurface() (or to the root, if there is no
michael@0 1248 * such ancestor), but for BasicLayers it's different.
michael@0 1249 */
michael@0 1250 const gfx::Matrix4x4& GetEffectiveTransform() const { return mEffectiveTransform; }
michael@0 1251
michael@0 1252 /**
michael@0 1253 * @param aTransformToSurface the composition of the transforms
michael@0 1254 * from the parent layer (if any) to the destination pixel grid.
michael@0 1255 *
michael@0 1256 * Computes mEffectiveTransform for this layer and all its descendants.
michael@0 1257 * mEffectiveTransform transforms this layer up to the destination
michael@0 1258 * pixel grid (whatever aTransformToSurface is relative to).
michael@0 1259 *
michael@0 1260 * We promise that when this is called on a layer, all ancestor layers
michael@0 1261 * have already had ComputeEffectiveTransforms called.
michael@0 1262 */
michael@0 1263 virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) = 0;
michael@0 1264
michael@0 1265 /**
michael@0 1266 * computes the effective transform for a mask layer, if this layer has one
michael@0 1267 */
michael@0 1268 void ComputeEffectiveTransformForMaskLayer(const gfx::Matrix4x4& aTransformToSurface);
michael@0 1269
michael@0 1270 /**
michael@0 1271 * Calculate the scissor rect required when rendering this layer.
michael@0 1272 * Returns a rectangle relative to the intermediate surface belonging to the
michael@0 1273 * nearest ancestor that has an intermediate surface, or relative to the root
michael@0 1274 * viewport if no ancestor has an intermediate surface, corresponding to the
michael@0 1275 * clip rect for this layer intersected with aCurrentScissorRect.
michael@0 1276 * If no ancestor has an intermediate surface, the clip rect is transformed
michael@0 1277 * by aWorldTransform before being combined with aCurrentScissorRect, if
michael@0 1278 * aWorldTransform is non-null.
michael@0 1279 */
michael@0 1280 nsIntRect CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
michael@0 1281 const gfx::Matrix* aWorldTransform);
michael@0 1282
michael@0 1283 virtual const char* Name() const =0;
michael@0 1284 virtual LayerType GetType() const =0;
michael@0 1285
michael@0 1286 /**
michael@0 1287 * Only the implementation should call this. This is per-implementation
michael@0 1288 * private data. Normally, all layers with a given layer manager
michael@0 1289 * use the same type of ImplData.
michael@0 1290 */
michael@0 1291 void* ImplData() { return mImplData; }
michael@0 1292
michael@0 1293 /**
michael@0 1294 * Only the implementation should use these methods.
michael@0 1295 */
michael@0 1296 void SetParent(ContainerLayer* aParent) { mParent = aParent; }
michael@0 1297 void SetNextSibling(Layer* aSibling) { mNextSibling = aSibling; }
michael@0 1298 void SetPrevSibling(Layer* aSibling) { mPrevSibling = aSibling; }
michael@0 1299
michael@0 1300 /**
michael@0 1301 * Dump information about this layer manager and its managed tree to
michael@0 1302 * aFile, which defaults to stderr.
michael@0 1303 */
michael@0 1304 void Dump(FILE* aFile=nullptr, const char* aPrefix="", bool aDumpHtml=false);
michael@0 1305 /**
michael@0 1306 * Dump information about just this layer manager itself to aFile,
michael@0 1307 * which defaults to stderr.
michael@0 1308 */
michael@0 1309 void DumpSelf(FILE* aFile=nullptr, const char* aPrefix="");
michael@0 1310
michael@0 1311 /**
michael@0 1312 * Log information about this layer manager and its managed tree to
michael@0 1313 * the NSPR log (if enabled for "Layers").
michael@0 1314 */
michael@0 1315 void Log(const char* aPrefix="");
michael@0 1316 /**
michael@0 1317 * Log information about just this layer manager itself to the NSPR
michael@0 1318 * log (if enabled for "Layers").
michael@0 1319 */
michael@0 1320 void LogSelf(const char* aPrefix="");
michael@0 1321
michael@0 1322 // Print interesting information about this into aTo. Internally
michael@0 1323 // used to implement Dump*() and Log*(). If subclasses have
michael@0 1324 // additional interesting properties, they should override this with
michael@0 1325 // an implementation that first calls the base implementation then
michael@0 1326 // appends additional info to aTo.
michael@0 1327 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 1328
michael@0 1329 static bool IsLogEnabled() { return LayerManager::IsLogEnabled(); }
michael@0 1330
michael@0 1331 /**
michael@0 1332 * Returns the current area of the layer (in layer-space coordinates)
michael@0 1333 * marked as needed to be recomposited.
michael@0 1334 */
michael@0 1335 const nsIntRegion& GetInvalidRegion() { return mInvalidRegion; }
michael@0 1336 const void SetInvalidRegion(const nsIntRegion& aRect) { mInvalidRegion = aRect; }
michael@0 1337
michael@0 1338 /**
michael@0 1339 * Mark the entirety of the layer's visible region as being invalid.
michael@0 1340 */
michael@0 1341 void SetInvalidRectToVisibleRegion() { mInvalidRegion = GetVisibleRegion(); }
michael@0 1342
michael@0 1343 /**
michael@0 1344 * Adds to the current invalid rect.
michael@0 1345 */
michael@0 1346 void AddInvalidRect(const nsIntRect& aRect) { mInvalidRegion.Or(mInvalidRegion, aRect); }
michael@0 1347
michael@0 1348 /**
michael@0 1349 * Clear the invalid rect, marking the layer as being identical to what is currently
michael@0 1350 * composited.
michael@0 1351 */
michael@0 1352 void ClearInvalidRect() { mInvalidRegion.SetEmpty(); }
michael@0 1353
michael@0 1354 void ApplyPendingUpdatesForThisTransaction();
michael@0 1355
michael@0 1356 #ifdef DEBUG
michael@0 1357 void SetDebugColorIndex(uint32_t aIndex) { mDebugColorIndex = aIndex; }
michael@0 1358 uint32_t GetDebugColorIndex() { return mDebugColorIndex; }
michael@0 1359 #endif
michael@0 1360
michael@0 1361 virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
michael@0 1362
michael@0 1363
michael@0 1364 void Mutated()
michael@0 1365 {
michael@0 1366 mManager->Mutated(this);
michael@0 1367 }
michael@0 1368
michael@0 1369 protected:
michael@0 1370 Layer(LayerManager* aManager, void* aImplData);
michael@0 1371
michael@0 1372 // Protected destructor, to discourage deletion outside of Release():
michael@0 1373 virtual ~Layer();
michael@0 1374
michael@0 1375 /**
michael@0 1376 * We can snap layer transforms for two reasons:
michael@0 1377 * 1) To avoid unnecessary resampling when a transform is a translation
michael@0 1378 * by a non-integer number of pixels.
michael@0 1379 * Snapping the translation to an integer number of pixels avoids
michael@0 1380 * blurring the layer and can be faster to composite.
michael@0 1381 * 2) When a layer is used to render a rectangular object, we need to
michael@0 1382 * emulate the rendering of rectangular inactive content and snap the
michael@0 1383 * edges of the rectangle to pixel boundaries. This is both to ensure
michael@0 1384 * layer rendering is consistent with inactive content rendering, and to
michael@0 1385 * avoid seams.
michael@0 1386 * This function implements type 1 snapping. If aTransform is a 2D
michael@0 1387 * translation, and this layer's layer manager has enabled snapping
michael@0 1388 * (which is the default), return aTransform with the translation snapped
michael@0 1389 * to nearest pixels. Otherwise just return aTransform. Call this when the
michael@0 1390 * layer does not correspond to a single rectangular content object.
michael@0 1391 * This function does not try to snap if aTransform has a scale, because in
michael@0 1392 * that case resampling is inevitable and there's no point in trying to
michael@0 1393 * avoid it. In fact snapping can cause problems because pixel edges in the
michael@0 1394 * layer's content can be rendered unpredictably (jiggling) as the scale
michael@0 1395 * interacts with the snapping of the translation, especially with animated
michael@0 1396 * transforms.
michael@0 1397 * @param aResidualTransform a transform to apply before the result transform
michael@0 1398 * in order to get the results to completely match aTransform.
michael@0 1399 */
michael@0 1400 gfx::Matrix4x4 SnapTransformTranslation(const gfx::Matrix4x4& aTransform,
michael@0 1401 gfx::Matrix* aResidualTransform);
michael@0 1402 /**
michael@0 1403 * See comment for SnapTransformTranslation.
michael@0 1404 * This function implements type 2 snapping. If aTransform is a translation
michael@0 1405 * and/or scale, transform aSnapRect by aTransform, snap to pixel boundaries,
michael@0 1406 * and return the transform that maps aSnapRect to that rect. Otherwise
michael@0 1407 * just return aTransform.
michael@0 1408 * @param aSnapRect a rectangle whose edges should be snapped to pixel
michael@0 1409 * boundaries in the destination surface.
michael@0 1410 * @param aResidualTransform a transform to apply before the result transform
michael@0 1411 * in order to get the results to completely match aTransform.
michael@0 1412 */
michael@0 1413 gfx::Matrix4x4 SnapTransform(const gfx::Matrix4x4& aTransform,
michael@0 1414 const gfxRect& aSnapRect,
michael@0 1415 gfx::Matrix* aResidualTransform);
michael@0 1416
michael@0 1417 /**
michael@0 1418 * Returns true if this layer's effective transform is not just
michael@0 1419 * a translation by integers, or if this layer or some ancestor layer
michael@0 1420 * is marked as having a transform that may change without a full layer
michael@0 1421 * transaction.
michael@0 1422 */
michael@0 1423 bool MayResample();
michael@0 1424
michael@0 1425 LayerManager* mManager;
michael@0 1426 ContainerLayer* mParent;
michael@0 1427 Layer* mNextSibling;
michael@0 1428 Layer* mPrevSibling;
michael@0 1429 void* mImplData;
michael@0 1430 nsRefPtr<Layer> mMaskLayer;
michael@0 1431 gfx::UserData mUserData;
michael@0 1432 nsIntRegion mVisibleRegion;
michael@0 1433 EventRegions mEventRegions;
michael@0 1434 gfx::Matrix4x4 mTransform;
michael@0 1435 // A mutation of |mTransform| that we've queued to be applied at the
michael@0 1436 // end of the next transaction (if nothing else overrides it in the
michael@0 1437 // meantime).
michael@0 1438 nsAutoPtr<gfx::Matrix4x4> mPendingTransform;
michael@0 1439 float mPostXScale;
michael@0 1440 float mPostYScale;
michael@0 1441 gfx::Matrix4x4 mEffectiveTransform;
michael@0 1442 AnimationArray mAnimations;
michael@0 1443 // See mPendingTransform above.
michael@0 1444 nsAutoPtr<AnimationArray> mPendingAnimations;
michael@0 1445 InfallibleTArray<AnimData> mAnimationData;
michael@0 1446 float mOpacity;
michael@0 1447 gfx::CompositionOp mMixBlendMode;
michael@0 1448 bool mForceIsolatedGroup;
michael@0 1449 nsIntRect mClipRect;
michael@0 1450 nsIntRect mTileSourceRect;
michael@0 1451 nsIntRegion mInvalidRegion;
michael@0 1452 uint32_t mContentFlags;
michael@0 1453 bool mUseClipRect;
michael@0 1454 bool mUseTileSourceRect;
michael@0 1455 bool mIsFixedPosition;
michael@0 1456 LayerPoint mAnchor;
michael@0 1457 LayerMargin mMargins;
michael@0 1458 struct StickyPositionData {
michael@0 1459 FrameMetrics::ViewID mScrollId;
michael@0 1460 LayerRect mOuter;
michael@0 1461 LayerRect mInner;
michael@0 1462 };
michael@0 1463 nsAutoPtr<StickyPositionData> mStickyPositionData;
michael@0 1464 FrameMetrics::ViewID mScrollbarTargetId;
michael@0 1465 ScrollDirection mScrollbarDirection;
michael@0 1466 DebugOnly<uint32_t> mDebugColorIndex;
michael@0 1467 // If this layer is used for OMTA, then this counter is used to ensure we
michael@0 1468 // stay in sync with the animation manager
michael@0 1469 uint64_t mAnimationGeneration;
michael@0 1470 };
michael@0 1471
michael@0 1472 /**
michael@0 1473 * A Layer which we can draw into using Thebes. It is a conceptually
michael@0 1474 * infinite surface, but each ThebesLayer has an associated "valid region"
michael@0 1475 * of contents that it is currently storing, which is finite. ThebesLayer
michael@0 1476 * implementations can store content between paints.
michael@0 1477 *
michael@0 1478 * ThebesLayers are rendered into during the drawing phase of a transaction.
michael@0 1479 *
michael@0 1480 * Currently the contents of a ThebesLayer are in the device output color
michael@0 1481 * space.
michael@0 1482 */
michael@0 1483 class ThebesLayer : public Layer {
michael@0 1484 public:
michael@0 1485 /**
michael@0 1486 * CONSTRUCTION PHASE ONLY
michael@0 1487 * Tell this layer that the content in some region has changed and
michael@0 1488 * will need to be repainted. This area is removed from the valid
michael@0 1489 * region.
michael@0 1490 */
michael@0 1491 virtual void InvalidateRegion(const nsIntRegion& aRegion) = 0;
michael@0 1492 /**
michael@0 1493 * CONSTRUCTION PHASE ONLY
michael@0 1494 * Set whether ComputeEffectiveTransforms should compute the
michael@0 1495 * "residual translation" --- the translation that should be applied *before*
michael@0 1496 * mEffectiveTransform to get the ideal transform for this ThebesLayer.
michael@0 1497 * When this is true, ComputeEffectiveTransforms will compute the residual
michael@0 1498 * and ensure that the layer is invalidated whenever the residual changes.
michael@0 1499 * When it's false, a change in the residual will not trigger invalidation
michael@0 1500 * and GetResidualTranslation will return 0,0.
michael@0 1501 * So when the residual is to be ignored, set this to false for better
michael@0 1502 * performance.
michael@0 1503 */
michael@0 1504 void SetAllowResidualTranslation(bool aAllow) { mAllowResidualTranslation = aAllow; }
michael@0 1505
michael@0 1506 /**
michael@0 1507 * Can be used anytime
michael@0 1508 */
michael@0 1509 const nsIntRegion& GetValidRegion() const { return mValidRegion; }
michael@0 1510
michael@0 1511 virtual ThebesLayer* AsThebesLayer() { return this; }
michael@0 1512
michael@0 1513 MOZ_LAYER_DECL_NAME("ThebesLayer", TYPE_THEBES)
michael@0 1514
michael@0 1515 virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
michael@0 1516 {
michael@0 1517 gfx::Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
michael@0 1518 gfx::Matrix residual;
michael@0 1519 mEffectiveTransform = SnapTransformTranslation(idealTransform,
michael@0 1520 mAllowResidualTranslation ? &residual : nullptr);
michael@0 1521 // The residual can only be a translation because SnapTransformTranslation
michael@0 1522 // only changes the transform if it's a translation
michael@0 1523 NS_ASSERTION(residual.IsTranslation(),
michael@0 1524 "Residual transform can only be a translation");
michael@0 1525 if (!gfx::ThebesPoint(residual.GetTranslation()).WithinEpsilonOf(mResidualTranslation, 1e-3f)) {
michael@0 1526 mResidualTranslation = gfx::ThebesPoint(residual.GetTranslation());
michael@0 1527 NS_ASSERTION(-0.5 <= mResidualTranslation.x && mResidualTranslation.x < 0.5 &&
michael@0 1528 -0.5 <= mResidualTranslation.y && mResidualTranslation.y < 0.5,
michael@0 1529 "Residual translation out of range");
michael@0 1530 mValidRegion.SetEmpty();
michael@0 1531 }
michael@0 1532 ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
michael@0 1533 }
michael@0 1534
michael@0 1535 bool UsedForReadback() { return mUsedForReadback; }
michael@0 1536 void SetUsedForReadback(bool aUsed) { mUsedForReadback = aUsed; }
michael@0 1537 /**
michael@0 1538 * Returns the residual translation. Apply this translation when drawing
michael@0 1539 * into the ThebesLayer so that when mEffectiveTransform is applied afterwards
michael@0 1540 * by layer compositing, the results exactly match the "ideal transform"
michael@0 1541 * (the product of the transform of this layer and its ancestors).
michael@0 1542 * Returns 0,0 unless SetAllowResidualTranslation(true) has been called.
michael@0 1543 * The residual translation components are always in the range [-0.5, 0.5).
michael@0 1544 */
michael@0 1545 gfxPoint GetResidualTranslation() const { return mResidualTranslation; }
michael@0 1546
michael@0 1547 protected:
michael@0 1548 ThebesLayer(LayerManager* aManager, void* aImplData)
michael@0 1549 : Layer(aManager, aImplData)
michael@0 1550 , mValidRegion()
michael@0 1551 , mUsedForReadback(false)
michael@0 1552 , mAllowResidualTranslation(false)
michael@0 1553 {
michael@0 1554 mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
michael@0 1555 }
michael@0 1556
michael@0 1557 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 1558
michael@0 1559 /**
michael@0 1560 * ComputeEffectiveTransforms snaps the ideal transform to get mEffectiveTransform.
michael@0 1561 * mResidualTranslation is the translation that should be applied *before*
michael@0 1562 * mEffectiveTransform to get the ideal transform.
michael@0 1563 */
michael@0 1564 gfxPoint mResidualTranslation;
michael@0 1565 nsIntRegion mValidRegion;
michael@0 1566 /**
michael@0 1567 * Set when this ThebesLayer is participating in readback, i.e. some
michael@0 1568 * ReadbackLayer (may) be getting its background from this layer.
michael@0 1569 */
michael@0 1570 bool mUsedForReadback;
michael@0 1571 /**
michael@0 1572 * True when
michael@0 1573 */
michael@0 1574 bool mAllowResidualTranslation;
michael@0 1575 };
michael@0 1576
michael@0 1577 /**
michael@0 1578 * A Layer which other layers render into. It holds references to its
michael@0 1579 * children.
michael@0 1580 */
michael@0 1581 class ContainerLayer : public Layer {
michael@0 1582 public:
michael@0 1583
michael@0 1584 ~ContainerLayer();
michael@0 1585
michael@0 1586 /**
michael@0 1587 * CONSTRUCTION PHASE ONLY
michael@0 1588 * Insert aChild into the child list of this container. aChild must
michael@0 1589 * not be currently in any child list or the root for the layer manager.
michael@0 1590 * If aAfter is non-null, it must be a child of this container and
michael@0 1591 * we insert after that layer. If it's null we insert at the start.
michael@0 1592 */
michael@0 1593 virtual bool InsertAfter(Layer* aChild, Layer* aAfter);
michael@0 1594 /**
michael@0 1595 * CONSTRUCTION PHASE ONLY
michael@0 1596 * Remove aChild from the child list of this container. aChild must
michael@0 1597 * be a child of this container.
michael@0 1598 */
michael@0 1599 virtual bool RemoveChild(Layer* aChild);
michael@0 1600 /**
michael@0 1601 * CONSTRUCTION PHASE ONLY
michael@0 1602 * Reposition aChild from the child list of this container. aChild must
michael@0 1603 * be a child of this container.
michael@0 1604 * If aAfter is non-null, it must be a child of this container and we
michael@0 1605 * reposition after that layer. If it's null, we reposition at the start.
michael@0 1606 */
michael@0 1607 virtual bool RepositionChild(Layer* aChild, Layer* aAfter);
michael@0 1608
michael@0 1609 /**
michael@0 1610 * CONSTRUCTION PHASE ONLY
michael@0 1611 * Set the (sub)document metrics used to render the Layer subtree
michael@0 1612 * rooted at this.
michael@0 1613 */
michael@0 1614 void SetFrameMetrics(const FrameMetrics& aFrameMetrics)
michael@0 1615 {
michael@0 1616 if (mFrameMetrics != aFrameMetrics) {
michael@0 1617 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FrameMetrics", this));
michael@0 1618 mFrameMetrics = aFrameMetrics;
michael@0 1619 Mutated();
michael@0 1620 }
michael@0 1621 }
michael@0 1622
michael@0 1623 // These functions allow attaching an AsyncPanZoomController to this layer,
michael@0 1624 // and can be used anytime.
michael@0 1625 // A container layer has an APZC only-if GetFrameMetrics().IsScrollable()
michael@0 1626 void SetAsyncPanZoomController(AsyncPanZoomController *controller);
michael@0 1627 AsyncPanZoomController* GetAsyncPanZoomController() const;
michael@0 1628
michael@0 1629 /**
michael@0 1630 * CONSTRUCTION PHASE ONLY
michael@0 1631 * Set the ViewID of the ContainerLayer to which overscroll should be handed
michael@0 1632 * off. A value of NULL_SCROLL_ID means that the default handoff-parent-finding
michael@0 1633 * behaviour should be used (i.e. walk up the layer tree to find the next
michael@0 1634 * scrollable ancestor layer).
michael@0 1635 */
michael@0 1636 void SetScrollHandoffParentId(FrameMetrics::ViewID aScrollParentId)
michael@0 1637 {
michael@0 1638 if (mScrollHandoffParentId != aScrollParentId) {
michael@0 1639 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollHandoffParentId", this));
michael@0 1640 mScrollHandoffParentId = aScrollParentId;
michael@0 1641 Mutated();
michael@0 1642 }
michael@0 1643 }
michael@0 1644
michael@0 1645 void SetPreScale(float aXScale, float aYScale)
michael@0 1646 {
michael@0 1647 if (mPreXScale == aXScale && mPreYScale == aYScale) {
michael@0 1648 return;
michael@0 1649 }
michael@0 1650
michael@0 1651 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) PreScale", this));
michael@0 1652 mPreXScale = aXScale;
michael@0 1653 mPreYScale = aYScale;
michael@0 1654 Mutated();
michael@0 1655 }
michael@0 1656
michael@0 1657 void SetInheritedScale(float aXScale, float aYScale)
michael@0 1658 {
michael@0 1659 if (mInheritedXScale == aXScale && mInheritedYScale == aYScale) {
michael@0 1660 return;
michael@0 1661 }
michael@0 1662
michael@0 1663 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) InheritedScale", this));
michael@0 1664 mInheritedXScale = aXScale;
michael@0 1665 mInheritedYScale = aYScale;
michael@0 1666 Mutated();
michael@0 1667 }
michael@0 1668
michael@0 1669 virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs);
michael@0 1670
michael@0 1671 void SortChildrenBy3DZOrder(nsTArray<Layer*>& aArray);
michael@0 1672
michael@0 1673 // These getters can be used anytime.
michael@0 1674
michael@0 1675 virtual ContainerLayer* AsContainerLayer() { return this; }
michael@0 1676 virtual const ContainerLayer* AsContainerLayer() const { return this; }
michael@0 1677
michael@0 1678 virtual Layer* GetFirstChild() const { return mFirstChild; }
michael@0 1679 virtual Layer* GetLastChild() const { return mLastChild; }
michael@0 1680 const FrameMetrics& GetFrameMetrics() const { return mFrameMetrics; }
michael@0 1681 FrameMetrics::ViewID GetScrollHandoffParentId() const { return mScrollHandoffParentId; }
michael@0 1682 float GetPreXScale() const { return mPreXScale; }
michael@0 1683 float GetPreYScale() const { return mPreYScale; }
michael@0 1684 float GetInheritedXScale() const { return mInheritedXScale; }
michael@0 1685 float GetInheritedYScale() const { return mInheritedYScale; }
michael@0 1686
michael@0 1687 MOZ_LAYER_DECL_NAME("ContainerLayer", TYPE_CONTAINER)
michael@0 1688
michael@0 1689 /**
michael@0 1690 * ContainerLayer backends need to override ComputeEffectiveTransforms
michael@0 1691 * since the decision about whether to use a temporary surface for the
michael@0 1692 * container is backend-specific. ComputeEffectiveTransforms must also set
michael@0 1693 * mUseIntermediateSurface.
michael@0 1694 */
michael@0 1695 virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) = 0;
michael@0 1696
michael@0 1697 /**
michael@0 1698 * Call this only after ComputeEffectiveTransforms has been invoked
michael@0 1699 * on this layer.
michael@0 1700 * Returns true if this will use an intermediate surface. This is largely
michael@0 1701 * backend-dependent, but it affects the operation of GetEffectiveOpacity().
michael@0 1702 */
michael@0 1703 bool UseIntermediateSurface() { return mUseIntermediateSurface; }
michael@0 1704
michael@0 1705 /**
michael@0 1706 * Returns the rectangle covered by the intermediate surface,
michael@0 1707 * in this layer's coordinate system
michael@0 1708 */
michael@0 1709 nsIntRect GetIntermediateSurfaceRect()
michael@0 1710 {
michael@0 1711 NS_ASSERTION(mUseIntermediateSurface, "Must have intermediate surface");
michael@0 1712 return mVisibleRegion.GetBounds();
michael@0 1713 }
michael@0 1714
michael@0 1715 /**
michael@0 1716 * Returns true if this container has more than one non-empty child
michael@0 1717 */
michael@0 1718 bool HasMultipleChildren();
michael@0 1719
michael@0 1720 /**
michael@0 1721 * Returns true if this container supports children with component alpha.
michael@0 1722 * Should only be called while painting a child of this layer.
michael@0 1723 */
michael@0 1724 bool SupportsComponentAlphaChildren() { return mSupportsComponentAlphaChildren; }
michael@0 1725
michael@0 1726 /**
michael@0 1727 * Returns true if aLayer or any layer in its parent chain has the opaque
michael@0 1728 * content flag set.
michael@0 1729 */
michael@0 1730 static bool HasOpaqueAncestorLayer(Layer* aLayer);
michael@0 1731
michael@0 1732 protected:
michael@0 1733 friend class ReadbackProcessor;
michael@0 1734
michael@0 1735 void DidInsertChild(Layer* aLayer);
michael@0 1736 void DidRemoveChild(Layer* aLayer);
michael@0 1737
michael@0 1738 ContainerLayer(LayerManager* aManager, void* aImplData);
michael@0 1739
michael@0 1740 /**
michael@0 1741 * A default implementation of ComputeEffectiveTransforms for use by OpenGL
michael@0 1742 * and D3D.
michael@0 1743 */
michael@0 1744 void DefaultComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface);
michael@0 1745
michael@0 1746 /**
michael@0 1747 * Loops over the children calling ComputeEffectiveTransforms on them.
michael@0 1748 */
michael@0 1749 void ComputeEffectiveTransformsForChildren(const gfx::Matrix4x4& aTransformToSurface);
michael@0 1750
michael@0 1751 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 1752
michael@0 1753 Layer* mFirstChild;
michael@0 1754 Layer* mLastChild;
michael@0 1755 FrameMetrics mFrameMetrics;
michael@0 1756 nsRefPtr<AsyncPanZoomController> mAPZC;
michael@0 1757 FrameMetrics::ViewID mScrollHandoffParentId;
michael@0 1758 float mPreXScale;
michael@0 1759 float mPreYScale;
michael@0 1760 // The resolution scale inherited from the parent layer. This will already
michael@0 1761 // be part of mTransform.
michael@0 1762 float mInheritedXScale;
michael@0 1763 float mInheritedYScale;
michael@0 1764 bool mUseIntermediateSurface;
michael@0 1765 bool mSupportsComponentAlphaChildren;
michael@0 1766 bool mMayHaveReadbackChild;
michael@0 1767 };
michael@0 1768
michael@0 1769 /**
michael@0 1770 * A Layer which just renders a solid color in its visible region. It actually
michael@0 1771 * can fill any area that contains the visible region, so if you need to
michael@0 1772 * restrict the area filled, set a clip region on this layer.
michael@0 1773 */
michael@0 1774 class ColorLayer : public Layer {
michael@0 1775 public:
michael@0 1776 virtual ColorLayer* AsColorLayer() { return this; }
michael@0 1777
michael@0 1778 /**
michael@0 1779 * CONSTRUCTION PHASE ONLY
michael@0 1780 * Set the color of the layer.
michael@0 1781 */
michael@0 1782 virtual void SetColor(const gfxRGBA& aColor)
michael@0 1783 {
michael@0 1784 if (mColor != aColor) {
michael@0 1785 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) Color", this));
michael@0 1786 mColor = aColor;
michael@0 1787 Mutated();
michael@0 1788 }
michael@0 1789 }
michael@0 1790
michael@0 1791 void SetBounds(const nsIntRect& aBounds)
michael@0 1792 {
michael@0 1793 if (!mBounds.IsEqualEdges(aBounds)) {
michael@0 1794 mBounds = aBounds;
michael@0 1795 Mutated();
michael@0 1796 }
michael@0 1797 }
michael@0 1798
michael@0 1799 const nsIntRect& GetBounds()
michael@0 1800 {
michael@0 1801 return mBounds;
michael@0 1802 }
michael@0 1803
michael@0 1804 // This getter can be used anytime.
michael@0 1805 virtual const gfxRGBA& GetColor() { return mColor; }
michael@0 1806
michael@0 1807 MOZ_LAYER_DECL_NAME("ColorLayer", TYPE_COLOR)
michael@0 1808
michael@0 1809 virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
michael@0 1810 {
michael@0 1811 gfx::Matrix4x4 idealTransform = GetLocalTransform() * aTransformToSurface;
michael@0 1812 mEffectiveTransform = SnapTransformTranslation(idealTransform, nullptr);
michael@0 1813 ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
michael@0 1814 }
michael@0 1815
michael@0 1816 protected:
michael@0 1817 ColorLayer(LayerManager* aManager, void* aImplData)
michael@0 1818 : Layer(aManager, aImplData),
michael@0 1819 mColor(0.0, 0.0, 0.0, 0.0)
michael@0 1820 {}
michael@0 1821
michael@0 1822 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 1823
michael@0 1824 nsIntRect mBounds;
michael@0 1825 gfxRGBA mColor;
michael@0 1826 };
michael@0 1827
michael@0 1828 /**
michael@0 1829 * A Layer for HTML Canvas elements. It's backed by either a
michael@0 1830 * gfxASurface or a GLContext (for WebGL layers), and has some control
michael@0 1831 * for intelligent updating from the source if necessary (for example,
michael@0 1832 * if hardware compositing is not available, for reading from the GL
michael@0 1833 * buffer into an image surface that we can layer composite.)
michael@0 1834 *
michael@0 1835 * After Initialize is called, the underlying canvas Surface/GLContext
michael@0 1836 * must not be modified during a layer transaction.
michael@0 1837 */
michael@0 1838 class CanvasLayer : public Layer {
michael@0 1839 public:
michael@0 1840 struct Data {
michael@0 1841 Data()
michael@0 1842 : mDrawTarget(nullptr)
michael@0 1843 , mGLContext(nullptr)
michael@0 1844 , mStream(nullptr)
michael@0 1845 , mTexID(0)
michael@0 1846 , mSize(0,0)
michael@0 1847 , mIsGLAlphaPremult(false)
michael@0 1848 { }
michael@0 1849
michael@0 1850 // One of these two must be specified for Canvas2D, but never both
michael@0 1851 mozilla::gfx::DrawTarget *mDrawTarget; // a DrawTarget for the canvas contents
michael@0 1852 mozilla::gl::GLContext* mGLContext; // or this, for GL.
michael@0 1853
michael@0 1854 // Canvas/SkiaGL uses this
michael@0 1855 mozilla::gfx::SurfaceStream* mStream;
michael@0 1856
michael@0 1857 // ID of the texture backing the canvas layer (defaults to 0)
michael@0 1858 uint32_t mTexID;
michael@0 1859
michael@0 1860 // The size of the canvas content
michael@0 1861 nsIntSize mSize;
michael@0 1862
michael@0 1863 // Whether mGLContext contains data that is alpha-premultiplied.
michael@0 1864 bool mIsGLAlphaPremult;
michael@0 1865 };
michael@0 1866
michael@0 1867 /**
michael@0 1868 * CONSTRUCTION PHASE ONLY
michael@0 1869 * Initialize this CanvasLayer with the given data. The data must
michael@0 1870 * have either mSurface or mGLContext initialized (but not both), as
michael@0 1871 * well as mSize.
michael@0 1872 *
michael@0 1873 * This must only be called once.
michael@0 1874 */
michael@0 1875 virtual void Initialize(const Data& aData) = 0;
michael@0 1876
michael@0 1877 /**
michael@0 1878 * Check the data is owned by this layer is still valid for rendering
michael@0 1879 */
michael@0 1880 virtual bool IsDataValid(const Data& aData) { return true; }
michael@0 1881
michael@0 1882 /**
michael@0 1883 * Notify this CanvasLayer that the canvas surface contents have
michael@0 1884 * changed (or will change) before the next transaction.
michael@0 1885 */
michael@0 1886 void Updated() { mDirty = true; SetInvalidRectToVisibleRegion(); }
michael@0 1887
michael@0 1888 /**
michael@0 1889 * Notify this CanvasLayer that the canvas surface contents have
michael@0 1890 * been painted since the last change.
michael@0 1891 */
michael@0 1892 void Painted() { mDirty = false; }
michael@0 1893
michael@0 1894 /**
michael@0 1895 * Returns true if the canvas surface contents have changed since the
michael@0 1896 * last paint.
michael@0 1897 */
michael@0 1898 bool IsDirty()
michael@0 1899 {
michael@0 1900 // We can only tell if we are dirty if we're part of the
michael@0 1901 // widget's retained layer tree.
michael@0 1902 if (!mManager || !mManager->IsWidgetLayerManager()) {
michael@0 1903 return true;
michael@0 1904 }
michael@0 1905 return mDirty;
michael@0 1906 }
michael@0 1907
michael@0 1908 /**
michael@0 1909 * Register a callback to be called at the start of each transaction.
michael@0 1910 */
michael@0 1911 typedef void PreTransactionCallback(void* closureData);
michael@0 1912 void SetPreTransactionCallback(PreTransactionCallback* callback, void* closureData)
michael@0 1913 {
michael@0 1914 mPreTransCallback = callback;
michael@0 1915 mPreTransCallbackData = closureData;
michael@0 1916 }
michael@0 1917
michael@0 1918 protected:
michael@0 1919 void FirePreTransactionCallback()
michael@0 1920 {
michael@0 1921 if (mPreTransCallback) {
michael@0 1922 mPreTransCallback(mPreTransCallbackData);
michael@0 1923 }
michael@0 1924 }
michael@0 1925
michael@0 1926 public:
michael@0 1927 /**
michael@0 1928 * Register a callback to be called at the end of each transaction.
michael@0 1929 */
michael@0 1930 typedef void (* DidTransactionCallback)(void* aClosureData);
michael@0 1931 void SetDidTransactionCallback(DidTransactionCallback aCallback, void* aClosureData)
michael@0 1932 {
michael@0 1933 mPostTransCallback = aCallback;
michael@0 1934 mPostTransCallbackData = aClosureData;
michael@0 1935 }
michael@0 1936
michael@0 1937 /**
michael@0 1938 * CONSTRUCTION PHASE ONLY
michael@0 1939 * Set the filter used to resample this image (if necessary).
michael@0 1940 */
michael@0 1941 void SetFilter(GraphicsFilter aFilter)
michael@0 1942 {
michael@0 1943 if (mFilter != aFilter) {
michael@0 1944 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) Filter", this));
michael@0 1945 mFilter = aFilter;
michael@0 1946 Mutated();
michael@0 1947 }
michael@0 1948 }
michael@0 1949 GraphicsFilter GetFilter() const { return mFilter; }
michael@0 1950
michael@0 1951 MOZ_LAYER_DECL_NAME("CanvasLayer", TYPE_CANVAS)
michael@0 1952
michael@0 1953 virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface)
michael@0 1954 {
michael@0 1955 // Snap our local transform first, and snap the inherited transform as well.
michael@0 1956 // This makes our snapping equivalent to what would happen if our content
michael@0 1957 // was drawn into a ThebesLayer (gfxContext would snap using the local
michael@0 1958 // transform, then we'd snap again when compositing the ThebesLayer).
michael@0 1959 mEffectiveTransform =
michael@0 1960 SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
michael@0 1961 nullptr)*
michael@0 1962 SnapTransformTranslation(aTransformToSurface, nullptr);
michael@0 1963 ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
michael@0 1964 }
michael@0 1965
michael@0 1966 protected:
michael@0 1967 CanvasLayer(LayerManager* aManager, void* aImplData)
michael@0 1968 : Layer(aManager, aImplData)
michael@0 1969 , mPreTransCallback(nullptr)
michael@0 1970 , mPreTransCallbackData(nullptr)
michael@0 1971 , mPostTransCallback(nullptr)
michael@0 1972 , mPostTransCallbackData(nullptr)
michael@0 1973 , mFilter(GraphicsFilter::FILTER_GOOD)
michael@0 1974 , mDirty(false)
michael@0 1975 {}
michael@0 1976
michael@0 1977 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 1978
michael@0 1979 void FireDidTransactionCallback()
michael@0 1980 {
michael@0 1981 if (mPostTransCallback) {
michael@0 1982 mPostTransCallback(mPostTransCallbackData);
michael@0 1983 }
michael@0 1984 }
michael@0 1985
michael@0 1986 /**
michael@0 1987 * 0, 0, canvaswidth, canvasheight
michael@0 1988 */
michael@0 1989 nsIntRect mBounds;
michael@0 1990 PreTransactionCallback* mPreTransCallback;
michael@0 1991 void* mPreTransCallbackData;
michael@0 1992 DidTransactionCallback mPostTransCallback;
michael@0 1993 void* mPostTransCallbackData;
michael@0 1994 GraphicsFilter mFilter;
michael@0 1995
michael@0 1996 private:
michael@0 1997 /**
michael@0 1998 * Set to true in Updated(), cleared during a transaction.
michael@0 1999 */
michael@0 2000 bool mDirty;
michael@0 2001 };
michael@0 2002
michael@0 2003 /**
michael@0 2004 * ContainerLayer that refers to a "foreign" layer tree, through an
michael@0 2005 * ID. Usage of RefLayer looks like
michael@0 2006 *
michael@0 2007 * Construction phase:
michael@0 2008 * allocate ID for layer subtree
michael@0 2009 * create RefLayer, SetReferentId(ID)
michael@0 2010 *
michael@0 2011 * Composition:
michael@0 2012 * look up subtree for GetReferentId()
michael@0 2013 * ConnectReferentLayer(subtree)
michael@0 2014 * compose
michael@0 2015 * ClearReferentLayer()
michael@0 2016 *
michael@0 2017 * Clients will usually want to Connect/Clear() on each transaction to
michael@0 2018 * avoid difficulties managing memory across multiple layer subtrees.
michael@0 2019 */
michael@0 2020 class RefLayer : public ContainerLayer {
michael@0 2021 friend class LayerManager;
michael@0 2022
michael@0 2023 private:
michael@0 2024 virtual bool InsertAfter(Layer* aChild, Layer* aAfter) MOZ_OVERRIDE
michael@0 2025 { MOZ_CRASH(); return false; }
michael@0 2026
michael@0 2027 virtual bool RemoveChild(Layer* aChild)
michael@0 2028 { MOZ_CRASH(); return false; }
michael@0 2029
michael@0 2030 virtual bool RepositionChild(Layer* aChild, Layer* aAfter)
michael@0 2031 { MOZ_CRASH(); return false; }
michael@0 2032
michael@0 2033 using ContainerLayer::SetFrameMetrics;
michael@0 2034
michael@0 2035 public:
michael@0 2036 /**
michael@0 2037 * CONSTRUCTION PHASE ONLY
michael@0 2038 * Set the ID of the layer's referent.
michael@0 2039 */
michael@0 2040 void SetReferentId(uint64_t aId)
michael@0 2041 {
michael@0 2042 MOZ_ASSERT(aId != 0);
michael@0 2043 if (mId != aId) {
michael@0 2044 MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ReferentId", this));
michael@0 2045 mId = aId;
michael@0 2046 Mutated();
michael@0 2047 }
michael@0 2048 }
michael@0 2049 /**
michael@0 2050 * CONSTRUCTION PHASE ONLY
michael@0 2051 * Connect this ref layer to its referent, temporarily.
michael@0 2052 * ClearReferentLayer() must be called after composition.
michael@0 2053 */
michael@0 2054 void ConnectReferentLayer(Layer* aLayer)
michael@0 2055 {
michael@0 2056 MOZ_ASSERT(!mFirstChild && !mLastChild);
michael@0 2057 MOZ_ASSERT(!aLayer->GetParent());
michael@0 2058 MOZ_ASSERT(aLayer->Manager() == Manager());
michael@0 2059
michael@0 2060 mFirstChild = mLastChild = aLayer;
michael@0 2061 aLayer->SetParent(this);
michael@0 2062 }
michael@0 2063
michael@0 2064 /**
michael@0 2065 * DRAWING PHASE ONLY
michael@0 2066 * |aLayer| is the same as the argument to ConnectReferentLayer().
michael@0 2067 */
michael@0 2068 void DetachReferentLayer(Layer* aLayer)
michael@0 2069 {
michael@0 2070 MOZ_ASSERT(aLayer == mFirstChild && mFirstChild == mLastChild);
michael@0 2071 MOZ_ASSERT(aLayer->GetParent() == this);
michael@0 2072
michael@0 2073 mFirstChild = mLastChild = nullptr;
michael@0 2074 aLayer->SetParent(nullptr);
michael@0 2075 }
michael@0 2076
michael@0 2077 // These getters can be used anytime.
michael@0 2078 virtual RefLayer* AsRefLayer() { return this; }
michael@0 2079
michael@0 2080 virtual int64_t GetReferentId() { return mId; }
michael@0 2081
michael@0 2082 /**
michael@0 2083 * DRAWING PHASE ONLY
michael@0 2084 */
michael@0 2085 virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs);
michael@0 2086
michael@0 2087 MOZ_LAYER_DECL_NAME("RefLayer", TYPE_REF)
michael@0 2088
michael@0 2089 protected:
michael@0 2090 RefLayer(LayerManager* aManager, void* aImplData)
michael@0 2091 : ContainerLayer(aManager, aImplData) , mId(0)
michael@0 2092 {}
michael@0 2093
michael@0 2094 virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
michael@0 2095
michael@0 2096 Layer* mTempReferent;
michael@0 2097 // 0 is a special value that means "no ID".
michael@0 2098 uint64_t mId;
michael@0 2099 };
michael@0 2100
michael@0 2101 void SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget);
michael@0 2102 void SetAntialiasingFlags(Layer* aLayer, gfx::DrawTarget* aTarget);
michael@0 2103
michael@0 2104 #ifdef MOZ_DUMP_PAINTING
michael@0 2105 void WriteSnapshotToDumpFile(Layer* aLayer, gfx::DataSourceSurface* aSurf);
michael@0 2106 void WriteSnapshotToDumpFile(LayerManager* aManager, gfx::DataSourceSurface* aSurf);
michael@0 2107 void WriteSnapshotToDumpFile(Compositor* aCompositor, gfx::DrawTarget* aTarget);
michael@0 2108 #endif
michael@0 2109
michael@0 2110 }
michael@0 2111 }
michael@0 2112
michael@0 2113 #endif /* GFX_LAYERS_H */

mercurial