Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: C++; tab-width: 20; 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 FRAMELAYERBUILDER_H_ |
michael@0 | 7 | #define FRAMELAYERBUILDER_H_ |
michael@0 | 8 | |
michael@0 | 9 | #include "nsTHashtable.h" |
michael@0 | 10 | #include "nsHashKeys.h" |
michael@0 | 11 | #include "nsTArray.h" |
michael@0 | 12 | #include "nsRegion.h" |
michael@0 | 13 | #include "nsIFrame.h" |
michael@0 | 14 | #include "ImageLayers.h" |
michael@0 | 15 | #include "DisplayItemClip.h" |
michael@0 | 16 | #include "mozilla/layers/LayersTypes.h" |
michael@0 | 17 | |
michael@0 | 18 | class nsDisplayListBuilder; |
michael@0 | 19 | class nsDisplayList; |
michael@0 | 20 | class nsDisplayItem; |
michael@0 | 21 | class gfxContext; |
michael@0 | 22 | class nsDisplayItemGeometry; |
michael@0 | 23 | |
michael@0 | 24 | namespace mozilla { |
michael@0 | 25 | namespace layers { |
michael@0 | 26 | class ContainerLayer; |
michael@0 | 27 | class LayerManager; |
michael@0 | 28 | class BasicLayerManager; |
michael@0 | 29 | class ThebesLayer; |
michael@0 | 30 | } |
michael@0 | 31 | |
michael@0 | 32 | class FrameLayerBuilder; |
michael@0 | 33 | class LayerManagerData; |
michael@0 | 34 | class ThebesLayerData; |
michael@0 | 35 | |
michael@0 | 36 | enum LayerState { |
michael@0 | 37 | LAYER_NONE, |
michael@0 | 38 | LAYER_INACTIVE, |
michael@0 | 39 | LAYER_ACTIVE, |
michael@0 | 40 | // Force an active layer even if it causes incorrect rendering, e.g. |
michael@0 | 41 | // when the layer has rounded rect clips. |
michael@0 | 42 | LAYER_ACTIVE_FORCE, |
michael@0 | 43 | // Special layer that is metadata only. |
michael@0 | 44 | LAYER_ACTIVE_EMPTY, |
michael@0 | 45 | // Inactive style layer for rendering SVG effects. |
michael@0 | 46 | LAYER_SVG_EFFECTS |
michael@0 | 47 | }; |
michael@0 | 48 | |
michael@0 | 49 | class RefCountedRegion { |
michael@0 | 50 | public: |
michael@0 | 51 | NS_INLINE_DECL_REFCOUNTING(RefCountedRegion) |
michael@0 | 52 | |
michael@0 | 53 | RefCountedRegion() : mIsInfinite(false) {} |
michael@0 | 54 | nsRegion mRegion; |
michael@0 | 55 | bool mIsInfinite; |
michael@0 | 56 | }; |
michael@0 | 57 | |
michael@0 | 58 | struct ContainerLayerParameters { |
michael@0 | 59 | ContainerLayerParameters() : |
michael@0 | 60 | mXScale(1), mYScale(1), mAncestorClipRect(nullptr), |
michael@0 | 61 | mInTransformedSubtree(false), mInActiveTransformedSubtree(false), |
michael@0 | 62 | mDisableSubpixelAntialiasingInDescendants(false) |
michael@0 | 63 | {} |
michael@0 | 64 | ContainerLayerParameters(float aXScale, float aYScale) : |
michael@0 | 65 | mXScale(aXScale), mYScale(aYScale), mAncestorClipRect(nullptr), |
michael@0 | 66 | mInTransformedSubtree(false), mInActiveTransformedSubtree(false), |
michael@0 | 67 | mDisableSubpixelAntialiasingInDescendants(false) |
michael@0 | 68 | {} |
michael@0 | 69 | ContainerLayerParameters(float aXScale, float aYScale, |
michael@0 | 70 | const nsIntPoint& aOffset, |
michael@0 | 71 | const ContainerLayerParameters& aParent) : |
michael@0 | 72 | mXScale(aXScale), mYScale(aYScale), mAncestorClipRect(nullptr), |
michael@0 | 73 | mOffset(aOffset), |
michael@0 | 74 | mInTransformedSubtree(aParent.mInTransformedSubtree), |
michael@0 | 75 | mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree), |
michael@0 | 76 | mDisableSubpixelAntialiasingInDescendants(aParent.mDisableSubpixelAntialiasingInDescendants) |
michael@0 | 77 | {} |
michael@0 | 78 | float mXScale, mYScale; |
michael@0 | 79 | /** |
michael@0 | 80 | * An ancestor clip rect that can be applied to restrict the visibility |
michael@0 | 81 | * of this container. Null if none available. |
michael@0 | 82 | */ |
michael@0 | 83 | const nsIntRect* mAncestorClipRect; |
michael@0 | 84 | /** |
michael@0 | 85 | * An offset to append to the transform set on all child layers created. |
michael@0 | 86 | */ |
michael@0 | 87 | nsIntPoint mOffset; |
michael@0 | 88 | |
michael@0 | 89 | bool mInTransformedSubtree; |
michael@0 | 90 | bool mInActiveTransformedSubtree; |
michael@0 | 91 | bool mDisableSubpixelAntialiasingInDescendants; |
michael@0 | 92 | /** |
michael@0 | 93 | * When this is false, ThebesLayer coordinates are drawn to with an integer |
michael@0 | 94 | * translation and the scale in mXScale/mYScale. |
michael@0 | 95 | */ |
michael@0 | 96 | bool AllowResidualTranslation() |
michael@0 | 97 | { |
michael@0 | 98 | // If we're in a transformed subtree, but no ancestor transform is actively |
michael@0 | 99 | // changing, we'll use the residual translation when drawing into the |
michael@0 | 100 | // ThebesLayer to ensure that snapping exactly matches the ideal transform. |
michael@0 | 101 | return mInTransformedSubtree && !mInActiveTransformedSubtree; |
michael@0 | 102 | } |
michael@0 | 103 | }; |
michael@0 | 104 | |
michael@0 | 105 | /** |
michael@0 | 106 | * The FrameLayerBuilder is responsible for converting display lists |
michael@0 | 107 | * into layer trees. Every LayerManager needs a unique FrameLayerBuilder |
michael@0 | 108 | * to build layers. |
michael@0 | 109 | * |
michael@0 | 110 | * The most important API in this class is BuildContainerLayerFor. This |
michael@0 | 111 | * method takes a display list as input and constructs a ContainerLayer |
michael@0 | 112 | * with child layers that render the contents of the display list. It |
michael@0 | 113 | * records the relationship between frames and layers. |
michael@0 | 114 | * |
michael@0 | 115 | * That data enables us to retain layer trees. When constructing a |
michael@0 | 116 | * ContainerLayer, we first check to see if there's an existing |
michael@0 | 117 | * ContainerLayer for the same frame that can be recycled. If we recycle |
michael@0 | 118 | * it, we also try to reuse its existing ThebesLayer children to render |
michael@0 | 119 | * the display items without layers of their own. The idea is that by |
michael@0 | 120 | * recycling layers deterministically, we can ensure that when nothing |
michael@0 | 121 | * changes in a display list, we will reuse the existing layers without |
michael@0 | 122 | * changes. |
michael@0 | 123 | * |
michael@0 | 124 | * We expose a GetLeafLayerFor method that can be called by display items |
michael@0 | 125 | * that make their own layers (e.g. canvas and video); this method |
michael@0 | 126 | * locates the last layer used to render the display item, if any, and |
michael@0 | 127 | * return it as a candidate for recycling. |
michael@0 | 128 | * |
michael@0 | 129 | * FrameLayerBuilder sets up ThebesLayers so that 0,0 in the Thebes layer |
michael@0 | 130 | * corresponds to the (pixel-snapped) top-left of the aAnimatedGeometryRoot. |
michael@0 | 131 | * It sets up ContainerLayers so that 0,0 in the container layer |
michael@0 | 132 | * corresponds to the snapped top-left of the display item reference frame. |
michael@0 | 133 | * |
michael@0 | 134 | * When we construct a container layer, we know the transform that will be |
michael@0 | 135 | * applied to the layer. If the transform scales the content, we can get |
michael@0 | 136 | * better results when intermediate buffers are used by pushing some scale |
michael@0 | 137 | * from the container's transform down to the children. For ThebesLayer |
michael@0 | 138 | * children, the scaling can be achieved by changing the size of the layer |
michael@0 | 139 | * and drawing into it with increased or decreased resolution. By convention, |
michael@0 | 140 | * integer types (nsIntPoint/nsIntSize/nsIntRect/nsIntRegion) are all in layer |
michael@0 | 141 | * coordinates, post-scaling, whereas appunit types are all pre-scaling. |
michael@0 | 142 | */ |
michael@0 | 143 | class FrameLayerBuilder : public layers::LayerUserData { |
michael@0 | 144 | public: |
michael@0 | 145 | typedef layers::ContainerLayer ContainerLayer; |
michael@0 | 146 | typedef layers::Layer Layer; |
michael@0 | 147 | typedef layers::ThebesLayer ThebesLayer; |
michael@0 | 148 | typedef layers::ImageLayer ImageLayer; |
michael@0 | 149 | typedef layers::LayerManager LayerManager; |
michael@0 | 150 | typedef layers::BasicLayerManager BasicLayerManager; |
michael@0 | 151 | typedef layers::EventRegions EventRegions; |
michael@0 | 152 | |
michael@0 | 153 | FrameLayerBuilder() : |
michael@0 | 154 | mRetainingManager(nullptr), |
michael@0 | 155 | mDetectedDOMModification(false), |
michael@0 | 156 | mInvalidateAllLayers(false), |
michael@0 | 157 | mInLayerTreeCompressionMode(false), |
michael@0 | 158 | mContainerLayerGeneration(0), |
michael@0 | 159 | mMaxContainerLayerGeneration(0) |
michael@0 | 160 | { |
michael@0 | 161 | MOZ_COUNT_CTOR(FrameLayerBuilder); |
michael@0 | 162 | } |
michael@0 | 163 | ~FrameLayerBuilder() |
michael@0 | 164 | { |
michael@0 | 165 | MOZ_COUNT_DTOR(FrameLayerBuilder); |
michael@0 | 166 | } |
michael@0 | 167 | |
michael@0 | 168 | static void Shutdown(); |
michael@0 | 169 | |
michael@0 | 170 | void Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager, |
michael@0 | 171 | ThebesLayerData* aLayerData = nullptr); |
michael@0 | 172 | |
michael@0 | 173 | /** |
michael@0 | 174 | * Call this to notify that we have just started a transaction on the |
michael@0 | 175 | * retained layer manager aManager. |
michael@0 | 176 | */ |
michael@0 | 177 | void DidBeginRetainedLayerTransaction(LayerManager* aManager); |
michael@0 | 178 | |
michael@0 | 179 | /** |
michael@0 | 180 | * Call this just before we end a transaction. |
michael@0 | 181 | */ |
michael@0 | 182 | void WillEndTransaction(); |
michael@0 | 183 | |
michael@0 | 184 | /** |
michael@0 | 185 | * Call this after we end a transaction. |
michael@0 | 186 | */ |
michael@0 | 187 | void DidEndTransaction(); |
michael@0 | 188 | |
michael@0 | 189 | enum { |
michael@0 | 190 | CONTAINER_NOT_CLIPPED_BY_ANCESTORS = 0x01 |
michael@0 | 191 | }; |
michael@0 | 192 | /** |
michael@0 | 193 | * Build a container layer for a display item that contains a child |
michael@0 | 194 | * list, either reusing an existing one or creating a new one. It |
michael@0 | 195 | * sets the container layer children to layers which together render |
michael@0 | 196 | * the contents of the display list. It reuses existing layers from |
michael@0 | 197 | * the retained layer manager if possible. |
michael@0 | 198 | * aContainer may be null, in which case we construct a root layer. |
michael@0 | 199 | * This gets called by display list code. It calls BuildLayer on the |
michael@0 | 200 | * items in the display list, making items with their own layers |
michael@0 | 201 | * children of the new container, and assigning all other items to |
michael@0 | 202 | * ThebesLayer children created and managed by the FrameLayerBuilder. |
michael@0 | 203 | * Returns a layer with clip rect cleared; it is the |
michael@0 | 204 | * caller's responsibility to add any clip rect. The visible region |
michael@0 | 205 | * is set based on what's in the layer. |
michael@0 | 206 | * The container layer is transformed by aTransform (if non-null), and |
michael@0 | 207 | * the result is transformed by the scale factors in aContainerParameters. |
michael@0 | 208 | */ |
michael@0 | 209 | already_AddRefed<ContainerLayer> |
michael@0 | 210 | BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, |
michael@0 | 211 | LayerManager* aManager, |
michael@0 | 212 | nsIFrame* aContainerFrame, |
michael@0 | 213 | nsDisplayItem* aContainerItem, |
michael@0 | 214 | const nsDisplayList& aChildren, |
michael@0 | 215 | const ContainerLayerParameters& aContainerParameters, |
michael@0 | 216 | const gfx3DMatrix* aTransform, |
michael@0 | 217 | uint32_t aFlags = 0); |
michael@0 | 218 | |
michael@0 | 219 | /** |
michael@0 | 220 | * Get a retained layer for a display item that needs to create its own |
michael@0 | 221 | * layer for rendering (i.e. under nsDisplayItem::BuildLayer). Returns |
michael@0 | 222 | * null if no retained layer is available, which usually means that this |
michael@0 | 223 | * display item didn't have a layer before so the caller will |
michael@0 | 224 | * need to create one. |
michael@0 | 225 | * Returns a layer with clip rect cleared; it is the |
michael@0 | 226 | * caller's responsibility to add any clip rect and set the visible |
michael@0 | 227 | * region. |
michael@0 | 228 | */ |
michael@0 | 229 | Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder, |
michael@0 | 230 | nsDisplayItem* aItem); |
michael@0 | 231 | |
michael@0 | 232 | /** |
michael@0 | 233 | * Call this to force all retained layers to be discarded and recreated at |
michael@0 | 234 | * the next paint. |
michael@0 | 235 | */ |
michael@0 | 236 | static void InvalidateAllLayers(LayerManager* aManager); |
michael@0 | 237 | static void InvalidateAllLayersForFrame(nsIFrame *aFrame); |
michael@0 | 238 | |
michael@0 | 239 | /** |
michael@0 | 240 | * Call this to determine if a frame has a dedicated (non-Thebes) layer |
michael@0 | 241 | * for the given display item key. If there isn't one, we return null, |
michael@0 | 242 | * otherwise we return the layer. |
michael@0 | 243 | */ |
michael@0 | 244 | static Layer* GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey); |
michael@0 | 245 | |
michael@0 | 246 | /** |
michael@0 | 247 | * This callback must be provided to EndTransaction. The callback data |
michael@0 | 248 | * must be the nsDisplayListBuilder containing this FrameLayerBuilder. |
michael@0 | 249 | * This function can be called multiple times in a row to draw |
michael@0 | 250 | * different regions. |
michael@0 | 251 | */ |
michael@0 | 252 | static void DrawThebesLayer(ThebesLayer* aLayer, |
michael@0 | 253 | gfxContext* aContext, |
michael@0 | 254 | const nsIntRegion& aRegionToDraw, |
michael@0 | 255 | mozilla::layers::DrawRegionClip aClip, |
michael@0 | 256 | const nsIntRegion& aRegionToInvalidate, |
michael@0 | 257 | void* aCallbackData); |
michael@0 | 258 | |
michael@0 | 259 | #ifdef MOZ_DUMP_PAINTING |
michael@0 | 260 | /** |
michael@0 | 261 | * Dumps this FrameLayerBuilder's retained layer manager's retained |
michael@0 | 262 | * layer tree. Defaults to dumping to stdout in non-HTML format. |
michael@0 | 263 | */ |
michael@0 | 264 | static void DumpRetainedLayerTree(LayerManager* aManager, FILE* aFile = stdout, bool aDumpHtml = false); |
michael@0 | 265 | #endif |
michael@0 | 266 | |
michael@0 | 267 | /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/ |
michael@0 | 268 | /* These are only in the public section because they need |
michael@0 | 269 | * to be called by file-scope helper functions in FrameLayerBuilder.cpp. |
michael@0 | 270 | */ |
michael@0 | 271 | |
michael@0 | 272 | /** |
michael@0 | 273 | * Record aItem as a display item that is rendered by aLayer. |
michael@0 | 274 | * |
michael@0 | 275 | * @param aLayer Layer that the display item will be rendered into |
michael@0 | 276 | * @param aItem Display item to be drawn. |
michael@0 | 277 | * @param aLayerState What LayerState the item is using. |
michael@0 | 278 | * @param aTopLeft offset from active scrolled root to reference frame |
michael@0 | 279 | * @param aManager If the layer is in the LAYER_INACTIVE state, |
michael@0 | 280 | * then this is the temporary layer manager to draw with. |
michael@0 | 281 | */ |
michael@0 | 282 | void AddLayerDisplayItem(Layer* aLayer, |
michael@0 | 283 | nsDisplayItem* aItem, |
michael@0 | 284 | const DisplayItemClip& aClip, |
michael@0 | 285 | LayerState aLayerState, |
michael@0 | 286 | const nsPoint& aTopLeft, |
michael@0 | 287 | BasicLayerManager* aManager, |
michael@0 | 288 | nsAutoPtr<nsDisplayItemGeometry> aGeometry); |
michael@0 | 289 | |
michael@0 | 290 | /** |
michael@0 | 291 | * Record aItem as a display item that is rendered by the ThebesLayer |
michael@0 | 292 | * aLayer, with aClipRect, where aContainerLayerFrame is the frame |
michael@0 | 293 | * for the container layer this ThebesItem belongs to. |
michael@0 | 294 | * aItem must have an underlying frame. |
michael@0 | 295 | * @param aTopLeft offset from active scrolled root to reference frame |
michael@0 | 296 | */ |
michael@0 | 297 | void AddThebesDisplayItem(ThebesLayerData* aLayer, |
michael@0 | 298 | nsDisplayItem* aItem, |
michael@0 | 299 | const DisplayItemClip& aClip, |
michael@0 | 300 | nsIFrame* aContainerLayerFrame, |
michael@0 | 301 | LayerState aLayerState, |
michael@0 | 302 | const nsPoint& aTopLeft, |
michael@0 | 303 | nsAutoPtr<nsDisplayItemGeometry> aGeometry); |
michael@0 | 304 | |
michael@0 | 305 | /** |
michael@0 | 306 | * Gets the frame property descriptor for the given manager, or for the current |
michael@0 | 307 | * widget layer manager if nullptr is passed. |
michael@0 | 308 | */ |
michael@0 | 309 | static const FramePropertyDescriptor* GetDescriptorForManager(LayerManager* aManager); |
michael@0 | 310 | |
michael@0 | 311 | /** |
michael@0 | 312 | * Calls GetOldLayerForFrame on the underlying frame of the display item, |
michael@0 | 313 | * and each subsequent merged frame if no layer is found for the underlying |
michael@0 | 314 | * frame. |
michael@0 | 315 | */ |
michael@0 | 316 | Layer* GetOldLayerFor(nsDisplayItem* aItem, |
michael@0 | 317 | nsDisplayItemGeometry** aOldGeometry = nullptr, |
michael@0 | 318 | DisplayItemClip** aOldClip = nullptr, |
michael@0 | 319 | nsTArray<nsIFrame*>* aChangedFrames = nullptr, |
michael@0 | 320 | bool *aIsInvalid = nullptr); |
michael@0 | 321 | |
michael@0 | 322 | static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey); |
michael@0 | 323 | |
michael@0 | 324 | /** |
michael@0 | 325 | * Destroy any stored LayerManagerDataProperty and the associated data for |
michael@0 | 326 | * aFrame. |
michael@0 | 327 | */ |
michael@0 | 328 | static void DestroyDisplayItemDataFor(nsIFrame* aFrame); |
michael@0 | 329 | |
michael@0 | 330 | LayerManager* GetRetainingLayerManager() { return mRetainingManager; } |
michael@0 | 331 | |
michael@0 | 332 | /** |
michael@0 | 333 | * Returns true if the given display item was rendered during the previous |
michael@0 | 334 | * paint. Returns false otherwise. |
michael@0 | 335 | */ |
michael@0 | 336 | static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey); |
michael@0 | 337 | |
michael@0 | 338 | class DisplayItemData; |
michael@0 | 339 | typedef void (*DisplayItemDataCallback)(nsIFrame *aFrame, DisplayItemData* aItem); |
michael@0 | 340 | |
michael@0 | 341 | static void IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback); |
michael@0 | 342 | |
michael@0 | 343 | /** |
michael@0 | 344 | * Save transform that was in aLayer when we last painted, and the position |
michael@0 | 345 | * of the active scrolled root frame. It must be an integer |
michael@0 | 346 | * translation. |
michael@0 | 347 | */ |
michael@0 | 348 | void SaveLastPaintOffset(ThebesLayer* aLayer); |
michael@0 | 349 | /** |
michael@0 | 350 | * Get the translation transform that was in aLayer when we last painted. It's either |
michael@0 | 351 | * the transform saved by SaveLastPaintTransform, or else the transform |
michael@0 | 352 | * that's currently in the layer (which must be an integer translation). |
michael@0 | 353 | */ |
michael@0 | 354 | nsIntPoint GetLastPaintOffset(ThebesLayer* aLayer); |
michael@0 | 355 | |
michael@0 | 356 | /** |
michael@0 | 357 | * Return the resolution at which we expect to render aFrame's contents, |
michael@0 | 358 | * assuming they are being painted to retained layers. This takes into account |
michael@0 | 359 | * the resolution the contents of the ContainerLayer containing aFrame are |
michael@0 | 360 | * being rendered at, as well as any currently-inactive transforms between |
michael@0 | 361 | * aFrame and that container layer. |
michael@0 | 362 | */ |
michael@0 | 363 | static gfxSize GetThebesLayerScaleForFrame(nsIFrame* aFrame); |
michael@0 | 364 | |
michael@0 | 365 | /** |
michael@0 | 366 | * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair. |
michael@0 | 367 | * |
michael@0 | 368 | * Used when we optimize a ThebesLayer into an ImageLayer and want to retroactively update the |
michael@0 | 369 | * DisplayItemData so we can retrieve the layer from within layout. |
michael@0 | 370 | */ |
michael@0 | 371 | void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer); |
michael@0 | 372 | |
michael@0 | 373 | NS_DECLARE_FRAME_PROPERTY_WITH_FRAME_IN_DTOR(LayerManagerDataProperty, |
michael@0 | 374 | RemoveFrameFromLayerManager) |
michael@0 | 375 | |
michael@0 | 376 | /** |
michael@0 | 377 | * Retained data storage: |
michael@0 | 378 | * |
michael@0 | 379 | * Each layer manager (widget, and inactive) stores a LayerManagerData object |
michael@0 | 380 | * that keeps a hash-set of DisplayItemData items that were drawn into it. |
michael@0 | 381 | * Each frame also keeps a list of DisplayItemData pointers that were |
michael@0 | 382 | * created for that frame. DisplayItemData objects manage these lists automatically. |
michael@0 | 383 | * |
michael@0 | 384 | * During layer construction we update the data in the LayerManagerData object, marking |
michael@0 | 385 | * items that are modified. At the end we sweep the LayerManagerData hash-set and remove |
michael@0 | 386 | * all items that haven't been modified. |
michael@0 | 387 | */ |
michael@0 | 388 | |
michael@0 | 389 | /** |
michael@0 | 390 | * Retained data for a display item. |
michael@0 | 391 | */ |
michael@0 | 392 | class DisplayItemData MOZ_FINAL { |
michael@0 | 393 | public: |
michael@0 | 394 | friend class FrameLayerBuilder; |
michael@0 | 395 | |
michael@0 | 396 | uint32_t GetDisplayItemKey() { return mDisplayItemKey; } |
michael@0 | 397 | Layer* GetLayer() { return mLayer; } |
michael@0 | 398 | void Invalidate() { mIsInvalid = true; } |
michael@0 | 399 | |
michael@0 | 400 | private: |
michael@0 | 401 | DisplayItemData(LayerManagerData* aParent, uint32_t aKey, Layer* aLayer, LayerState aLayerState, uint32_t aGeneration); |
michael@0 | 402 | DisplayItemData(DisplayItemData &toCopy); |
michael@0 | 403 | |
michael@0 | 404 | /** |
michael@0 | 405 | * Removes any references to this object from frames |
michael@0 | 406 | * in mFrameList. |
michael@0 | 407 | */ |
michael@0 | 408 | ~DisplayItemData(); |
michael@0 | 409 | |
michael@0 | 410 | NS_INLINE_DECL_REFCOUNTING(DisplayItemData) |
michael@0 | 411 | |
michael@0 | 412 | |
michael@0 | 413 | /** |
michael@0 | 414 | * Associates this DisplayItemData with a frame, and adds it |
michael@0 | 415 | * to the LayerManagerDataProperty list on the frame. |
michael@0 | 416 | */ |
michael@0 | 417 | void AddFrame(nsIFrame* aFrame); |
michael@0 | 418 | void RemoveFrame(nsIFrame* aFrame); |
michael@0 | 419 | void GetFrameListChanges(nsDisplayItem* aOther, nsTArray<nsIFrame*>& aOut); |
michael@0 | 420 | |
michael@0 | 421 | /** |
michael@0 | 422 | * Updates the contents of this item to a new set of data, instead of allocating a new |
michael@0 | 423 | * object. |
michael@0 | 424 | * Set the passed in parameters, and clears the opt layer, inactive manager, geometry |
michael@0 | 425 | * and clip. |
michael@0 | 426 | * Parent, frame list and display item key are assumed to be the same. |
michael@0 | 427 | */ |
michael@0 | 428 | void UpdateContents(Layer* aLayer, LayerState aState, |
michael@0 | 429 | uint32_t aContainerLayerGeneration, nsDisplayItem* aItem = nullptr); |
michael@0 | 430 | |
michael@0 | 431 | LayerManagerData* mParent; |
michael@0 | 432 | nsRefPtr<Layer> mLayer; |
michael@0 | 433 | nsRefPtr<Layer> mOptLayer; |
michael@0 | 434 | nsRefPtr<BasicLayerManager> mInactiveManager; |
michael@0 | 435 | nsAutoTArray<nsIFrame*, 1> mFrameList; |
michael@0 | 436 | nsAutoPtr<nsDisplayItemGeometry> mGeometry; |
michael@0 | 437 | DisplayItemClip mClip; |
michael@0 | 438 | uint32_t mDisplayItemKey; |
michael@0 | 439 | uint32_t mContainerLayerGeneration; |
michael@0 | 440 | LayerState mLayerState; |
michael@0 | 441 | |
michael@0 | 442 | /** |
michael@0 | 443 | * Used to track if data currently stored in mFramesWithLayers (from an existing |
michael@0 | 444 | * paint) has been updated in the current paint. |
michael@0 | 445 | */ |
michael@0 | 446 | bool mUsed; |
michael@0 | 447 | bool mIsInvalid; |
michael@0 | 448 | }; |
michael@0 | 449 | |
michael@0 | 450 | protected: |
michael@0 | 451 | |
michael@0 | 452 | friend class LayerManagerData; |
michael@0 | 453 | |
michael@0 | 454 | static void RemoveFrameFromLayerManager(nsIFrame* aFrame, void* aPropertyValue); |
michael@0 | 455 | |
michael@0 | 456 | /** |
michael@0 | 457 | * Given a frame and a display item key that uniquely identifies a |
michael@0 | 458 | * display item for the frame, find the layer that was last used to |
michael@0 | 459 | * render that display item. Returns null if there is no such layer. |
michael@0 | 460 | * This could be a dedicated layer for the display item, or a ThebesLayer |
michael@0 | 461 | * that renders many display items. |
michael@0 | 462 | */ |
michael@0 | 463 | DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey); |
michael@0 | 464 | |
michael@0 | 465 | /** |
michael@0 | 466 | * Stores DisplayItemData associated with aFrame, stores the data in |
michael@0 | 467 | * mNewDisplayItemData. |
michael@0 | 468 | */ |
michael@0 | 469 | DisplayItemData* StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState); |
michael@0 | 470 | void StoreDataForFrame(nsIFrame* aFrame, |
michael@0 | 471 | uint32_t aDisplayItemKey, |
michael@0 | 472 | Layer* aLayer, |
michael@0 | 473 | LayerState aState); |
michael@0 | 474 | |
michael@0 | 475 | // Flash the area within the context clip if paint flashing is enabled. |
michael@0 | 476 | static void FlashPaint(gfxContext *aContext); |
michael@0 | 477 | |
michael@0 | 478 | /* |
michael@0 | 479 | * Get the DisplayItemData array associated with this frame, or null if one |
michael@0 | 480 | * doesn't exist. |
michael@0 | 481 | * |
michael@0 | 482 | * Note that the pointer returned here is only valid so long as you don't |
michael@0 | 483 | * poke the LayerManagerData's mFramesWithLayers hashtable. |
michael@0 | 484 | */ |
michael@0 | 485 | DisplayItemData* GetDisplayItemData(nsIFrame *aFrame, uint32_t aKey); |
michael@0 | 486 | |
michael@0 | 487 | /* |
michael@0 | 488 | * Get the DisplayItemData associated with this frame / display item pair, |
michael@0 | 489 | * using the LayerManager instead of FrameLayerBuilder. |
michael@0 | 490 | */ |
michael@0 | 491 | static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, |
michael@0 | 492 | uint32_t aDisplayItemKey, |
michael@0 | 493 | LayerManager* aManager); |
michael@0 | 494 | static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, |
michael@0 | 495 | uint32_t aDisplayItemKey); |
michael@0 | 496 | static DisplayItemData* GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager); |
michael@0 | 497 | static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame, |
michael@0 | 498 | uint32_t aDisplayItemKey, |
michael@0 | 499 | LayerManagerData* aData); |
michael@0 | 500 | |
michael@0 | 501 | static PLDHashOperator DumpDisplayItemDataForFrame(nsRefPtrHashKey<DisplayItemData>* aEntry, |
michael@0 | 502 | void* aClosure); |
michael@0 | 503 | /** |
michael@0 | 504 | * We store one of these for each display item associated with a |
michael@0 | 505 | * ThebesLayer, in a hashtable that maps each ThebesLayer to an array |
michael@0 | 506 | * of ClippedDisplayItems. (ThebesLayerItemsEntry is the hash entry |
michael@0 | 507 | * for that hashtable.) |
michael@0 | 508 | * These are only stored during the paint process, so that the |
michael@0 | 509 | * DrawThebesLayer callback can figure out which items to draw for the |
michael@0 | 510 | * ThebesLayer. |
michael@0 | 511 | */ |
michael@0 | 512 | struct ClippedDisplayItem { |
michael@0 | 513 | ClippedDisplayItem(nsDisplayItem* aItem, uint32_t aGeneration) |
michael@0 | 514 | : mItem(aItem), mContainerLayerGeneration(aGeneration) |
michael@0 | 515 | { |
michael@0 | 516 | } |
michael@0 | 517 | |
michael@0 | 518 | ~ClippedDisplayItem(); |
michael@0 | 519 | |
michael@0 | 520 | nsDisplayItem* mItem; |
michael@0 | 521 | |
michael@0 | 522 | /** |
michael@0 | 523 | * If the display item is being rendered as an inactive |
michael@0 | 524 | * layer, then this stores the layer manager being |
michael@0 | 525 | * used for the inactive transaction. |
michael@0 | 526 | */ |
michael@0 | 527 | nsRefPtr<LayerManager> mInactiveLayerManager; |
michael@0 | 528 | |
michael@0 | 529 | uint32_t mContainerLayerGeneration; |
michael@0 | 530 | }; |
michael@0 | 531 | |
michael@0 | 532 | static void RecomputeVisibilityForItems(nsTArray<ClippedDisplayItem>& aItems, |
michael@0 | 533 | nsDisplayListBuilder* aBuilder, |
michael@0 | 534 | const nsIntRegion& aRegionToDraw, |
michael@0 | 535 | const nsIntPoint& aOffset, |
michael@0 | 536 | int32_t aAppUnitsPerDevPixel, |
michael@0 | 537 | float aXScale, |
michael@0 | 538 | float aYScale); |
michael@0 | 539 | |
michael@0 | 540 | void PaintItems(nsTArray<ClippedDisplayItem>& aItems, |
michael@0 | 541 | const nsIntRect& aRect, |
michael@0 | 542 | gfxContext* aContext, |
michael@0 | 543 | nsRenderingContext* aRC, |
michael@0 | 544 | nsDisplayListBuilder* aBuilder, |
michael@0 | 545 | nsPresContext* aPresContext, |
michael@0 | 546 | const nsIntPoint& aOffset, |
michael@0 | 547 | float aXScale, float aYScale, |
michael@0 | 548 | int32_t aCommonClipCount); |
michael@0 | 549 | |
michael@0 | 550 | /** |
michael@0 | 551 | * We accumulate ClippedDisplayItem elements in a hashtable during |
michael@0 | 552 | * the paint process. This is the hashentry for that hashtable. |
michael@0 | 553 | */ |
michael@0 | 554 | public: |
michael@0 | 555 | class ThebesLayerItemsEntry : public nsPtrHashKey<ThebesLayer> { |
michael@0 | 556 | public: |
michael@0 | 557 | ThebesLayerItemsEntry(const ThebesLayer *key) : |
michael@0 | 558 | nsPtrHashKey<ThebesLayer>(key), mContainerLayerFrame(nullptr), |
michael@0 | 559 | mContainerLayerGeneration(0), |
michael@0 | 560 | mHasExplicitLastPaintOffset(false), mCommonClipCount(0) {} |
michael@0 | 561 | ThebesLayerItemsEntry(const ThebesLayerItemsEntry &toCopy) : |
michael@0 | 562 | nsPtrHashKey<ThebesLayer>(toCopy.mKey), mItems(toCopy.mItems) |
michael@0 | 563 | { |
michael@0 | 564 | NS_ERROR("Should never be called, since we ALLOW_MEMMOVE"); |
michael@0 | 565 | } |
michael@0 | 566 | |
michael@0 | 567 | nsTArray<ClippedDisplayItem> mItems; |
michael@0 | 568 | nsIFrame* mContainerLayerFrame; |
michael@0 | 569 | // The translation set on this ThebesLayer before we started updating the |
michael@0 | 570 | // layer tree. |
michael@0 | 571 | nsIntPoint mLastPaintOffset; |
michael@0 | 572 | uint32_t mContainerLayerGeneration; |
michael@0 | 573 | bool mHasExplicitLastPaintOffset; |
michael@0 | 574 | /** |
michael@0 | 575 | * The first mCommonClipCount rounded rectangle clips are identical for |
michael@0 | 576 | * all items in the layer. Computed in ThebesLayerData. |
michael@0 | 577 | */ |
michael@0 | 578 | uint32_t mCommonClipCount; |
michael@0 | 579 | |
michael@0 | 580 | enum { ALLOW_MEMMOVE = true }; |
michael@0 | 581 | }; |
michael@0 | 582 | |
michael@0 | 583 | /** |
michael@0 | 584 | * Get the ThebesLayerItemsEntry object associated with aLayer in this |
michael@0 | 585 | * FrameLayerBuilder |
michael@0 | 586 | */ |
michael@0 | 587 | ThebesLayerItemsEntry* GetThebesLayerItemsEntry(ThebesLayer* aLayer) |
michael@0 | 588 | { |
michael@0 | 589 | return mThebesLayerItems.GetEntry(aLayer); |
michael@0 | 590 | } |
michael@0 | 591 | |
michael@0 | 592 | ThebesLayerData* GetContainingThebesLayerData() |
michael@0 | 593 | { |
michael@0 | 594 | return mContainingThebesLayer; |
michael@0 | 595 | } |
michael@0 | 596 | |
michael@0 | 597 | /** |
michael@0 | 598 | * Attempt to build the most compressed layer tree possible, even if it means |
michael@0 | 599 | * throwing away existing retained buffers. |
michael@0 | 600 | */ |
michael@0 | 601 | void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; } |
michael@0 | 602 | bool CheckInLayerTreeCompressionMode(); |
michael@0 | 603 | |
michael@0 | 604 | protected: |
michael@0 | 605 | void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer, |
michael@0 | 606 | bool aRemoveThebesItems, |
michael@0 | 607 | bool aRemoveOwnerData); |
michael@0 | 608 | |
michael@0 | 609 | static PLDHashOperator ProcessRemovedDisplayItems(nsRefPtrHashKey<DisplayItemData>* aEntry, |
michael@0 | 610 | void* aUserArg); |
michael@0 | 611 | static PLDHashOperator RestoreDisplayItemData(nsRefPtrHashKey<DisplayItemData>* aEntry, |
michael@0 | 612 | void *aUserArg); |
michael@0 | 613 | |
michael@0 | 614 | static PLDHashOperator RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry, |
michael@0 | 615 | void *aUserArg); |
michael@0 | 616 | |
michael@0 | 617 | /** |
michael@0 | 618 | * Returns true if the DOM has been modified since we started painting, |
michael@0 | 619 | * in which case we should bail out and not paint anymore. This should |
michael@0 | 620 | * never happen, but plugins can trigger it in some cases. |
michael@0 | 621 | */ |
michael@0 | 622 | bool CheckDOMModified(); |
michael@0 | 623 | |
michael@0 | 624 | /** |
michael@0 | 625 | * The layer manager belonging to the widget that is being retained |
michael@0 | 626 | * across paints. |
michael@0 | 627 | */ |
michael@0 | 628 | LayerManager* mRetainingManager; |
michael@0 | 629 | /** |
michael@0 | 630 | * The root prescontext for the display list builder reference frame |
michael@0 | 631 | */ |
michael@0 | 632 | nsRefPtr<nsRootPresContext> mRootPresContext; |
michael@0 | 633 | |
michael@0 | 634 | /** |
michael@0 | 635 | * The display list builder being used. |
michael@0 | 636 | */ |
michael@0 | 637 | nsDisplayListBuilder* mDisplayListBuilder; |
michael@0 | 638 | /** |
michael@0 | 639 | * A map from ThebesLayers to the list of display items (plus |
michael@0 | 640 | * clipping data) to be rendered in the layer. |
michael@0 | 641 | */ |
michael@0 | 642 | nsTHashtable<ThebesLayerItemsEntry> mThebesLayerItems; |
michael@0 | 643 | |
michael@0 | 644 | /** |
michael@0 | 645 | * When building layers for an inactive layer, this is where the |
michael@0 | 646 | * inactive layer will be placed. |
michael@0 | 647 | */ |
michael@0 | 648 | ThebesLayerData* mContainingThebesLayer; |
michael@0 | 649 | |
michael@0 | 650 | /** |
michael@0 | 651 | * Saved generation counter so we can detect DOM changes. |
michael@0 | 652 | */ |
michael@0 | 653 | uint32_t mInitialDOMGeneration; |
michael@0 | 654 | /** |
michael@0 | 655 | * Set to true if we have detected and reported DOM modification during |
michael@0 | 656 | * the current paint. |
michael@0 | 657 | */ |
michael@0 | 658 | bool mDetectedDOMModification; |
michael@0 | 659 | /** |
michael@0 | 660 | * Indicates that the entire layer tree should be rerendered |
michael@0 | 661 | * during this paint. |
michael@0 | 662 | */ |
michael@0 | 663 | bool mInvalidateAllLayers; |
michael@0 | 664 | |
michael@0 | 665 | bool mInLayerTreeCompressionMode; |
michael@0 | 666 | |
michael@0 | 667 | uint32_t mContainerLayerGeneration; |
michael@0 | 668 | uint32_t mMaxContainerLayerGeneration; |
michael@0 | 669 | }; |
michael@0 | 670 | |
michael@0 | 671 | } |
michael@0 | 672 | |
michael@0 | 673 | #endif /* FRAMELAYERBUILDER_H_ */ |