|
|
| Line 59: |
Line 59: |
| Currently when we paint we only build a display list for the items that intersect the bounding rectangle of the invalid area. Instead let's assume we have to build a display list for the entire visible window area. This is not likely to be a performance problem. This does not mean we actually have to repaint the entire visible window every time, it just means we figure out what would be painted. | | Currently when we paint we only build a display list for the items that intersect the bounding rectangle of the invalid area. Instead let's assume we have to build a display list for the entire visible window area. This is not likely to be a performance problem. This does not mean we actually have to repaint the entire visible window every time, it just means we figure out what would be painted. |
|
| |
|
| Then traversing the display list lets us build a new layer tree. The trick is that we want to identify layers that can be reused, or partially reused, from the previous tree and incorporated into the new tree. (Perhaps we construct the new tree from the old tree by imperative mutation, or perhaps we construct the new tree from scratch in a functional manner.) | | Then traversing the display list lets us (re)build the layer tree. |
|
| |
|
| There are three kinds of layers: | | There are three kinds of layers: |
| Line 84: |
Line 84: |
| *** SVG foreignObject inside arbitrary SVG gunk ... hmm. Maybe if we support all the above, *and* render SVG using display lists (which we currently don't), that would be enough. | | *** SVG foreignObject inside arbitrary SVG gunk ... hmm. Maybe if we support all the above, *and* render SVG using display lists (which we currently don't), that would be enough. |
|
| |
|
| The hard remaining problem is to know how to reuse or update the implicit layers belonging to a container. The content rendered in those layers may have been invalidated. We also need to figure out how to relate the N implicit layers currently associated with the container to the M new implicit layers. For example, if an explicit layer has gone away then M might be less than N, the implicit layers before and after it have "merged". The good news is that any content in the implicit layers that changes will cause the frame for the container to receive an nsIFrame::InvalidateInternal, so we can know the region of the implicit layers that's changed, although it will be hard to know which implicit layers changed ... we can probably just repaint that region of all of them. Proposal: | | The hard remaining problem is to know how to reuse or update the implicit layers belonging to a container. The content rendered in those layers may have been invalidated. Updating the invalid rectangle in each "implicit" layer is not that hard. The hard part is knowing when to create and/or destroy implicit layers because content has changed z-index, or an explicit layer child has been inserted or removed. I think we can do this with special flags to tag invalidations caused by a frame with an explicit layer child being inserted or removed. |
| * Match the explicit layer children that were already children of the container to the explicit layer children in the new display list. They have to be in the same order before and after. (In general there are multiple solutions to this problem. E.g. if we had explicit layers A, B, C before and now we have B, A, C, we can select A, C as matching, or B, C as matching.)
| |
| * Divide up the display list into the runs of consecutive child display items that were not matched in the previous step. For each such run, let's say between explicit layers L1 and L2:
| |
| ** Reuse the old implicit layer children between L1 and L2 for the new implicit layers in this run. It won't matter how they're reassigned as long as they're kept in the same order. Some new layers might need to be created and leftovers destroyed.
| |
| ** Union together the areas covered by explicit layers that were in the container layer between L1 and L2 (exclusive) (these are the old layers that have been removed from this run)
| |
| ** Add the areas covered by explicit layers that are in the display list between L1 and L2 (exclusive) (these are the new layers that have appeared in this run)
| |
| ** Add the areas invalidated by InvalidateInternal as observed by this container layer's frame
| |
| ** Repaint the resulting area in *every* implicit layer in the run. We're done!
| |
| ** The common case should be that the explicit layer children currently in the container are exactly the same list in the same order as the explicit layer children in the new display list, in which case the above steps will find no explicit layer children between L1 and L2 and there will be exactly one implicit layer child in each run.
| |
|
| |
|
| For this to work well we need to be able to distinguish invalidates that need to update implicit layers of a frame with a container layer from other invalidates of that frame. We can do this using an extra invalidation flag, say INVALIDATE_IMPLICIT_LAYER. When a frame with a container layer gets an invalidate from a child with that flag, it adds the invalid area to the region of its implicit layers that needs to be updated, and removes the flag before passing the invalidate upwards.
| | Thought experiment: suppose we have a regular Web page so everything can be rendered in one implicit layer. Then suppose someone inserts a small element with its own layer (say a 3D-transformed button) into the page, or it gets scrolled into view from offscreen. Suddenly the page content splits into two implicit layers, the stuff below the button and the stuff above the button. From the display list we can easily compute the bounding regions of these two layers. If they're both non-empty, then we need to split the old layer into two layers. We need to re-render at least the intersection of the two regions. I think this can be done fairly efficiently, but it will be tricky. |
|
| |
|
| Another thing we'll need for this to work well is to be able to control the size of the implicit layers. Each time we update an implicit layer we can calculate a new bounding-box and resize the implicit layer to that size. Often the size will be 0, but for simplicity it will probably be easier to manipulate zero-size layers than try to eliminate them at the display list level.
| | Implicit layers can also change size, need to be scrolled, etc. |
|
| |
|
| === Old proposal === | | === Old proposal === |