Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef FRAMELAYERBUILDER_H_
7 : #define FRAMELAYERBUILDER_H_
8 :
9 : #include "nsAutoPtr.h"
10 : #include "nsTHashtable.h"
11 : #include "nsHashKeys.h"
12 : #include "nsTArray.h"
13 : #include "nsRegion.h"
14 : #include "nsIFrame.h"
15 : #include "DisplayItemClip.h"
16 : #include "mozilla/gfx/MatrixFwd.h"
17 : #include "mozilla/layers/LayersTypes.h"
18 : #include "LayerState.h"
19 : #include "Layers.h"
20 : #include "LayerUserData.h"
21 :
22 : class nsDisplayListBuilder;
23 : class nsDisplayList;
24 : class nsDisplayItem;
25 : class gfxContext;
26 : class nsDisplayItemGeometry;
27 : class nsDisplayMask;
28 :
29 : namespace mozilla {
30 : struct ActiveScrolledRoot;
31 : struct DisplayItemClipChain;
32 : namespace layers {
33 : class ContainerLayer;
34 : class LayerManager;
35 : class BasicLayerManager;
36 : class PaintedLayer;
37 : class ImageLayer;
38 : } // namespace layers
39 :
40 : class FrameLayerBuilder;
41 : class LayerManagerData;
42 : class PaintedLayerData;
43 : class ContainerState;
44 :
45 : /**
46 : * Retained data storage:
47 : *
48 : * Each layer manager (widget, and inactive) stores a LayerManagerData object
49 : * that keeps a hash-set of DisplayItemData items that were drawn into it.
50 : * Each frame also keeps a list of DisplayItemData pointers that were
51 : * created for that frame. DisplayItemData objects manage these lists automatically.
52 : *
53 : * During layer construction we update the data in the LayerManagerData object, marking
54 : * items that are modified. At the end we sweep the LayerManagerData hash-set and remove
55 : * all items that haven't been modified.
56 : */
57 :
58 : /**
59 : * Retained data for a display item.
60 : */
61 : class DisplayItemData final {
62 : public:
63 : friend class FrameLayerBuilder;
64 :
65 567 : uint32_t GetDisplayItemKey() { return mDisplayItemKey; }
66 : layers::Layer* GetLayer() { return mLayer; }
67 287 : nsDisplayItemGeometry* GetGeometry() const { return mGeometry.get(); }
68 13 : void Invalidate() { mIsInvalid = true; }
69 : void ClearAnimationCompositorState();
70 :
71 : static DisplayItemData* AssertDisplayItemData(DisplayItemData* aData);
72 :
73 87 : void* operator new(size_t sz, nsPresContext* aPresContext)
74 : {
75 : // Check the recycle list first.
76 : return aPresContext->PresShell()->
77 87 : AllocateByObjectID(eArenaObjectID_DisplayItemData, sz);
78 : }
79 :
80 186 : nsrefcnt AddRef() {
81 186 : if (mRefCnt == UINT32_MAX) {
82 0 : NS_WARNING("refcount overflow, leaking object");
83 0 : return mRefCnt;
84 : }
85 186 : ++mRefCnt;
86 186 : NS_LOG_ADDREF(this, mRefCnt, "nsStyleContext", sizeof(nsStyleContext));
87 186 : return mRefCnt;
88 : }
89 :
90 124 : nsrefcnt Release() {
91 124 : if (mRefCnt == UINT32_MAX) {
92 0 : NS_WARNING("refcount overflow, leaking object");
93 0 : return mRefCnt;
94 : }
95 124 : --mRefCnt;
96 124 : NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
97 124 : if (mRefCnt == 0) {
98 25 : Destroy();
99 25 : return 0;
100 : }
101 99 : return mRefCnt;
102 : }
103 :
104 : private:
105 : DisplayItemData(LayerManagerData* aParent,
106 : uint32_t aKey,
107 : layers::Layer* aLayer,
108 : nsIFrame* aFrame = nullptr);
109 :
110 : /**
111 : * Removes any references to this object from frames
112 : * in mFrameList.
113 : */
114 : ~DisplayItemData();
115 :
116 25 : void Destroy()
117 : {
118 : // Get the pres context.
119 50 : RefPtr<nsPresContext> presContext = mFrameList[0]->PresContext();
120 :
121 : // Call our destructor.
122 25 : this->~DisplayItemData();
123 :
124 : // Don't let the memory be freed, since it will be recycled
125 : // instead. Don't call the global operator delete.
126 : presContext->PresShell()->
127 25 : FreeByObjectID(eArenaObjectID_DisplayItemData, this);
128 25 : }
129 :
130 : /**
131 : * Associates this DisplayItemData with a frame, and adds it
132 : * to the LayerManagerDataProperty list on the frame.
133 : */
134 : void AddFrame(nsIFrame* aFrame);
135 : void RemoveFrame(nsIFrame* aFrame);
136 : const nsRegion& GetChangedFrameInvalidations();
137 :
138 : /**
139 : * Updates the contents of this item to a new set of data, instead of allocating a new
140 : * object.
141 : * Set the passed in parameters, and clears the opt layer and inactive manager.
142 : * Parent, and display item key are assumed to be the same.
143 : *
144 : * EndUpdate must be called before the end of the transaction to complete the update.
145 : */
146 : void BeginUpdate(layers::Layer* aLayer, LayerState aState,
147 : uint32_t aContainerLayerGeneration, nsDisplayItem* aItem = nullptr);
148 :
149 : /**
150 : * Completes the update of this, and removes any references to data that won't live
151 : * longer than the transaction.
152 : *
153 : * Updates the geometry, frame list and clip.
154 : * For items within a PaintedLayer, a geometry object must be specified to retain
155 : * until the next transaction.
156 : *
157 : */
158 : void EndUpdate(nsAutoPtr<nsDisplayItemGeometry> aGeometry);
159 : void EndUpdate();
160 :
161 : uint32_t mRefCnt;
162 : LayerManagerData* mParent;
163 : RefPtr<layers::Layer> mLayer;
164 : RefPtr<layers::Layer> mOptLayer;
165 : RefPtr<layers::BasicLayerManager> mInactiveManager;
166 : AutoTArray<nsIFrame*, 1> mFrameList;
167 : nsAutoPtr<nsDisplayItemGeometry> mGeometry;
168 : DisplayItemClip mClip;
169 : uint32_t mDisplayItemKey;
170 : uint32_t mContainerLayerGeneration;
171 : LayerState mLayerState;
172 :
173 : /**
174 : * Temporary stoarage of the display item being referenced, only valid between
175 : * BeginUpdate and EndUpdate.
176 : */
177 : nsDisplayItem* mItem;
178 : nsRegion mChangedFrameInvalidations;
179 :
180 : /**
181 : * Used to track if data currently stored in mFramesWithLayers (from an existing
182 : * paint) has been updated in the current paint.
183 : */
184 : bool mUsed;
185 : bool mIsInvalid;
186 : };
187 :
188 : class RefCountedRegion {
189 : private:
190 : ~RefCountedRegion() {}
191 : public:
192 : NS_INLINE_DECL_REFCOUNTING(RefCountedRegion)
193 :
194 : RefCountedRegion() : mIsInfinite(false) {}
195 : nsRegion mRegion;
196 : bool mIsInfinite;
197 : };
198 :
199 : struct ContainerLayerParameters {
200 382 : ContainerLayerParameters()
201 382 : : mXScale(1)
202 : , mYScale(1)
203 : , mLayerContentsVisibleRect(nullptr)
204 : , mBackgroundColor(NS_RGBA(0,0,0,0))
205 : , mScrollMetadataASR(nullptr)
206 : , mCompositorASR(nullptr)
207 : , mInTransformedSubtree(false)
208 : , mInActiveTransformedSubtree(false)
209 : , mDisableSubpixelAntialiasingInDescendants(false)
210 : , mInLowPrecisionDisplayPort(false)
211 : , mForEventsAndPluginsOnly(false)
212 382 : , mLayerCreationHint(layers::LayerManager::NONE)
213 382 : {}
214 44 : ContainerLayerParameters(float aXScale, float aYScale)
215 44 : : mXScale(aXScale)
216 : , mYScale(aYScale)
217 : , mLayerContentsVisibleRect(nullptr)
218 : , mBackgroundColor(NS_RGBA(0,0,0,0))
219 : , mScrollMetadataASR(nullptr)
220 : , mCompositorASR(nullptr)
221 : , mInTransformedSubtree(false)
222 : , mInActiveTransformedSubtree(false)
223 : , mDisableSubpixelAntialiasingInDescendants(false)
224 : , mInLowPrecisionDisplayPort(false)
225 : , mForEventsAndPluginsOnly(false)
226 44 : , mLayerCreationHint(layers::LayerManager::NONE)
227 44 : {}
228 239 : ContainerLayerParameters(float aXScale, float aYScale,
229 : const nsIntPoint& aOffset,
230 : const ContainerLayerParameters& aParent)
231 239 : : mXScale(aXScale)
232 : , mYScale(aYScale)
233 : , mLayerContentsVisibleRect(nullptr)
234 : , mOffset(aOffset)
235 239 : , mBackgroundColor(aParent.mBackgroundColor)
236 239 : , mScrollMetadataASR(aParent.mScrollMetadataASR)
237 239 : , mCompositorASR(aParent.mCompositorASR)
238 239 : , mInTransformedSubtree(aParent.mInTransformedSubtree)
239 239 : , mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree)
240 239 : , mDisableSubpixelAntialiasingInDescendants(aParent.mDisableSubpixelAntialiasingInDescendants)
241 239 : , mInLowPrecisionDisplayPort(aParent.mInLowPrecisionDisplayPort)
242 239 : , mForEventsAndPluginsOnly(aParent.mForEventsAndPluginsOnly)
243 2151 : , mLayerCreationHint(aParent.mLayerCreationHint)
244 239 : {}
245 :
246 : float mXScale, mYScale;
247 :
248 27 : LayoutDeviceToLayerScale2D Scale() const {
249 27 : return LayoutDeviceToLayerScale2D(mXScale, mYScale);
250 : }
251 :
252 : /**
253 : * If non-null, the rectangle in which BuildContainerLayerFor stores the
254 : * visible rect of the layer, in the coordinate system of the created layer.
255 : */
256 : nsIntRect* mLayerContentsVisibleRect;
257 :
258 : /**
259 : * An offset to apply to all child layers created.
260 : */
261 : nsIntPoint mOffset;
262 :
263 0 : LayerIntPoint Offset() const {
264 0 : return LayerIntPoint::FromUnknownPoint(mOffset);
265 : }
266 :
267 : nscolor mBackgroundColor;
268 : const ActiveScrolledRoot* mScrollMetadataASR;
269 : const ActiveScrolledRoot* mCompositorASR;
270 :
271 : bool mInTransformedSubtree;
272 : bool mInActiveTransformedSubtree;
273 : bool mDisableSubpixelAntialiasingInDescendants;
274 : bool mInLowPrecisionDisplayPort;
275 : bool mForEventsAndPluginsOnly;
276 : layers::LayerManager::PaintedLayerCreationHint mLayerCreationHint;
277 :
278 : /**
279 : * When this is false, PaintedLayer coordinates are drawn to with an integer
280 : * translation and the scale in mXScale/mYScale.
281 : */
282 497 : bool AllowResidualTranslation()
283 : {
284 : // If we're in a transformed subtree, but no ancestor transform is actively
285 : // changing, we'll use the residual translation when drawing into the
286 : // PaintedLayer to ensure that snapping exactly matches the ideal transform.
287 497 : return mInTransformedSubtree && !mInActiveTransformedSubtree;
288 : }
289 : };
290 :
291 : /**
292 : * The FrameLayerBuilder is responsible for converting display lists
293 : * into layer trees. Every LayerManager needs a unique FrameLayerBuilder
294 : * to build layers.
295 : *
296 : * The most important API in this class is BuildContainerLayerFor. This
297 : * method takes a display list as input and constructs a ContainerLayer
298 : * with child layers that render the contents of the display list. It
299 : * records the relationship between frames and layers.
300 : *
301 : * That data enables us to retain layer trees. When constructing a
302 : * ContainerLayer, we first check to see if there's an existing
303 : * ContainerLayer for the same frame that can be recycled. If we recycle
304 : * it, we also try to reuse its existing PaintedLayer children to render
305 : * the display items without layers of their own. The idea is that by
306 : * recycling layers deterministically, we can ensure that when nothing
307 : * changes in a display list, we will reuse the existing layers without
308 : * changes.
309 : *
310 : * We expose a GetLeafLayerFor method that can be called by display items
311 : * that make their own layers (e.g. canvas and video); this method
312 : * locates the last layer used to render the display item, if any, and
313 : * return it as a candidate for recycling.
314 : *
315 : * FrameLayerBuilder sets up PaintedLayers so that 0,0 in the Painted layer
316 : * corresponds to the (pixel-snapped) top-left of the aAnimatedGeometryRoot.
317 : * It sets up ContainerLayers so that 0,0 in the container layer
318 : * corresponds to the snapped top-left of the display item reference frame.
319 : *
320 : * When we construct a container layer, we know the transform that will be
321 : * applied to the layer. If the transform scales the content, we can get
322 : * better results when intermediate buffers are used by pushing some scale
323 : * from the container's transform down to the children. For PaintedLayer
324 : * children, the scaling can be achieved by changing the size of the layer
325 : * and drawing into it with increased or decreased resolution. By convention,
326 : * integer types (nsIntPoint/nsIntSize/nsIntRect/nsIntRegion) are all in layer
327 : * coordinates, post-scaling, whereas appunit types are all pre-scaling.
328 : */
329 : class FrameLayerBuilder : public layers::LayerUserData {
330 : public:
331 : typedef layers::ContainerLayer ContainerLayer;
332 : typedef layers::Layer Layer;
333 : typedef layers::PaintedLayer PaintedLayer;
334 : typedef layers::ImageLayer ImageLayer;
335 : typedef layers::LayerManager LayerManager;
336 : typedef layers::BasicLayerManager BasicLayerManager;
337 : typedef layers::EventRegions EventRegions;
338 :
339 : FrameLayerBuilder();
340 : ~FrameLayerBuilder();
341 :
342 : static void Shutdown();
343 :
344 : void Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
345 : PaintedLayerData* aLayerData = nullptr,
346 : const DisplayItemClip* aInactiveLayerClip = nullptr);
347 :
348 : /**
349 : * Call this to notify that we have just started a transaction on the
350 : * retained layer manager aManager.
351 : */
352 : void DidBeginRetainedLayerTransaction(LayerManager* aManager);
353 :
354 : /**
355 : * Call this just before we end a transaction.
356 : */
357 : void WillEndTransaction();
358 :
359 : /**
360 : * Call this after we end a transaction.
361 : */
362 : void DidEndTransaction();
363 :
364 : enum {
365 : /**
366 : * Set this when pulling an opaque background color from behind the
367 : * container layer into the container doesn't change the visual results,
368 : * given the effects you're going to apply to the container layer.
369 : * For example, this is compatible with opacity or clipping/masking, but
370 : * not with non-OVER blend modes or filters.
371 : */
372 : CONTAINER_ALLOW_PULL_BACKGROUND_COLOR = 0x01
373 : };
374 : /**
375 : * Build a container layer for a display item that contains a child
376 : * list, either reusing an existing one or creating a new one. It
377 : * sets the container layer children to layers which together render
378 : * the contents of the display list. It reuses existing layers from
379 : * the retained layer manager if possible.
380 : * aContainerItem may be null, in which case we construct a root layer.
381 : * This gets called by display list code. It calls BuildLayer on the
382 : * items in the display list, making items with their own layers
383 : * children of the new container, and assigning all other items to
384 : * PaintedLayer children created and managed by the FrameLayerBuilder.
385 : * Returns a layer with clip rect cleared; it is the
386 : * caller's responsibility to add any clip rect. The visible region
387 : * is set based on what's in the layer.
388 : * The container layer is transformed by aTransform (if non-null), and
389 : * the result is transformed by the scale factors in aContainerParameters.
390 : * aChildren is modified due to display item merging and flattening.
391 : * The visible region of the returned layer is set only if aContainerItem
392 : * is null.
393 : */
394 : already_AddRefed<ContainerLayer>
395 : BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
396 : LayerManager* aManager,
397 : nsIFrame* aContainerFrame,
398 : nsDisplayItem* aContainerItem,
399 : nsDisplayList* aChildren,
400 : const ContainerLayerParameters& aContainerParameters,
401 : const gfx::Matrix4x4* aTransform,
402 : uint32_t aFlags = 0);
403 :
404 : /**
405 : * Get a retained layer for a display item that needs to create its own
406 : * layer for rendering (i.e. under nsDisplayItem::BuildLayer). Returns
407 : * null if no retained layer is available, which usually means that this
408 : * display item didn't have a layer before so the caller will
409 : * need to create one.
410 : * Returns a layer with clip rect cleared; it is the
411 : * caller's responsibility to add any clip rect and set the visible
412 : * region.
413 : */
414 : Layer* GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
415 : nsDisplayItem* aItem);
416 :
417 : /**
418 : * Call this to force all retained layers to be discarded and recreated at
419 : * the next paint.
420 : */
421 : static void InvalidateAllLayers(LayerManager* aManager);
422 : static void InvalidateAllLayersForFrame(nsIFrame *aFrame);
423 :
424 : /**
425 : * Call this to determine if a frame has a dedicated (non-Painted) layer
426 : * for the given display item key. If there isn't one, we return null,
427 : * otherwise we return the layer.
428 : */
429 : static Layer* GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey);
430 :
431 : /**
432 : * This callback must be provided to EndTransaction. The callback data
433 : * must be the nsDisplayListBuilder containing this FrameLayerBuilder.
434 : * This function can be called multiple times in a row to draw
435 : * different regions. This will occur when, for example, progressive paint is
436 : * enabled. In these cases aDirtyRegion can be used to specify a larger region
437 : * than aRegionToDraw that will be drawn during the transaction, possibly
438 : * allowing the callback to make optimizations.
439 : */
440 : static void DrawPaintedLayer(PaintedLayer* aLayer,
441 : gfxContext* aContext,
442 : const nsIntRegion& aRegionToDraw,
443 : const nsIntRegion& aDirtyRegion,
444 : mozilla::layers::DrawRegionClip aClip,
445 : const nsIntRegion& aRegionToInvalidate,
446 : void* aCallbackData);
447 :
448 : /**
449 : * Dumps this FrameLayerBuilder's retained layer manager's retained
450 : * layer tree. Defaults to dumping to stdout in non-HTML format.
451 : */
452 : static void DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml = false);
453 :
454 : /**
455 : * Returns the most recently allocated geometry item for the given display
456 : * item.
457 : *
458 : * XXX(seth): The current implementation must iterate through all display
459 : * items allocated for this display item's frame. This may lead to O(n^2)
460 : * behavior in some situations.
461 : */
462 : static nsDisplayItemGeometry* GetMostRecentGeometry(nsDisplayItem* aItem);
463 :
464 :
465 : /******* PRIVATE METHODS to FrameLayerBuilder.cpp ********/
466 : /* These are only in the public section because they need
467 : * to be called by file-scope helper functions in FrameLayerBuilder.cpp.
468 : */
469 :
470 : /**
471 : * Record aItem as a display item that is rendered by aLayer.
472 : *
473 : * @param aLayer Layer that the display item will be rendered into
474 : * @param aItem Display item to be drawn.
475 : * @param aLayerState What LayerState the item is using.
476 : * @param aManager If the layer is in the LAYER_INACTIVE state,
477 : * then this is the temporary layer manager to draw with.
478 : */
479 : void AddLayerDisplayItem(Layer* aLayer,
480 : nsDisplayItem* aItem,
481 : LayerState aLayerState,
482 : BasicLayerManager* aManager);
483 :
484 : /**
485 : * Record aItem as a display item that is rendered by the PaintedLayer
486 : * aLayer, with aClipRect, where aContainerLayerFrame is the frame
487 : * for the container layer this ThebesItem belongs to.
488 : * aItem must have an underlying frame.
489 : * @param aTopLeft offset from active scrolled root to reference frame
490 : */
491 : void AddPaintedDisplayItem(PaintedLayerData* aLayer,
492 : nsDisplayItem* aItem,
493 : const DisplayItemClip& aClip,
494 : ContainerState& aContainerState,
495 : LayerState aLayerState,
496 : const nsPoint& aTopLeft);
497 :
498 : /**
499 : * Calls GetOldLayerForFrame on the underlying frame of the display item,
500 : * and each subsequent merged frame if no layer is found for the underlying
501 : * frame.
502 : */
503 : Layer* GetOldLayerFor(nsDisplayItem* aItem,
504 : nsDisplayItemGeometry** aOldGeometry = nullptr,
505 : DisplayItemClip** aOldClip = nullptr);
506 :
507 : void ClearCachedGeometry(nsDisplayItem* aItem);
508 :
509 : static Layer* GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
510 :
511 : /**
512 : * Return the layer that all display items of aFrame were assigned to in the
513 : * last paint, or nullptr if there was no single layer assigned to all of the
514 : * frame's display items (i.e. zero, or more than one).
515 : * This function is for testing purposes and not performance sensitive.
516 : */
517 : template<class T>
518 : static T*
519 0 : GetDebugSingleOldLayerForFrame(nsIFrame* aFrame)
520 : {
521 0 : SmallPointerArray<DisplayItemData>& array = aFrame->DisplayItemData();
522 :
523 0 : Layer* layer = nullptr;
524 0 : for (DisplayItemData* data : array) {
525 0 : DisplayItemData::AssertDisplayItemData(data);
526 0 : if (data->mLayer->GetType() != T::Type()) {
527 0 : continue;
528 : }
529 0 : if (layer && layer != data->mLayer) {
530 : // More than one layer assigned, bail.
531 0 : return nullptr;
532 : }
533 0 : layer = data->mLayer;
534 : }
535 :
536 0 : if (!layer) {
537 0 : return nullptr;
538 : }
539 :
540 0 : return static_cast<T*>(layer);
541 : }
542 :
543 : /**
544 : * Destroy any stored LayerManagerDataProperty and the associated data for
545 : * aFrame.
546 : */
547 : static void DestroyDisplayItemDataFor(nsIFrame* aFrame);
548 :
549 : LayerManager* GetRetainingLayerManager() { return mRetainingManager; }
550 :
551 : /**
552 : * Returns true if the given display item was rendered during the previous
553 : * paint. Returns false otherwise.
554 : */
555 : static bool HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey);
556 :
557 : typedef void (*DisplayItemDataCallback)(nsIFrame *aFrame, DisplayItemData* aItem);
558 :
559 : static void IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback);
560 :
561 : /**
562 : * Save transform that was in aLayer when we last painted, and the position
563 : * of the active scrolled root frame. It must be an integer
564 : * translation.
565 : */
566 : void SavePreviousDataForLayer(PaintedLayer* aLayer, uint32_t aClipCount);
567 : /**
568 : * Get the translation transform that was in aLayer when we last painted. It's either
569 : * the transform saved by SaveLastPaintTransform, or else the transform
570 : * that's currently in the layer (which must be an integer translation).
571 : */
572 : nsIntPoint GetLastPaintOffset(PaintedLayer* aLayer);
573 :
574 : /**
575 : * Return the resolution at which we expect to render aFrame's contents,
576 : * assuming they are being painted to retained layers. This takes into account
577 : * the resolution the contents of the ContainerLayer containing aFrame are
578 : * being rendered at, as well as any currently-inactive transforms between
579 : * aFrame and that container layer.
580 : */
581 : static gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame);
582 :
583 : /**
584 : * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair.
585 : *
586 : * Used when we optimize a PaintedLayer into an ImageLayer and want to retroactively update the
587 : * DisplayItemData so we can retrieve the layer from within layout.
588 : */
589 : void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer);
590 :
591 : static void RemoveFrameFromLayerManager(const nsIFrame* aFrame,
592 : SmallPointerArray<DisplayItemData>& aArray);
593 :
594 : protected:
595 :
596 : friend class LayerManagerData;
597 :
598 : /**
599 : * Given a frame and a display item key that uniquely identifies a
600 : * display item for the frame, find the layer that was last used to
601 : * render that display item. Returns null if there is no such layer.
602 : * This could be a dedicated layer for the display item, or a PaintedLayer
603 : * that renders many display items.
604 : */
605 : DisplayItemData* GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey);
606 :
607 : /**
608 : * Stores DisplayItemData associated with aFrame, stores the data in
609 : * mNewDisplayItemData.
610 : */
611 : DisplayItemData* StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState);
612 : void StoreDataForFrame(nsIFrame* aFrame,
613 : uint32_t aDisplayItemKey,
614 : Layer* aLayer,
615 : LayerState aState);
616 :
617 : // Flash the area within the context clip if paint flashing is enabled.
618 : static void FlashPaint(gfxContext *aContext);
619 :
620 : /*
621 : * Get the DisplayItemData array associated with this frame, or null if one
622 : * doesn't exist.
623 : *
624 : * Note that the pointer returned here is only valid so long as you don't
625 : * poke the LayerManagerData's mFramesWithLayers hashtable.
626 : */
627 : DisplayItemData* GetDisplayItemData(nsIFrame *aFrame, uint32_t aKey);
628 :
629 : /*
630 : * Get the DisplayItemData associated with this frame / display item pair,
631 : * using the LayerManager instead of FrameLayerBuilder.
632 : */
633 : static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame,
634 : uint32_t aDisplayItemKey,
635 : LayerManager* aManager);
636 : static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame,
637 : uint32_t aDisplayItemKey);
638 : static DisplayItemData* GetDisplayItemDataForManager(nsDisplayItem* aItem, LayerManager* aManager);
639 : static DisplayItemData* GetDisplayItemDataForManager(nsIFrame* aFrame,
640 : uint32_t aDisplayItemKey,
641 : LayerManagerData* aData);
642 :
643 : /**
644 : * We store one of these for each display item associated with a
645 : * PaintedLayer, in a hashtable that maps each PaintedLayer to an array
646 : * of ClippedDisplayItems. (PaintedLayerItemsEntry is the hash entry
647 : * for that hashtable.)
648 : * These are only stored during the paint process, so that the
649 : * DrawPaintedLayer callback can figure out which items to draw for the
650 : * PaintedLayer.
651 : */
652 1298 : struct ClippedDisplayItem {
653 : ClippedDisplayItem(nsDisplayItem* aItem, uint32_t aGeneration);
654 : ~ClippedDisplayItem();
655 :
656 : nsDisplayItem* mItem;
657 :
658 : /**
659 : * If the display item is being rendered as an inactive
660 : * layer, then this stores the layer manager being
661 : * used for the inactive transaction.
662 : */
663 : RefPtr<LayerManager> mInactiveLayerManager;
664 :
665 : uint32_t mContainerLayerGeneration;
666 :
667 : };
668 :
669 : static void RecomputeVisibilityForItems(nsTArray<ClippedDisplayItem>& aItems,
670 : nsDisplayListBuilder* aBuilder,
671 : const nsIntRegion& aRegionToDraw,
672 : const nsIntPoint& aOffset,
673 : int32_t aAppUnitsPerDevPixel,
674 : float aXScale,
675 : float aYScale);
676 :
677 : void PaintItems(nsTArray<ClippedDisplayItem>& aItems,
678 : const nsIntRect& aRect,
679 : gfxContext* aContext,
680 : gfxContext* aRC,
681 : nsDisplayListBuilder* aBuilder,
682 : nsPresContext* aPresContext,
683 : const nsIntPoint& aOffset,
684 : float aXScale, float aYScale,
685 : int32_t aCommonClipCount);
686 :
687 : /**
688 : * We accumulate ClippedDisplayItem elements in a hashtable during
689 : * the paint process. This is the hashentry for that hashtable.
690 : */
691 : public:
692 : class PaintedLayerItemsEntry : public nsPtrHashKey<PaintedLayer> {
693 : public:
694 : explicit PaintedLayerItemsEntry(const PaintedLayer *key);
695 : PaintedLayerItemsEntry(const PaintedLayerItemsEntry&);
696 : ~PaintedLayerItemsEntry();
697 :
698 : nsTArray<ClippedDisplayItem> mItems;
699 : nsIFrame* mContainerLayerFrame;
700 : // The translation set on this PaintedLayer before we started updating the
701 : // layer tree.
702 : nsIntPoint mLastPaintOffset;
703 : uint32_t mLastCommonClipCount;
704 :
705 : uint32_t mContainerLayerGeneration;
706 : bool mHasExplicitLastPaintOffset;
707 : /**
708 : * The first mCommonClipCount rounded rectangle clips are identical for
709 : * all items in the layer. Computed in PaintedLayerData.
710 : */
711 : uint32_t mCommonClipCount;
712 :
713 : enum { ALLOW_MEMMOVE = true };
714 : };
715 :
716 : /**
717 : * Get the PaintedLayerItemsEntry object associated with aLayer in this
718 : * FrameLayerBuilder
719 : */
720 255 : PaintedLayerItemsEntry* GetPaintedLayerItemsEntry(PaintedLayer* aLayer)
721 : {
722 255 : return mPaintedLayerItems.GetEntry(aLayer);
723 : }
724 :
725 2121 : PaintedLayerData* GetContainingPaintedLayerData()
726 : {
727 2121 : return mContainingPaintedLayer;
728 : }
729 :
730 258 : const DisplayItemClip* GetInactiveLayerClip() const
731 : {
732 258 : return mInactiveLayerClip;
733 : }
734 :
735 826 : bool IsBuildingRetainedLayers()
736 : {
737 826 : return !mContainingPaintedLayer && mRetainingManager;
738 : }
739 :
740 : /**
741 : * Attempt to build the most compressed layer tree possible, even if it means
742 : * throwing away existing retained buffers.
743 : */
744 1 : void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; }
745 : bool CheckInLayerTreeCompressionMode();
746 :
747 : void ComputeGeometryChangeForItem(DisplayItemData* aData);
748 :
749 : protected:
750 : /**
751 : * Returns true if the DOM has been modified since we started painting,
752 : * in which case we should bail out and not paint anymore. This should
753 : * never happen, but plugins can trigger it in some cases.
754 : */
755 : bool CheckDOMModified();
756 :
757 : /**
758 : * The layer manager belonging to the widget that is being retained
759 : * across paints.
760 : */
761 : LayerManager* mRetainingManager;
762 : /**
763 : * The root prescontext for the display list builder reference frame
764 : */
765 : RefPtr<nsRootPresContext> mRootPresContext;
766 :
767 : /**
768 : * The display list builder being used.
769 : */
770 : nsDisplayListBuilder* mDisplayListBuilder;
771 : /**
772 : * A map from PaintedLayers to the list of display items (plus
773 : * clipping data) to be rendered in the layer.
774 : */
775 : nsTHashtable<PaintedLayerItemsEntry> mPaintedLayerItems;
776 :
777 : /**
778 : * When building layers for an inactive layer, this is where the
779 : * inactive layer will be placed.
780 : */
781 : PaintedLayerData* mContainingPaintedLayer;
782 :
783 : /**
784 : * When building layers for an inactive layer, this stores the clip
785 : * of the display item that built the inactive layer.
786 : */
787 : const DisplayItemClip* mInactiveLayerClip;
788 :
789 : /**
790 : * Saved generation counter so we can detect DOM changes.
791 : */
792 : uint32_t mInitialDOMGeneration;
793 : /**
794 : * Set to true if we have detected and reported DOM modification during
795 : * the current paint.
796 : */
797 : bool mDetectedDOMModification;
798 : /**
799 : * Indicates that the entire layer tree should be rerendered
800 : * during this paint.
801 : */
802 : bool mInvalidateAllLayers;
803 :
804 : bool mInLayerTreeCompressionMode;
805 :
806 : uint32_t mContainerLayerGeneration;
807 : uint32_t mMaxContainerLayerGeneration;
808 : };
809 :
810 : } // namespace mozilla
811 :
812 : #endif /* FRAMELAYERBUILDER_H_ */
|