zoukankan      html  css  js  c++  java
  • chromium 绘制 paint 与 合成

    E:devchromiumsrc hird_partylink endererplatformgraphicspaintREADME.md

    Platform paint code

    This directory contains the implementation of display lists and display
    list-based painting, except for code which requires knowledge of core/
    concepts, such as DOM elements and layout objects.

    For information about how the display list and paint property trees are
    generated, see the core paint README file.

    This code is owned by the rendering team.

    Paint artifact

    The CompositeAfterPaint paint artifact consists of a list of
    display items in paint order (ideally mostly or all drawings), partitioned into
    paint chunks which define certain paint properties which affect how the
    content should be drawn or composited.

    Paint properties

    Paint properties define characteristics of how a paint chunk should be drawn,
    such as the transform it should be drawn with. To enable efficient updates,
    a chunk's paint properties are described hierarchically. For instance, each
    chunk is associated with a transform node, whose matrix should be multiplied by
    its ancestor transform nodes in order to compute the final transformation matrix
    to the screen.

    See ObjectPaintProperties for
    description of all paint properties that we create for a LayoutObject.

    Paint properties are represented by four paint property trees (transform, clip,
    effect and scroll) each of which contains corresponding type of
    paint property nodes. Each paint property node has a
    pointer to the parent node. The parent node pointers link the paint property
    nodes in a tree.

    Transforms

    Each paint chunk is associated with a transform node,
    which defines the coordinate space in which the content should be painted.

    Each transform node has:

    • a 4x4 TransformationMatrix
    • a 3-dimensional transform origin, which defines the origin relative to which
      the transformation matrix should be applied (e.g. a rotation applied with some
      transform origin will rotate the plane about that point)
    • a boolean indicating whether the transform should be projected into the plane
      of its parent (i.e., whether the total transform inherited from its parent
      should be flattened before this node's transform is applied and propagated to
      children)
    • an integer rendering context ID; content whose transform nodes share a
      rendering context ID should sort together
    • other fields, see the header file

    *** note
    The painting system may create transform nodes which don't affect the position
    of points in the xy-plane, but which have an apparent effect only when
    multiplied with other transformation matrices. In particular, a transform node
    may be created to establish a perspective matrix for descendant transforms in
    order to create the illusion of depth.


    Note that, even though CSS does not permit it in the DOM, the transform tree can
    have nodes whose children do not flatten their inherited transform and
    participate in no 3D rendering context. For example, not flattening is necessary
    to preserve the 3D character of the perspective transform, but this does not
    imply any 3D sorting.

    Clips

    Each paint chunk is associated with a clip node,
    which defines the raster region that will be applied on the canvas when
    the chunk is rastered.

    Each clip node has:

    • A float rect with (optionally) rounded corner radius.
    • An optional clip path if the clip is a clip path.
    • An associated transform node, which the clip rect is based on.

    The raster region defined by a node is the rounded rect and/or clip path
    transformed to the root space, intersects with the raster region defined by its
    parent clip node (if not root).

    Effects

    Each paint chunk is associated with an effect node,
    which defines the effect (opacity, transfer mode, filter, mask, etc.) that
    should be applied to the content before or as it is composited into the content
    below.

    Each effect node has:

    • effects, including opacity, transfer mode, filter, mask, etc.
    • an optional associated clip node which clips the output of the effect when
      composited into the current backdrop.
    • an associated transform node which defines the geometry space of some
      geometry-related effects (e.g. some filters).

    The hierarchy in the effect tree defines the dependencies between
    rasterization of different contents.

    One can imagine each effect node as corresponding roughly to a bitmap that is
    drawn before being composited into another bitmap, though for implementation
    reasons this may not be how it is actually implemented.

    Scrolling

    Each paint chunk is associated with a scroll node
    which defines information about how a subtree scrolls so threads other than the
    main thread can perform scrolling. Scroll information includes:

    • Which directions, if any, are scrollable by the user.
    • A reference to a transform node which contains
      a 2d scroll offset.
    • The extent that can be scrolled. For example, an overflow clip of size 7x9
      with scrolling contents of size 7x13 can scroll 4px vertically and none
      horizontally.

    To ensure geometry operations are simple and only deal with transforms, the
    scroll offset is stored as a 2d transform in the transform tree.

    Display items

    A display item is the smallest unit of a display list in Blink. Each display
    item is identified by an ID consisting of:

    • an opaque pointer to the display item client that produced it
    • a type (from the DisplayItem::Type enum)

    In practice, display item clients are generally subclasses of LayoutObject,
    but can be other Blink objects which get painted, such as inline boxes and drag
    images.

    *** note
    It is illegal for there to be two display items with the same ID in a display
    item list, except for display items that are marked uncacheable
    (see DisplayItemCacheSkipper).


    Generally, clients of this code should use stack-allocated recorder classes to
    emit display items to a PaintController (using GraphicsContext).

    Standalone display items

    DrawingDisplayItem

    Holds a PaintRecord which contains the paint operations required to draw some
    atom of content.

    GraphicsLayerDisplayItem

    Placeholder for GraphicsLayers allocated by the pre-CompositeAfterPaint
    compositing logic. Each one of these may or may not ultimately produce a
    cc::PictureLayer, depending on the layer squashing mechanism. This class
    becomes obsolete with CompositeAfterPaint.

    ForeignLayerDisplayItem

    Draws an atom of content, but using a cc::Layer produced by some agent outside
    of the normal Blink paint system (for example, a plugin). Since they always map
    to a cc::Layer, they are always the only display item in their paint chunk,
    and are ineligible for squashing with other layers.

    ScrollHitTestDisplayItem

    Placeholder for creating a cc::Layer for scrolling in paint order. Hit testing
    in the compositor requires both property trees (scroll nodes) and a scrollable
    cc::layer in paint order. This should be associated with the scroll
    translation paint property node as well as any overflow clip nodes.

    Paint controller

    Callers use GraphicsContext (via its drawing methods, and its
    paintController() accessor) and scoped recorder classes, which emit items into
    a PaintController.

    PaintController is responsible for producing the paint artifact. It contains
    the current paint artifact, and new display items and paint chunks, which
    are added as content is painted.

    Painters should call PaintController::UseCachedItemIfPossible() or
    PaintController::UseCachedSubsequenceIfPossible() and if the function returns
    true, existing display items that are still valid in the current paint artifact
    will be reused and the painter should skip real painting of the item or subsequence.

    When the new display items have been populated, clients call
    commitNewDisplayItems, which replaces the previous artifact with the new data,
    producing a new paint artifact.

    At this point, the paint artifact is ready to be drawn or composited.

    Paint result caching and invalidation

    See Display item caching
    and Paint invalidation for
    more details about how caching and invalidation are handled in blink core
    module using PaintController API.

    Paint artifact compositor

    PaintArtifactCompositor is
    responsible for consuming the PaintArtifact produced by the PaintController,
    and converting it into a form suitable for the compositor to consume.

    At present, PaintArtifactCompositor creates a cc layer tree, with one layer
    for each paint chunk. In the future, it is expected that we will use heuristics
    to combine paint chunks into a smaller number of layers.

    The owner of the PaintArtifactCompositor (e.g. WebView) can then attach its
    root layer to the overall layer hierarchy to be displayed to the user.

    In the future we would like to explore moving to a single shared property tree
    representation across both cc and
    Blink. See Web Page Geometries for more.

    Raster invalidation

    This is to mark which parts of the composited layers need to be re-rasterized to
    reflect changes of painting, by comparing the current paint artifact against the
    previous paint artifact. It's the last step of painting.

    It's done in two levels:

    • Paint chunk level RasterInvalidator: matches each
      paint chunk in the current paint artifact against the corresponding paint
      chunk in the previous paint artifact, by matching their ids. There are
      following cases:

      • A new paint chunk doesn't match any old paint chunk (appearing): The bounds
        of the new paint chunk in the composited layer will be fully raster
        invalidated.

      • An old paint chunk doesn't match any new paint chunk (disappearing): The
        bounds of the old paint chunk in the composited layer will be fully raster
        invalidated.

      • A new paint chunk matches an old paint chunk:

        • The new paint chunk is moved backward (reordering): this may expose other
          chunks that was previously covered by it: Both of the old bounds and the
          new bounds will be fully raster invalidated.

        • Paint properties of the paint chunk changed:

          • If only clip changed, the difference between the old bounds and
            the new bounds will be raster invalidated (i.e. do incremental
            invalidation).

          • Otherwise, both of the old bounds and the new bounds will be fully
            raster invalidated.

        • Otherwise, check for changed display items within the paint chunk.

    • Display item level DisplayItemRasterInvalidator:
      This is executed when a new chunk matches an old chunk in-order and paint
      properties didn't change. The algorithm checks changed display items within a
      paint chunk.

      • Similar to the paint chunk level, the visual rects (mapped to the space of
        the composited layer) of appearing, disappearing, reordering display items
        are fully raster invalidated.

      • If a new paint chunk in-order matches an old paint chunk, if the display
        item client has been paint invalidated,
        we will do full raster invalidation (which invalidates the old visual rect
        and the new visual rect in the composted layer) or incremental raster
        invalidation (which invalidates the difference between the old visual rect
        and the new visual rect) according to the paint invalidation reason.

    Geometry routines

    The GeometryMapper is responsible for efficiently computing
    visual and transformed rects of display items in the coordinate space of ancestor
    PropertyTreeStates.

    The transformed rect of a display item in an ancestor PropertyTreeState is
    that rect, multiplied by the transforms between the display item's
    PropertyTreeState and the ancestors, then flattened into 2D.

    The visual rect of a display item in an ancestor PropertyTreeState is the
    intersection of all of the intermediate clips (transformed in to the ancestor
    state), with the display item's transformed rect.

    renderer/core/paint

    The code in this directory converts the LayoutObject tree into an efficient
    rendering format for the compositor (a list of cc::Layers containing display
    item lists, and associated cc::PropertyTrees). For a high level overview, see
    the Overview section.

    For information about how the display list and paint property trees are
    implemented, see
    the platform paint README file.

    This code is owned by the
    rendering team.

    Glossaries

    Stacked elements and stacking contexts

    This chapter is basically a clarification of CSS 2.1 appendix E. Elaborate
    description of Stacking Contexts
    .

    Note: we use 'element' instead of 'object' in this chapter to keep consistency
    with the spec. We use 'object' in other places in this document.

    According to the documentation, we can have the following types of elements that
    are treated in different ways during painting:

    • Stacked objects: objects that are z-ordered in stacking contexts, including:

      • Stacking contexts: elements with non-auto z-indices or other properties
        that affect stacking e.g. transform, opacity, blend-mode.

      • Replaced normal-flow stacking elements:
        replaced elements
        that do not have non-auto z-index but are stacking contexts for elements
        below them. Right now the only example is SVG <foreignObject>. The
        difference between these elements and regular stacking contexts is that
        they paint in the foreground phase of the painting algorithm (as opposed
        to the positioned descendants phase).

      • Elements that are not real stacking contexts but are treated as stacking
        contexts but don't manage other stacked elements. Their z-ordering are
        managed by real stacking contexts. They are positioned elements with
        z-index: auto (E.2.8 in the documentation).

        They must be managed by the enclosing stacking context as stacked
        elements because z-index:auto and z-index:0 are considered equal for
        stacking context sorting and they may interleave by DOM order.

        The difference of a stacked element of this type from a real stacking
        context is that it doesn't manage z-ordering of stacked descendants.
        These descendants are managed by the parent stacking context of this
        stacked element.

      "Stacked element" is not defined as a formal term in the documentation, but
      we found it convenient to use this term to refer to any elements
      participating z-index ordering in stacking contexts.

      A stacked element is represented by a PaintLayerStackingNode associated
      with a PaintLayer. It's painted as self-painting PaintLayers by
      PaintLayerPainter
      by executing all of the steps of the painting algorithm explained in the
      documentation for the element. When painting a stacked element of the second
      type, we don't paint its stacked descendants which are managed by the parent
      stacking context.

    • Non-stacked pseudo stacking contexts: elements that are not stacked, but
      paint their descendants (excluding any stacked contents) as if they created
      stacking contexts. This includes

      • inline blocks, inline tables, inline-level replaced elements
        (E.2.7.2.1.4 in the documentation)
      • non-positioned floating elements (E.2.5 in the documentation)
      • flex items
      • grid items
      • custom scrollbar parts

      They are painted by ObjectPainter::paintAllPhasesAtomically() which
      executes all of the steps of the painting algorithm explained in the
      documentation, except ignores any descendants which are positioned or have
      non-auto z-index (which is achieved by skipping descendants with
      self-painting layers).

    • Other normal elements.

    Other glossaries

    • Paint container: the parent of an object for painting, as defined by
      CSS2.1 spec for painting. For
      regular objects, this is the parent in the DOM. For stacked objects, it's
      the containing stacking context-inducing object.

    • Paint container chain: the chain of paint ancestors between an element and
      the root of the page.

    • Compositing container: an implementation detail of Blink, which uses
      PaintLayers to represent some layout objects. It is the ancestor along the
      paint ancestor chain which has a PaintLayer. Implemented in
      PaintLayer::compositingContainer(). Think of it as skipping intermediate
      normal objects and going directly to the containing stacked object.

    • Compositing container chain: same as paint chain, but for compositing
      container.

    • Paint invalidation container: the nearest object on the compositing
      container chain which is composited. CompositeAfterPaint doesn't have this
      concept.

    • Visual rect: the bounding box of all pixels that will be painted by a
      for a display item
      It's in the space of the containing transform property node (see Building
      paint property trees
      ). It's calculated
      during paint for each display item.

    • Isolation nodes/boundary: In certain situations, it is possible to put in
      place a barrier that isolates a subtree from being affected by its
      ancestors. This barrier is called an isolation boundary and is implemented
      in the property trees as isolation nodes that serve as roots for any
      descendant property nodes. Currently, the contain: paint css property
      establishes an isolation boundary.

    • Local property tree state: the PropertyTreeState associated with each
      fragment. All fragments have a well-defined local property tree state.
      This is often cached in the LocalBorderBoxProperties
      struct that belongs to FragmentData. Some FragmentData objects don't
      have a LocalBorderBoxProperties, but that is merely a memory optimization.

    Overview

    The primary responsibility of this directory is to convert the outputs from
    layout (the LayoutObject tree) to the inputs of the compositor
    (the cc::Layer list, which contains display items, and the associated
    cc::PropertyNodes).

    This process is done in the following document lifecycle phases:

    • Compositing update (kInCompositingUpdate, kCompositingInputsClean)
    • PrePaint (kInPrePaint)
    • Paint (kInPaint)
      • Walks the LayoutObject tree and creates a display item list.
      • Groups the display list into paint chunks which share the same
        property tree state.
      • Commits the results to the compositor.
        * CompositeAfterPaint
        will decide layerization at this point.
        * Passes the paint chunks to the compositor in a cc::Layer list.
        * Converts the blink property tree nodes into cc property tree nodes.

    Compositing decisions are currently made before paint (see
    Current compositing algorithm)
    but there is an in-progress refactoring to make compositing decisions after
    paint (see
    CompositeAfterPaint). The
    most recent step towards CompositeAfterPaint was a project called
    BlinkGenPropertyTrees
    which uses the compositing decisions from the current compositor
    (PaintLayerCompositor, which produces GraphicsLayers) with the new
    CompositeAfterPaint compositor (PaintArtifactCompositor). This is done by a step
    at the end of paint which collects all painted GraphicsLayers as a list of
    GraphicsLayerDisplayItems.
    Additionaly, ForeignLayerDisplayItems are used for cc::Layers managed outside blink (e.g.,
    video layers, plugin layers) and are treated as opaque composited content by
    the PaintArtifactCompositor. This approach starts using
    much of the new PaintArtifactCompositor logic (e.g., converting blink property
    trees to cc property trees) without changing how compositing decisions are made.

    Debugging blink objects
    has information about dumping the paint and compositing datastructures for
    debugging.

    Current compositing algorithm (CompositeBeforePaint)

    The current compositing system chooses which LayoutObjects paint into their
    own composited backing texture. This is called "having a compositing trigger".
    These textures correspond to GraphicsLayers. There are also additional
    GraphicsLayers which represent property tree-related effects.

    All elements which do not have a compositing trigger paint into the texture
    of the nearest LayoutObjectwith a compositing trigger on its
    compositing container chain (except for squashed layers; see below). For
    historical, practical and implementation detail reasons, only LayoutObjects
    with PaintLayers can have a compositing trigger. See
    crbug.com/370604 for a bug tracking this limitation,
    which is often referred to as the fundamental compositing bug.

    The various compositing triggers are listed in
    compositing_reasons.h and fall
    in to several categories:

    1. Direct reasons due to CSS style (see CompositingReason::kComboAllDirectStyleDeterminedReasons)
    2. Direct reasons due to other conditions (see CompositingReason::kComboAllDirectNonStyleDeterminedReasons)
    3. Composited scrolling-dependent reasons (see CompositingReason::kComboAllCompositedScrollingDeterminedReasons)
    4. Composited descendant-dependent reasons (see CompositingReason::kComboCompositedDescendants)
    5. Overlap-dependent reasons (See CompositingReasons::kComboSquashableReasons)

    The triggers have no effect unless PaintLayerCompositor::CanBeComposited
    returns true.

    Category (1) always triggers compositing of a LayoutObject based on its own
    style. Category (2) triggers based on the LayoutObject's style, its DOM
    ancestors, and whether it is a certain kind of frame root. Category (3)
    triggers based on whether composited scrolling applies to the LayoutObject,
    or the LayoutObject moves relative to a composited scroller (position: fixed
    or position: sticky). Category (4) triggers if there are any stacking
    descendants of the LayoutObject that end up composited. Category 5 triggers
    if the LayoutObject paints after and overlaps (or may overlap) another
    composited layer.

    Note that composited scrolling is special. Several ways it is special:

    • Composited descendants do not necessarily cause composited scrolling of an
      ancestor.
    • The presence of LCD text prevents composited scrolling in the
      absence of other overriding triggers.
    • Local frame roots always use
      composited scrolling if they have overflow.
    • Non-local frame roots use
      composited scrolling if they have overflow and any composited descendants.
    • Composited scrolling is indicated by a bit on PaintLayerScrollableArea, not
      a direct compositing reason. This bit is then transformed into a compositing
      reason from category (3) during the CompositingRequirementsUpdater

    Note that overlap triggers have two special behaviors:

    • Any LayoutObject
      which may overlap a LayoutObject that uses composited scrolling or a
      transform animation, paints after it, and scrolls with respect to it, receives
      an overlap trigger. In some cases this trigger is too aggressive.
    • Inline CSS
      transform is treated as if it was a transform animation. (This is a heuristic
      to speed up the compositing step but leads to more composited layers.)

    The sequence of work during the DocumentLifecycle to compute these triggers
    is as follows:

    • kInStyleRecalc: compute (1) and most of (4) by calling
      CompositingReasonFinder::PotentialCompositingReasonsFromStyle and caching
      the result on PaintLayer, accessible via
      PaintLayer::PotentialCompositingReasonsFromStyle. Dirty bits in
      StyleDifference determine whether this has to be re-computed on a particular
      lifecycle update.
    • kInCompositingUpdate: compute (2) CompositingInputsUpdater. Also
      set the composited scrolling bit on PaintLayerScrollableArea if applicable.
    • kCompositingInputsClean: compute (3), the rest of (4), and (5), in
      CompositingRequirementsUpdater

    The flow of data from the LayoutObject tree to the cc::Layer list and cc
    property trees is described below:

    from layout
      |
      v
    +------------------------------+
    | LayoutObject/PaintLayer tree |-----------+
    +------------------------------+           |
      |                                        |
      | PaintLayerCompositor::UpdateIfNeeded() |
      |   CompositingInputsUpdater::Update()   |
      |   CompositingLayerAssigner::Assign()   |
      |   GraphicsLayerUpdater::Update()       | PrePaintTreeWalk::Walk()
      |   GraphicsLayerTreeBuilder::Rebuild()  |   PaintPropertyTreeBuider::UpdatePropertiesForSelf()
      v                                        |
    +--------------------+                   +------------------+
    | GraphicsLayer tree |<------------------|  Property trees  |
    +--------------------+                   +------------------+
          |                                    |              |
          |<-----------------------------------+              |
          | LocalFrameView::PaintTree()                       |
          |   LocalFrameView::PaintGraphicsLayerRecursively() |
          |     GraphicsLayer::Paint()                        |
          |       CompositedLayerMapping::PaintContents()     |
          |         PaintLayerPainter::PaintLayerContents()   |
          |           ObjectPainter::Paint()                  |
          v                                                   |
        +---------------------------------+                   |
        | DisplayItemList/PaintChunk list |                   |
        +---------------------------------+                   |
          |                                                   |
          |<--------------------------------------------------+
          | PaintChunksToCcLayer::Convert()                   |
          v                                                   |
    +--------------------------------------------------+      |
    | GraphicsLayerDisplayItem/ForeignLayerDisplayItem |      |
    +--------------------------------------------------+      |
      |                                                       |
      |    LocalFrameView::PushPaintArtifactToCompositor()    |
      |         PaintArtifactCompositor::Update()             |
      +--------------------+       +--------------------------+
                           |       |
                           v       v
            +----------------+  +-----------------------+
            | cc::Layer list |  |   cc property trees   |
            +----------------+  +-----------------------+
                    |              |
      +-------------+--------------+
      | to compositor
      v
    

    Debugging blink objects
    has information about dumping these paint and compositing datastructures for
    debugging.

    New compositing algorithm (CompositeAfterPaint)

    This is a new mode under development. In this mode, layerization decisions are
    made after paint.

    The process starts with pre-paint to generate property trees. During paint,
    each generated display item will be associated with a property tree state.
    Adjacent display items having the same property tree state will be grouped as
    PaintChunk. The list of paint chunks then will be processed by
    PaintArtifactCompositor for layerization. Property nodes that will be
    composited are converted into cc property nodes, while non-composited property
    nodes are converted into meta display items by PaintChunksToCcLayer.

    from layout
      |
      v
    +------------------------------+
    | LayoutObject/PaintLayer tree |
    +------------------------------+
      |     |
      |     | PrePaintTreeWalk::Walk()
      |     |   PaintPropertyTreeBuider::UpdatePropertiesForSelf()
      |     v
      |   +--------------------------------+
      |<--|         Property trees         |
      |   +--------------------------------+
      |                                  |
      | LocalFrameView::PaintTree()      |
      |   FramePainter::Paint()          |
      |     PaintLayerPainter::Paint()   |
      |       ObjectPainter::Paint()     |
      v                                  |
    +---------------------------------+  |
    | DisplayItemList/PaintChunk list |  |
    +---------------------------------+  |
      |                                  |
      |<---------------------------------+
      | LocalFrameView::PushPaintArtifactToCompositor()
      |   PaintArtifactCompositor::Update()
      |
      +---+---------------------------------+
      |   v                                 |
      | +----------------------+            |
      | | Chunk list for layer |            |
      | +----------------------+            |
      |   |                                 |
      |   | PaintChunksToCcLayer::Convert() |
      v   v                                 v
    +----------------+ +-----------------------+
    | cc::Layer list | |   cc property trees   |
    +----------------+ +-----------------------+
      |                  |
      +------------------+
      | to compositor
      v
    

    Debugging blink objects
    has information about dumping these paint and compositing datastructures for
    debugging.

    Comparison of the current and new compositing algorithms

    The
    current compositing design
    is an incremental step towards the new
    CompositeAfterPaint design
    and was launched as BlinkGenPropertyTrees. The design before
    BlinkGenPropertyTrees is not described in this document.

    Current (CompositeBeforePaint) New (CompositeAfterPaint)
    REF::CompositeAfterPaintEnabled False True
    Layerization PaintLayerCompositor, CompositedLayerMapping PaintArtifactCompositor
    PaintController One per GraphicsLayer One per LocalFrameView

    PrePaint

    PrePaintTreeWalk

    During the InPrePaint document lifecycle state, this class is called to walk
    the whole layout tree, beginning from the root FrameView, and across frame
    boundaries. This is an in-order tree traversal which is important for
    efficiently computing DOM-order hierarchy such as the parent containing block.

    The PrePaint walk has two primary goals:
    paint invalidation and
    building paint property trees.

    Paint invalidation

    PaintInvalidator

    Paint invalidator marks anything that need to be painted differently from the
    original cached painting.

    During the document lifecycle stages prior to PrePaint, objects are marked for
    needing paint invalidation checking if needed by style change, layout change,
    compositing change, etc. In PrePaint stage, we traverse the layout tree in
    pre-order, crossing frame boundaries, for marked subtrees and objects and
    invalidate display item clients that will generate different display items.

    At the beginning of the PrePaint tree walk, a root PaintInvalidatorContext
    is created for the root LayoutView. During the tree walk, one
    PaintInvalidatorContext is created for each visited object based on the
    PaintInvalidatorContext passed from the parent object. It tracks the following
    information to provide O(1) complexity access to them if possible:

    • Paint invalidation container (Slimming Paint v1 only): As described by
      the definitions in Other glossaries, the paint
      invalidation container for stacked objects can differ from normal objects,
      we have to track both separately. Here is an example:

      <div style="overflow: scroll">
          <div id=A style="position: absolute"></div>
          <div id=B></div>
      </div>
      

      If the scroller is composited (for high-DPI screens for example), it is the
      paint invalidation container for div B, but not A.

    • Painting layer: the layer which will initiate painting of the current
      object. It's the same value as LayoutObject::PaintingLayer().

    PaintInvalidator initializes PaintInvalidatorContext
    for the current object, then calls LayoutObject::InvalidatePaint() which
    calls the object's paint invalidator (e.g. BoxPaintInvalidator) to complete
    paint invalidation of the object.

    Paint invalidation of text

    Text is painted by InlineTextBoxPainter using InlineTextBox as display
    item client. Text backgrounds and masks are painted by InlineTextFlowPainter
    using InlineFlowBox as display item client. We should invalidate these display
    item clients when their painting will change.

    LayoutInlines and LayoutTexts are marked for full paint invalidation if
    needed when new style is set on them. During paint invalidation, we invalidate
    the InlineFlowBoxs directly contained by the LayoutInline in
    LayoutInline::InvalidateDisplayItemClients() and InlineTextBoxs contained by
    the LayoutText in LayoutText::InvalidateDisplayItemClients(). We don't need
    to traverse into the subtree of InlineFlowBoxs in
    LayoutInline::InvalidateDisplayItemClients() because the descendant
    InlineFlowBoxs and InlineTextBoxs will be handled by their owning
    LayoutInlines and LayoutTexts, respectively, when changed style is
    propagated.

    Specialty of ::first-line

    ::first-line pseudo style dynamically applies to all InlineBox's in the
    first line in the block having ::first-line style. The actual applied style is
    computed from the ::first-line style and other applicable styles.

    If the first line contains any LayoutInline, we compute the style from the
    ::first-line style and the style of the LayoutInline and apply the computed
    style to the first line part of the LayoutInline. In Blink's style
    implementation, the combined first line style of LayoutInline is identified
    with kPseudoIdFirstLineInherited.

    The normal paint invalidation of texts doesn't work for first line because:

    • ComputedStyle::VisualInvalidationDiff() can't detect first line style
      changes;
    • The normal paint invalidation is based on whole LayoutObject's, not aware of
      the first line.

    We have a special path for first line style change: the style system informs the
    layout system when the computed first-line style changes through
    LayoutObject::FirstLineStyleDidChange(). When this happens, we invalidate all
    InlineBoxes in the first line.

    Building paint property trees

    PaintPropertyTreeBuilder

    This class is responsible for building property trees
    (see
    platform/paint/README.md
    for information about what property trees are).

    Each PaintLayer's LayoutObject has one or more FragmentData objects (see
    below for more on fragments). Every FragmentData has an
    ObjectPaintProperties object if any property nodes are induced by it. For
    example, if the object has a transform, its ObjectPaintProperties::Transform()
    field points at the TransformPaintPropertyNode representing that transform.

    The NeedsPaintPropertyUpdate, SubtreeNeedsPaintPropertyUpdate and
    DescendantNeedsPaintPropertyUpdate dirty bits on LayoutObject control how
    much of the layout tree is traversed during each PrePaintTreeWalk.

    Additionally, some dirty bits are cleared at an isolation boundary. For example
    if the paint property tree topology has changed by adding or removing nodes
    for an element, we typically force a subtree walk for all descendants since
    the descendant nodes may now refer to new parent nodes. However, at an
    isolation boundary, we can reason that none of the descendants of an isolation
    element would be affected, since the highest node that the paint property nodes
    of an isolation element's subtree can reference are the isolation
    nodes established at this element itself.

    Implementation note: the isolation boundary is achieved using alias nodes, which
    are nodes that are put in place on an isolated element for clip, transform, and
    effect trees. These nodes do not themselves contribute to any painted output,
    but serve as parents to the subtree nodes. The alias nodes and isolation nodes
    are synonymous and are used interchangeably. Also note that these nodes are
    placed as children of the regular nodes of the element. This means that the
    element itself is not isolated against ancestor mutations; it only isolates the
    element's subtree.

    Example tree:

                            +----------------------+
                            | 1. Root LayoutObject |
                            +----------------------+
                              /                  
               +-----------------+            +-----------------+
               | 2. LayoutObject |            | 3. LayoutObject |
               +-----------------+            +-----------------+
                 /                              /             
      +-----------------+          +-----------------+    +-----------------+
      | 4. LayoutObject |          | 5. LayoutObject |    | 6. LayoutObject |
      +-----------------+          +-----------------+    +-----------------+
                                     /             
                       +-----------------+     +-----------------+
                       | 7. LayoutObject |     | 8. LayoutObject |
                       +-----------------+     +-----------------+
    

    Suppose that element 3's style changes to include a transform (e.g.
    transform: translateX(10px)).

    Typically, here is the order of the walk (depth first) and updates:

    • Root element 1 is visited since some descendant needs updates
    • Element 2 is visited since it is one of the descendants, but it doesn't
      need updates.
    • Element 4 is skipped since the above step didn't need to recurse.
    • Element 3 is visited since it's a descendant of the root element, and its
      property trees are updated to include a new transform. This causes a flag
      to be flipped that all subtree nodes need an update.
    • Elements are then visited in depth order: 5, 7, 8, 6. Elements 5 and 6
      reparent their transform nodes to point to the transform node of element 3.
      Elements 7 and 8 are visited and updated but no changes occur.

    Now suppose that element 5 has "contain: paint" style, which establishes an
    isolation boundary. The walk changes in the following way:

    • Root element 1 is visited since some descendant needs updates
    • Element 2 is visited since it is one of the descendants, but it doesn't
      need updates.
    • Element 4 is skipped since the above step didn't need to recurse.
    • Element 3 is visited since it's a descendant of the root element, and its
      property trees are updated to include a new transform. This causes a flag
      to be flipped that all subtree nodes need an update.
    • Element 5 is visited and updated by reparenting the transform nodes.
      However, now the element is an isolation boundary so elements 7 and 8 are
      not visited (i.e. the forced subtree update flag is ignored).
    • Element 6 is visited as before and is updated to reparent the transform
      node.

    Note that there are subtleties when deciding whether we can skip the subtree
    walk. Specifically, not all subtree walks can be stopped at an isolation
    boundary. For more information, see
    PaintPropertyTreeBuilder and its use of
    IsolationPiercing vs IsolationBlocked subtree update reasons.

    Fragments

    In the absence of multicolumn/pagination, there is a 1:1 correspondence between
    LayoutObjects and FragmentData. If there is multicolumn/pagination,
    there may be more FragmentDatas. If a LayoutObject has a property node,
    each of its fragments will have one. The parent of a fragment's property node is
    the property node that belongs to the ancestor LayoutObject which is part of
    the same column. For example, if there are 3 columns and both a parent and child
    LayoutObject have a transform, there will be 3 FragmentData objects for
    the parent, 3 for the child, each FragmentData will have its own
    TransformPaintPropertyNode, and the child's ith fragment's transform will
    point to the ith parent's transform.

    Each FragmentData receives its own ClipPaintPropertyNode. They
    also store a unique PaintOffset, PaginationOffset and
    LocalBorderBoxProperties object.

    See
    LayoutMultiColumnFlowThread.h
    for a much more detail about multicolumn/pagination.

    Paint

    Paint walks the LayoutObject tree in paint-order and produces a list of
    display items. This is implemented using static painter classes
    (e.g., BlockPainter) and appends display items to a
    PaintController. During
    this treewalk, the current property tree state is maintained (see:
    PaintController::UpdateCurrentPaintChunkProperties). The PaintController
    segments the display item list into
    PaintChunks which are
    sequential display items that share a common property tree state.

    With the
    current compositing algorithm,
    the paint-order LayoutObject treewalk is initiated by GraphicsLayers, and
    each GraphicsLayer contains a PaintController. In the new compositing
    approach,
    CompositeAfterPaint, there
    is only one PaintController for the entire LocalFrameView.

    Paint result caching

    PaintController holds the previous painting result as a cache of display
    items. If some painter would generate results same as those of the previous
    painting, we'll skip the painting and reuse the display items from cache.

    Display item caching

    When a painter would create a DrawingDisplayItem exactly the same as the
    display item created in the previous painting, we'll reuse the previous one
    instead of repainting it.

    Subsequence caching

    When possible, we create a scoped SubsequenceRecorder in
    PaintLayerPainter::PaintContents() to record all display items generated in
    the scope as a "subsequence". Before painting a layer, if we are sure that the
    layer will generate exactly the same display items as the previous paint, we'll
    get the whole subsequence from the cache instead of repainting them.

    There are many conditions affecting whether we need to generate subsequence for
    a PaintLayer and whether we can use cached subsequence for a PaintLayer. See
    ShouldCreateSubsequence() and shouldRepaintSubsequence() in
    PaintLayerPainter.cpp for the conditions.

    Empty paint phase optimization

    During painting, we walk the layout tree multiple times for multiple paint
    phases. Sometimes a layer contain nothing needing a certain paint phase and we
    can skip tree walk for such empty phases. Now we have optimized
    PaintPhaseDescendantOutlinesOnly and PaintPhaseFloat for empty paint phases.

    During paint invalidation, we set the containing self-painting layer's
    NeedsPaintPhaseXXX flag if the object has something needing to be painted in
    the paint phase.

    During painting, we check the flag before painting a paint phase and skip the
    tree walk if the flag is not set.

    When layer structure changes, and we are not invalidate paint of the changed
    subtree, we need to manually update the NeedsPaintPhaseXXX flags. For example,
    if an object changes style and creates a self-painting-layer, we copy the flags
    from its containing self-painting layer to this layer, assuming that this layer
    needs all paint phases that its container self-painting layer needs.

    Hit test information recording

    Hit testing is done in paint-order, and to preserve this information the paint
    system is re-used to record hit test information when painting the background.
    This information is then used in the compositor to implement cc-side hit
    testing. Hit test information is recorded even if there is no painted content.

    We record different types of hit test information in the following data
    structures:

    1. Paint chunk bounds

      The bounds of the current paint chunk are expanded to ensure the bounds
      contain the hit testable area.

    2. HitTestData::touch_action_rects

      Used for touch action rects
      which are areas of the page that allow certain gesture effects, as well as
      areas of the page that disallow touch events due to blocking touch event
      handlers.

    3. HitTestData::wheel_event_rects

      Used for wheel event handler regions
      which are areas of the page that disallow default wheel event processing
      due to blocking wheel event handlers.

    4. HitTestData::scroll_translation
      and
      HitTestData::scroll_hit_test_rect

      Used to create
      non-fast scrollable regions
      to prevent compositor scrolling of non-composited scrollers, plugins with
      blocking scroll event handlers, and resize handles.

      If scroll_translation is not null, this is also used for
      CompositeAfterPaint to force a special cc::Layer that is marked as being
      scrollable when composited scrolling is needed for the scroller.

    Scrollbar painting

    For now in pre-CompositeAfterPaint, we have distinct paths for composited
    scrollbars and non-composited scrollbars. For a composited scrollbar,
    PaintArtifactCompositor creates a GraphicsLayer, then ScrollingCoordinator
    creates the cc scrollbar layer which is set as the content layer of the
    GraphicsLayer. For a non-composited scrollbar, ScrollableAreaPainter paints
    the scrollbar into various drawing display items.

    In CompositeAfterPaint, during painting, for a non-custom scrollbar we create a
    ScrollbarDisplayItem
    which contains a cc::Scrollbar and other
    information that are needed to actually paint the scrollbar into a paint record
    or to create a cc scrollbar layer. During PaintArtifactCompositor update,
    we decide whether to composite the scrollbar and, if not composited, actually
    paint the scrollbar as a paint record, otherwise create a cc scrollbar layer
    of type cc::SolidColorScrollbarLayer, cc::PaintedScrollbarLayer or
    cc::PaintedOverlayScrollbarLayer depending on the type of the scrollbar.

    In CompositeAfterPaint, custom scrollbars are still painted into drawing
    display items directly.

    PaintNG

    LayoutNG is a project that will change how Layout
    generates geometry/style information for painting. Instead of modifying
    LayoutObjects, LayoutNG will generate an NGFragment tree.

    NGPaintFragments are:

    • immutable
    • all coordinates are physical. See
      layout_box_model_object.h.
    • instead of Location(), NGFragment has Offset(), a physical offset from parent
      fragment.

    The goal is for PaintNG to eventually paint from NGFragment tree,
    and not see LayoutObjects at all. Until this goal is reached,
    LegacyPaint, and NGPaint will coexist.

    When a particular LayoutObject subclass fully migrates to NG, its LayoutObject
    geometry information might no longer be updated(*), and its
    painter needs to be rewritten to paint NGFragments.
    For example, see how BlockPainter is being rewritten as NGBoxFragmentPainter.

  • 相关阅读:
    每日口语(6.12)
    The usage of thumb
    Chart相关网站
    每日口语(6.14)
    我为世界杯狂
    一个很简单的javascript问题,看你能否答对
    【转】理解伪元素:Before和:After
    JS BOM之location.hash详解
    JS BOM之location对象
    JS BOM之location.hash的用法
  • 原文地址:https://www.cnblogs.com/bigben0123/p/14963861.html
Copyright © 2011-2022 走看看