Wed, 31 Dec 2014 06:09:35 +0100
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 */ |