This is the sixth day of my participation in Gwen Challenge

This article has participated in the weekend study program, click to see more details

Let’s start with a summary

After the navigation phase is complete, the render phase is the process of receiving the data, parsing it, and generating the page.

Rendering line

Pipelining can be divided into the following sub-stages: DOM tree building, style calculation, layout stage, layering, drawing, chunking, rasterization, and composition

Focus on:

  • At the beginning each sub-stage has its input;
  • Then each sub-stage has its own process;
  • Eventually each sub-stage generates output.

1. Build a DOM tree

Why build a DOM tree?

This is because HTML cannot be understood and used directly by browsers, so you need to transform the HTML into a structure that browsers can understand — a DOM tree.

The structure of a tree is very much like a “tree” in our real life, where each point is called a node and the connected nodes are called parent nodes. Trees are often used in browsers, for example in the rendering process we will describe below.

As you can see from the figure, the input for building a DOM tree is a very simple HTML file, which is then parsed by an HTML parser and finally outputs the DOM as a tree structure.

You can type document in the console and see the DOM structure. You can see that the DOM is almost identical to the HTML content, but unlike HTML, the DOM is stored in an in-memory tree structure that can be queried or modified using JavaScript.

2. Style calculation

The purpose of style calculation is to calculate the specific style of each element in a DOM node, which can be done in three steps.

  1. Convert CSS to a structure that browsers can understand.

    CSS styles come from three sources:

    • External CSS file referenced by link

    • Just like HTML files, browsers don’t understand the CSS styles of plain text directly, so when the rendering engine receives CSS text, it performs a conversion operation that transforms the CSS text into styleSheets that browsers can understand.

      Type Document.stylesheets into the Chrome Console and you’ll see the structure shown in the image below

       <div align='center'>styleSheets</div>
      Copy the code
  2. Transform property values in the stylesheet to standardize them

    Now that we’ve converted the existing CSS text into a structure that browsers can understand, it’s time to standardize the property values.

    Take the CSS text below

    body { font-size: 2em } p {color:blue; } span {display: none} div {font-weight: bold} div p {color:green; } div {color:red; }Copy the code

    As you can see in the CSS text above, there are many attribute values, such as 2em, Blue and bold. These values are not easily understood by the rendering engine, so you need to convert all values into standardized computed values that the rendering engine can easily understand. This process is called attribute value standardization.

    What does it look like when it’s standardized?

    2em is resolved to 32px, red to RGB (255,0,0), bold to 700…

    The em unit is a relative unit of measure that looks for the font size of the parent tag. Then calculate the font size of their own. Em is several times the font size of the parent tag. The same goes for setting properties such as width or height of a note sheet using em units.

  3. Figure out the specific style of each node in the DOM tree

    Now that the style properties have been standardized, you need to calculate the style properties for each node in the DOM tree. How do you do that?

    This is where CSS inheritance and cascading rules come in.

    The first is CSS inheritance. CSS inheritance is when each DOM node contains the style of its parent node.

    For example, the following CSS text:

    body { font-size: 20px } p {color:blue; } span {display: none} div {font-weight: bold; color:red} div p {color:green; }Copy the code

    The final effect applied to DOM nodes is shown below:

    As you can see from the figure, all child nodes inherit the parent node style. For example, if the font-size property of the body node is 20, then all nodes below the body node will have a font-size of 20.

    Here’s another example of a browser right-clicking on an element:

    Specifically, the UserAgent style, which is a set of default styles provided by the browser, is used by default if you do not provide any styles.

    Cascading is a fundamental feature of CSS. It is an algorithm that defines how to combine property values from multiple sources. It is at the heart of CSS, which is highlighted by its full name, cascading style sheets.

    The purpose of the style calculation stage is to calculate the specific style of each element in the DOM node. In the calculation process, two rules of CSS inheritance and cascading need to be observed. The final output of this phase is the style of each DOM node, stored in the ComputedStyle structure.

    If you want to see how each DOM element ends up Computed, open Chrome’s Developer Tools, select the first “Element” TAB, and then the “Computed” child TAB, as shown below:

3. Layout stage

Now, we have the DOM tree and the styles of the elements in the DOM tree, but that’s not enough to display the page because we don’t yet know the geometry of the DOM elements. The next step is to figure out the geometry of the visible elements in the DOM tree, a process we call layout.

  1. Creating a layout tree

    DOM trees have many invisible elements, such as the head tag and elements that use the display: None attribute. So before displaying, we need to build an additional element layout tree with only visible elements.

  2. Layout calculation

    Now that we have a complete layout tree, we need to calculate the coordinate positions of the nodes in the layout tree.

    When a layout operation is performed, the result of the layout operation is written back into the layout tree, so the layout tree is both input and output.

4. The layered

Now that we have the layout tree and the exact location of each element calculated, is it time to start drawing the page? Again, the answer is no.

Because there are many complex effects on the page, such as complex 3D transformations, page scrolling, or z-index sorting, the rendering engine also needs to generate a LayerTree for a specific node to make it easier to achieve these effects. If you are familiar with Photoshop, you will easily understand the concept of layers, which are added together to form the final page image.

To visualize what Layers are, open Chrome’s Developer Tools and select the Layers TAB to visualize the Layers on your page, as shown in the following image

You can see that the effect is similar to photoshop layers, layer by layer, and then the final page.

Not every node in the layout tree contains a layer. If a node has no corresponding layer, then the node is subordinate to the parent node’s layer. If the SPAN tags in the image above do not have their own layer, they are subordinate to their parent layer. Eventually, however, each node is directly or indirectly subordinate to a layer.

So what criteria does the rendering engine need to meet to create a new layer for a particular node? Generally, elements that satisfy either of the following two points can be promoted to a separate layer.

First, elements with cascading context attributes are promoted to separate layers. A page is a two-dimensional plane, but a cascading context gives a three-dimensional concept to HTML elements that are distributed along the Z-axis perpendicular to the two-dimensional plane in terms of their attribute priorities. You can use the following image to get a feel for it:

As you can see from the figure, elements with explicitly positioned attributes, elements with transparent attributes defined, elements with CSS filters, and so on, all have cascading context attributes. If you want to learn more about cascading context, you can refer to this article.

Secondly, the places that need to be clipped will also be created as layers. But first you need to understand clipping, combined with the following HTML code:

<style> div { width: 200; height: 200; overflow:auto; background: gray; } </style> <body> <div > <p> So elements that have the property of A cascading context or need to be clipped will be promoted to A separate layer, as you can see below: </p> <p> These layers are organized into a tree structure. </p> <p> Layer trees are created based on the layout tree. To find out which elements need to be in which layers, the rendering engine iterates through the layout tree to create the Update LayerTree. </p> </div> </body>Copy the code

According to the results

In this case, we limit the size of the div to 200 by 200 pixels. There is a lot of text inside the div, and the text will be displayed in more than 200 by 200 pixels. At this point, clipping is generated.

When this clipping happens, the rendering engine creates a separate layer for the text section, and if the scroll bar appears, the scroll bar is promoted to a separate layer.

So an element that has the properties of a cascading context or needs to be clipped to satisfy any of these points can be promoted to a single layer.

5. Layer drawing

After building the layer tree, the rendering engine will render each layer in the tree, so how does the rendering engine render layers? Like drawing, the rendering engine will break up the drawing of a layer into many small drawing instructions, such as drawing a face, eyebrows, and eyes, and then put these instructions into a list of drawings in order

You can also experiment with drawing lists by opening the Layers TAB in developer Tools and selecting the Document layer

In the figure, area 1 is the drawing list of Document. Drag the progress bar in area 2 to reproduce the drawing process of the list.

6. Raster operation

A draw list is simply a list of draw orders and draw instructions that are actually done by the compositing thread in the rendering engine. You can see the relationship between the render main thread and the composition thread in the following image:

As shown above, when the drawing list of layers is ready, the main thread commits the drawing list to the composition thread. How does the composition thread work next?

Usually a page may be large, but the user can only see part of it. We call the part that the user can see the viewport. For example, if you pull down the page, you can only see what’s displayed on your screen. It’s like a slot machine click, and all you see is the last number you get.

In some cases, some layer can be very big, such as some pages you use the scroll bar to scroll to scroll to the bottom for a long time, but through the viewport, users can only see a small portion of the page, so in this case, to draw out all layer content, will generate too much overhead, but also it is not necessary.

For this reason, the composition thread will divide the layer into tiles, which are usually 256×256 or 512×512.

The compositing thread prioritizes bitmap generation based on the blocks near the viewport, and the actual bitmap generation is performed by rasterization. Rasterization refers to the transformation of a map block into a bitmap.

Bitmap: also known as a lattice image or raster image, the smallest unit of the pixel made up of the map

The graph block is the smallest unit for rasterization. The renderer maintains a rasterized thread pool, where all rasterization is performed, as shown below:

Generally, GPU is used to accelerate the generation of bitmaps during rasterization. The process of using GPU to generate bitmaps is called fast rasterization, or GPU rasterization. The generated bitmaps are stored in GPU memory.

As you may recall, GPU operations are run in the GPU process, and if rasterization operations use the GPU, then the final bitmap generation is done in the GPU, which involves cross-process operations. You can refer to the picture below for the specific form:

7. Composition and display

Once all the tiles have been rasterized, the composition thread generates a command to draw the tiles — “DrawQuad” — and submits the command to the browser process.

The browser process has a component called viz that receives DrawQuad commands from the compositing thread, draws its page contents into memory, and displays them on the screen.

At this point, through this series of stages, the HTML, CSS, JavaScript, etc., written by the browser will display a beautiful page.

Summary of rendering pipeline:

Ok, we have now analyzed the entire rendering process, from HTML to DOM, style calculation, layout, layering, drawing, rasterization, composition, and display. Here’s a diagram to summarize the entire rendering process:

  1. The renderer transforms the HTML content into a readable DOM tree structure.
  2. The rendering engine translates CSS styleSheets into styleSheets that browsers can understand, calculating the style of DOM nodes.
  3. Create a layout tree and calculate the layout information for the elements.
  4. Layer the layout tree and generate a hierarchical tree.
  5. Generate a draw list for each layer and submit it to the composition thread.
  6. The composite thread divides the layer into blocks and converts the blocks into bitmaps in the rasterized thread pool.
  7. The composite thread sends the DrawQuad command to the browser process.
  8. The browser process generates the page from the DrawQuad message and displays it on the monitor.