Chromium · Compositing

The compositor

The last stretch of the pipeline, and the one that decides whether the page feels fast. Painted content becomes textures on layers, layers become quads with transforms, and quads from every process are aggregated into one frame per vsync — most of it on threads that are not running your JavaScript.

01

The layer tree

what can move alone

Blink does not hand the compositor pixels or paint commands — it hands it a tree of layers. A layer is a thing that can be moved, scaled or faded independently of everything around it. Which elements get their own layer is the decision that determines what can be animated without waking the main thread.

will-change: transform  // promote to a layer
02

Main thread & compositor thread

the split

The main thread runs script, style, layout and paint. The compositor thread holds a committed copy of the layer tree and can keep producing frames from it on its own. That copy is the entire reason a page stuck in a long task still scrolls smoothly under your finger.

LayerTreeHost (main) ⇄ LayerTreeHostImpl (impl)
03

Tiling & raster

paint ops → pixels

A layer larger than the screen is cut into tiles, and only the tiles near the viewport are rastered, on worker threads or on the GPU. Priorities come from how close a tile is to being visible and how fast you are moving towards it. A checkerboard is a tile that missed its deadline.

visible → soon-visible → eventually → skip
04

Compositor frames

quads, not pixels

The compositor does not draw to the screen. It submits a CompositorFrame: a list of quads, each a transform plus a reference to an already-rastered texture. Producing one is cheap, and re-submitting the same one with a different transform is cheaper still — which is what a scroll actually is.

CompositorFrame { render_passes, quads }
05

Viz, the display compositor

in the GPU process

Every client — each renderer, the browser’s own UI — submits its frame to Viz, which aggregates them into one frame for the screen and draws it through Skia. It owns the vsync deadline, decides how long to wait for a late client, and is the last place anything can still be dropped.

components/viz/service/display/
06

Scroll & animation off-thread

why transform is cheap

Scroll offsets and animations of transform and opacity are handled entirely on the compositor thread, because neither changes any pixel that was already rastered — only the matrix a quad is drawn with. Animate top or width instead and you have asked for layout, on the main thread, every frame.

transform / opacity → compositor
top / width / color → main thread