Confirmed users
888
edits
Mattwoodrow (talk | contribs) No edit summary |
mNo edit summary |
||
| (8 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
Display List Based Invalidation - Bug 539356 | Display List Based Invalidation - {{Bug|539356}} | ||
Instead of invalidating areas of the screen as we do currently, we want invalidation to happen at the display list/layer boundary to reduce unnecessary redrawing | Instead of invalidating areas of the screen as we do currently, we want invalidation to happen at the display list/layer boundary to reduce unnecessary redrawing | ||
| Line 5: | Line 5: | ||
= Basic Outline = | = Basic Outline = | ||
There are 3 main components to DLBI: Frame invalidation, display list invalidation and layer tree invalidation. | |||
== Frame Invalidation == | |||
Code lives in layout/generic/nsIFrame.h and layout/generic/nsFrame.cpp | |||
This is used when a frame has a major change that will affect rendering (such as a style change) and all display items belonging to this frame should redraw their content. | |||
nsIFrame::InvalidateFrame() marks the frame as invalid. You can also specify a rect using nsIFrame::InvalidateFrameWithRect, but note that this is a minimum, the display items created by this frame can still choose to invalidate further. | |||
== Display List Invalidation == | |||
Compute the area of a ThebesLayer by comparing the current display list being drawn into the layer against the previous display list. | |||
Code lives in layout/base/FrameLayerBuilder.cpp, primarily in FrameLayerBuilder::InvalidateForLayerChange(). The nsDisplayItemGeometry classes in layout/base/nsDisplayListInvalidation.h, and layout/base/nsDisplayList.h - nsDisplayItem::AllocateGeometry(), nsDisplayItem::ComputeInvalidationRegion. | |||
Every display item is asked to allocate a geometry object that is retained between paints and then used to check for display item changes. | |||
When painting, it checks if it has been added or removed from the layer and invalidates the bounds of the display item if so. | |||
Items that exist between paints are asked to check for size changes using nsDisplayItem::ComputeInvalidationRegion and will compute the changed area (if any). | |||
== Layer Tree Invalidation == | |||
Code lives in gfx/layers/LayerTreeInvalidation.{h,cpp}. | |||
Computes changes in layer trees and reports the invalid area. | |||
Used to find changes in inactive layer trees, compute widget dirty rects (BasicLayers only) and report MozAfterPaint events. | |||
= Implementor Notes = | |||
* DLBI assumes that each frame builds display items for its own content. If changes to a frame are reflected in the display item of a different, then you need to make sure that either the display item's ComputeInvalidationRegion implementation knows to check for this, or propagate InvalidateFrame() calls up to the drawing frame. | |||
* If you're adding a new display item class, you may want to implement AllocateGeometry/ComputeInvalidationRegion and add a new nsDisplayItemGeometry subclass. Or the provided defaults may work fine. | |||
= Debugging Invalidations Problems = | = Debugging Invalidations Problems = | ||
== Invalidation Logging == | == Invalidation Logging == | ||
Enable | * This requires an --enable-debug or --enable-dump-painting build. | ||
Running with MOZ_DUMP_PAINT_LIST=1 in your environment is recommended to view the display list that is being analyzed by DLBI, but note that this adds a huge amount of extra log data. | * Enable invalidating logging by flipping the nglayout.debug.invalidation pref or setting env MOZ_DUMP_INVALIDATION (or else, prior to v24, defining 'DEBUG_INVALIDATIONS' in view/src/nsViewManager.cpp and layout/base/FrameLayerBuilder.cpp and recompile/link these files). | ||
* Running with MOZ_DUMP_PAINT_LIST=1 (only works if you also built with --enable-dump-painting) in your environment is recommended to view the display list that is being analyzed by DLBI, but note that this adds a huge amount of extra log data. | |||
This should then dump (to | This should then dump (to stderr) all invalidations generated by DLBI, along with the reason. Note that this doesn't include invalidations that come from the layers system (e.g. new layer creation, or layer backing store deleted due to inactivity). | ||
There are five general reasons for invalidation: | There are five general reasons for invalidation: | ||
| Line 48: | Line 64: | ||
* Inactive Layer tree has changed - Inactive LayerManager(0x11a3e8e20) for display item Opacity(0x116bf6560) has an invalid region - invalidating layer 0x119286800 | * Inactive Layer tree has changed - Inactive LayerManager(0x11a3e8e20) for display item Opacity(0x116bf6560) has an invalid region - invalidating layer 0x119286800 | ||
** When we have an inactive layer subtree, DLBI runs on the individual layers (and is logged as such) and we run LayerTreeInvalidation to find the changed area of the layer tree. | ** When we have an inactive layer subtree, DLBI runs on the individual layers (and is logged as such) and we run LayerTreeInvalidation to find the changed area of the layer tree. | ||
Logging Wish List: | Logging Wish List: | ||
| Line 58: | Line 71: | ||
* Convert display item type numbers to names. | * Convert display item type numbers to names. | ||
* View the inactive layer trees created/processed when MOZ_DUMP_PAINT_LIST=1 | * View the inactive layer trees created/processed when MOZ_DUMP_PAINT_LIST=1 | ||
== Under Invalidation == | |||
There are 3 main reasons for not invalidating the correct area: | |||
* Not scheduling a paint | |||
** If you're not getting 'PAINT START' / 'PAINT END' logged in response to the change, then nothing is scheduling a paint. You need to ensure that the changed frame is calling nsIFrame::SchedulePaint (possibly via one of the InvalidateFrame() functions). | |||
* Display item not changed | |||
** If the display item you expect to have changed isn't listed, then DLBI hasn't detected the change. You either need to mark the frame as invalid (using nsIFrame::InvalidateFrame), or check the logic in nsDisplayItem::ComputeInvalidationRegion (virtual!) to make sure that it can detect your change. | |||
* Wrong area invalidated | |||
** If your display item is listed as invalidated, but doesn't cover the right pixels, then this is most likely a bug in your implementation of ComputeInvalidationRegion, GetBounds, GetBorderRect, GetPaddingRect or GetContentRect on your display item. The code calling this is FrameLayerBuilder::InvalidateForLayerChange. | |||
== Other Useful Tools == | == Other Useful Tools == | ||
* Turn on paint flashing pref - nglayout.debug.paint_flashing | * Turn on paint flashing pref - nglayout.debug.paint_flashing | ||