Life of a Pixel 2018

This talk is about how Chrome turns web content into pixels. The entire process is called "rendering".
We'll describe what we mean by content, and what we mean by pixels, and then we'll explain the magic in between.

這個演講主要介紹chrome是如何把web content轉成像素點的,整個過程被稱爲「rendering」。
咱們首先描述什麼叫作content,而後再介紹pixels,而後解釋其中的魔法。前端

clipboard.png

Chrome's architecture is constantly evolving. This talk connects high-level concepts (which change slowly) to specific classes (which change frequently).
The details are based primarily on what is currently shipping in the canary channel (M69), but a few of the biggest future refactorings are mentioned in passing.

chrome的架構在不斷髮展。這個演講將高級概念(變化緩慢)與特定類(常常變化)聯繫起來。細節基於canary(M69),一些比較大的將來的重構也會被提到。web

clipboard.png

"Content" is the generic term in Chromium for all of the code inside a webpage or the frontend of a web application.
It's made of text, markup (surrounding the text), styles (defining how markup is rendered), and script (which can modify all of the above dynamically).
There are other kinds of content, which we won't cover here.

"Content"是最通用的Chromium的術語,指的是網頁內部或者是網絡應用的前端代碼。它由text,markup(環繞於文本),style(決定標記如何渲染),以及script(可以動態地改變上述提到的內容)。同時也有其餘的content,可是咱們在這裏暫時不作介紹。算法

clipboard.png

A real webpage is just thousands of lines of HTML, CSS, and JavaScript delivered in plain text over the network.
There's no notion of compilation or packaging as you might find on other kinds of software platforms - the webpage's source code is the input to the renderer.

一個真實的網頁由成千行的純文本的HTML,CSS以及JavaScript經過網絡提供。你可能在其餘軟件平臺找不到compilation或者packaging的概念,網頁的源代碼是renderer的輸入。chrome

clipboard.png

Architecturally, the "content" namespace in the Chromium C++ codebase is responsible for everything in the red box.
Contrast with tab strip, address bar, navigation buttons, menus, etc. which live outside of "content".
Key to Chrome's security model: rendering happens in a sandboxed process.

從架構上說,」content「在Chromium C++ 代碼的命名空間負責紅框中的全部內容。
對比而言,標籤條,地址欄,導航按鈕,菜單,在」content「以外。
Chrome安全模型的關鍵是,在沙盒進程中進行渲染。api

clipboard.png

At the other end of the pipeline we have to get pixels onto the screen using the graphics libraries provided by the underlying operating system.
On most platforms today, that's a standardized API called "OpenGL". On Windows there's an extra translation into DirectX. In the future, we may support newer APIs such as Vulkan.
These libraries provide low-level graphics primitives like "textures" and "shaders", and let you do things like "draw a polygon at these coordinates into a buffer of virtual pixels". But obviously they don't understand anything about the web or HTML or CSS.

在管道的另外一邊,咱們要利用操做系統下提供的圖形庫把像素點放置在屏幕上。現今,在大多數的平臺上,有一個標準API叫作」OpenGL」。在Windows上,有額外到DirectX的轉換。在未來,咱們會支持新的API(相似Vulkan)。
這些庫提供了低級圖形基元(primitive),相似「紋理(texture)」以及「着色器(shader)」,讓你可以作相似「在這些座標處繪製一個多邊形到虛擬像素緩衝區」這樣的操做。可是顯然他們並不理解任何和HTML和CSS相關的事情。瀏覽器

clipboard.png

So the goal of rendering can be stated as: turn HTML / CSS / JavaScript into the right OpenGL calls to display the pixels.
But keep in mind a second goal as we describe the pipeline: We also want the right intermediate data structures to update the rendering efficiently after it's produced, and answer queries about it from script or other parts of the system.

因此渲染的目標能夠描述爲:將HTML/CSS/JavaScript轉化爲正確的OpenGL的調用來展現像素。
可是要記住,咱們描述這個管道的第二個目標是:咱們一樣想知道正確的中間數據生成後有效地更新,而且能在腳本或者系統的其餘部分回答有關它的查詢。安全

clipboard.png

We break the pipeline into multiple "lifecycle stages", generating those intermediate outputs.
We'll first describe each stage of a working pipeline, then come back to the notion of efficient updating and introduce some concepts for optimization.

咱們將管道分紅多個「生命週期階段」,產生中間輸出。咱們首先描述工做流水線的每一個階段,而後回到有效更新的概念,再介紹優化相關的概念。網絡

clipboard.png

HTML tags impose a semantically meaningful hierarchical structure on the document. For example, a <div> may contain two paragraphs, each with text. So the first step is to parse those tags to build an object model that reflects this structure.

HTML標籤在文檔上強加了語義上有意義的層次結構。 例如,<div>可能包含兩個段落,每一個段落都帶有文本。 所以,第一步是解析這些標籤以構建反映此結構的對象模型。架構

clipboard.png

If you've taken computer science classes you may recognize this as a "tree".

若是你上過計算機科學的課程,那麼你就能認出來它是一棵樹。
clipboard.pngapp

The DOM serves double duty as both the internal representation of the page, and the API exposed to script for querying or modifying the rendering.
The JavaScript engine (V8) exposes DOM web APIs as thin wrappers around the real DOM tree through a system called "bindings".

DOM具備雙重功能,它既能做爲頁面的內部展現,也能做爲查詢和更改呈現的腳本的公開API。Javascript引擎(V8)經過一個系統叫作「bindings」把真實的DOM tree封裝成一個輕量的wrapper。

clipboard.png

Having built the DOM tree, the next step is to process the CSS styles.
A CSS selector selects a subset of DOM elements that its property declarations should apply to.

構建了DOM tree之後,下一步是處理CSS styles。一個CSS選擇器選擇它屬性聲明瞭應當應用的DOM元素的子集。

clipboard.png

Style properties are the knobs by which web authors can influence the rendering of DOM elements.
There are hundreds of style properties.

做者能夠經過Style屬性影響DOM元素的渲染。style屬性有幾百個。

clipboard.png

Furthermore, it's not trivial to determine which elements a style rule selects.
Some elements may be selected by more than one rule, with conflicting declarations for a particular style property.

此外,肯定樣式規則選擇哪些元素並不是易事。
某些元素可能由多個規則選擇,而且具備特定樣式屬性的衝突聲明。

clipboard.png

The layout stage runs after the style recalc stage.
First, the layout tree is constructed. Then, we walk the layout tree, filling in the geometry data, and processing side effects of the geometry.

layout階段在style重計算階段之後進行。首先,layout tree構建,而後咱們遍歷這個layout tree,填充幾何數據,而後處理幾何產生的反作用。

clipboard.png

Today, layout objects contain both inputs and outputs of the layout stage, without a clean separation between them.
For example, the LayoutObject acquires ownership of its element's ComputedStyle object.
A new layout system called LayoutNG is expected to simplify the architecture, and make it easier to build new layout algorithms.

現在,layout對象包括layout階段的輸入和輸出,它們之間的區分沒有那麼清晰。
好比,LayoutObject獲取它元素的 ComputedStyle 對象的全部權。一個新的layout系統叫作LayoutNG,被指望用來簡化架構,構建新的更簡單的layout算法。
clipboard.png

Now that we understand the geometry of our layout objects, it's time to paint them.
Paint records paint operations into a list of display items.
A paint operation might be something like "draw a rectangle at these coordinates, in this color".
There may be multiple display items for each layout object, corresponding to different parts of its visual appearance, like the background, foreground, outline, etc.
This is just a recording that can be played back later. We'll see why that's useful in a bit.

如今咱們理解了layout object的幾何形狀,接下來就是繪製它們。
paint將paint操做記錄爲一列display item。一個paint操做相似於「在這些座標用這個顏色繪製一個矩形」。對於每一個layout object也許有多個display item,對應視覺外觀的不一樣部分,好比背景,前景,輪廓等。~~~

clipboard.png
It's important to paint elements in the right order, so that they stack correctly when they overlap.
The order can be controlled by style.
以正確的順序paint element很是重要,只有這樣才能在元素覆蓋的時候正常顯示。這個順序能被style所控制。

clipboard.png

It's even possible for an element to be partly in front of and partly behind another element.
That's because paint runs in multiple phases, and each paint phase does its own traversal of a subtree.

一個元素部分在另一個元素的前面或者後面是可能的。由於paint在不一樣階段運行,每次的paint階段作了本身子樹的遍歷。

clipboard.png

The paint operations in the display item list are executed by a process called rasterization.
Each cell in the resulting bitmap holds values for four color channels.

在display item列表上進行paint操做被稱爲rasterization(光柵化)。位圖上的每一個像素點存着四個顏色通道的值。

clipboard.png

The rastered bitmap is stored in memory, typically GPU memory referenced by an OpenGL texture object.
The GPU can also run the commands that produce the bitmap ("accelerated rasterization").
Note that these pixels are not yet on the screen!

光柵化的位圖在內存中存儲,一般是被OpenGL紋理對象引用的GPU內存。
GPU可以運行產生位圖的命令(「加速光柵化」)
注意到此時像素並不在屏幕上。
clipboard.png

Rasterization issues OpenGL calls through a library called Skia. Skia provides a layer of abstraction around the hardware, and understands more complex things like paths and Bezier curves.
Skia is open-source and maintained by Google. It ships in the Chrome binary but lives in a separate code repository. It's also used by other products such as the Android OS.
Skia's GPU-accelerated codepath builds its own buffer of drawing operations, which is flushed at the end of the raster task.

Rasterization經過一個Skia的庫產生OpenGL調用,Skia圍繞硬件提供了一層抽象,能理解相似路徑和貝塞爾曲線等更復雜的事情。
Skia開源且由谷歌維護。它附帶在chrome二進制文件中,可是屬於一個單獨的代碼庫,同時也被其餘產品,好比安卓系統使用。
Skia的GPU加速代碼路徑構建了它獨立的繪製操做緩衝區,它會在光柵化任務結束的時候刷新。

clipboard.png

Recall that the renderer process is sandboxed, so it can't make system calls directly.
GL calls issued by Skia are actually proxied into a different process using a "command buffer".
The GPU process receives the command buffer and issues the "real" GL calls through a set of function pointers.
Besides escaping the renderer sandbox, isolating GL in the GPU process protects us from unstable or insecure graphics drivers.

回顧以前說的渲染進程在沙盒中,因此並不能直接進行系統調用。
Skia發起的GL調用使用「command buffer」被代理給了另外一個不一樣的進程。
GPU進程接受command buffer而後經過函數指針發起「真正」的GL調用。
逃離沙盒進程,GPU進程中獨立的GL將從不穩定和不安全的圖形驅動中保護咱們。

clipboard.png

Those GL function pointers are initialized by dynamic lookup from the system's shared OpenGL library - or the ANGLE library on Windows.
ANGLE is another library built by Google; its job is to translate OpenGL to DirectX, which is Microsoft's API for accelerated graphics on Windows.
There are also OpenGL drivers for Windows, but historically they have not been very high quality.

這些GL函數指針經過系統的共享OpenGL庫(或Windows上的ANGLE庫)進行動態查找來初始化。
ANGLE是Google創建的另外一個庫; 它的工做是將OpenGL轉換爲DirectX,這是微軟在Windows上加速圖形的API。
Windows也有OpenGL驅動程序,但從歷史上看,它們的質量並不高。

clipboard.png

Moving raster to the GPU process will improve performance.
It's also needed to support Vulkan.
把光柵化移動到GPU進程可以改善性能。它同時須要支持Vulkan

clipboard.png

We have now gone all the way from content to pixels in memory.
But note that the rendering is not static.
Running the full pipeline is expensive
如今咱們已經走完在內存中從content到pixels的全程了。可是渲染自己不是靜態的,走完管道全程老是代價昂貴的。

clipboard.png

Change is modelled as animation frames.
Each frame is a complete rendering of the state of the content at a particular point in time.

clipboard.png

clipboard.png

clipboard.png

clipboard.png

clipboard.png

clipboard.png

clipboard.png

clipboard.png

Certain style properties cause a layer to be created for a layout object.
If a layout object doesn't have a layer, it paints into the layer of the nearest ancestor that has one.
特定的樣式屬性會爲layout對象建立layer。若是一個layout對象自己並無layer,那麼它將被繪製到最近的祖先節點上。

clipboard.png

Building the layer tree is a new lifecycle stage on the main thread. Today, this happens before paint, and each layer is painted separately.

構建layer tree是主線程上的新生命週期階段。現在,這發生在paint以前,每層都是單獨paint的。

clipboard.png

clipboard.png

clipboard.png
After paint is finished, the commit updates a copy of the layer tree on the compositor thread, to match the state of the tree on the main thread.

paint結束後,commit將更新compositor線程上的layer tree的拷貝,以匹配主線程上tree的狀態。

clipboard.png

Recall: raster is the step after paint, which turns paint ops into bitmaps.
Layers can be large - rastering the whole layer is expensive, and unnecessary if only part of it is visible.
So the compositor thread divides the layer into tiles.
Tiles are the unit of raster work. Tiles are rastered with a pool of dedicated raster threads. Tiles are prioritized based on their distance from the viewport.
(Not shown: a layer actually has multiple tilings for different resolutions.)

回想一下:raster在paint以後,它將paint ops轉換爲位圖。
layer可能很大 - 整個layer都光柵化的成本很高,若是隻有部分可見則沒必要要所有光柵化。
所以,compositor線程將layer劃分爲tiles。
tiles是raster work的基本單位。 專門的raster線程池對tiles進行光柵化。 根據tiles與viewport的距離肯定tiles的優先級。
(未顯示:layer實際上有不一樣分辨率的多個tilings。)
clipboard.png

Once all the tiles are rastered, the compositor thread generates "draw quads". A quad is like a command to draw a tile in a particular location on the screen, taking into account all the transformations applied by the layer tree. Each quad references the tile's rastered output in memory (remember, no pixels are on the screen yet).
The quads are wrapped up in a compositor frame object which gets submitted to the browser process.

一旦全部tiles都被光柵化,compositor線程就會生成「draw quads」。 quads相似一個命令,考慮了圖層樹應用的全部變換在屏幕上的特定位置繪製tile。 每一個quads在內存中引用了tile的光柵輸出(請記住,屏幕上尚未像素)。
quads被包裝在一個compositor frame object中,該對象被提交給瀏覽器進程。

clipboard.png

The compositor thread has two copies of the tree, so that it can raster tiles from a new commit while drawing the previous commit.

合成器線程有兩個樹的副本,所以它能夠在繪製上一次commit時,對新的commit進行光柵化tiles。

clipboard.png

The browser process runs a component called the display compositor, inside a service called "viz" (short for visuals).
The display compositor aggregates compositor frames submitted from all the renderer processes, along with frames from the browser UI outside of the WebContents. Then it issues the GL calls to draw the quad resources, which go to the GPU process just like the GL calls from the raster workers.
On most platforms the display compositor's output is double-buffered, so the quads draw into a backbuffer, and a "swap" command makes it visible.
(On OS X we do something a little different with CoreAnimation.)
Finally our pixels are on the screen. :)
瀏覽器進程在名爲「viz」(visual的簡稱)的service中運行一個名爲display compositor的組件。
display compositor聚合從全部renderer進程提交的compositor frame,以及來自WebContents外部的browser UI的frame。 而後它發起GL調用來繪製quad資源,這些資源就像來自raster worker的GL調用同樣進入GPU進程。
在大多數平臺上,display compositor的輸出是雙緩衝的,所以quads繪製到backbuffer,「swap」命令使其可見。
(在OS X上,咱們使用CoreAnimation作了一些不一樣的事情。)
最後咱們的像素在屏幕上。:)

clipboard.png

clipboard.png

相關文章
相關標籤/搜索