David Baron's Weblog

Running animations on the compositor thread

Monday, 2015-09-16, 20:27 -0400

Support for running animations of 'transform' and 'opacity' on the compositor thread is scheduled to ship next week in Firefox 41. This has been supported in Firefox OS since 1.0, and is something that a number of other browsers do as well, but will now also ship in Firefox for desktop and Android.

This means that animations of the CSS 'transform' and 'opacity' properties will run on the compositor thread, which makes them smoother, because they will continue running smoothly when the main thread misses its frame budget (that is, when the main thread stays busy too long to meet the frame rate).

Even better, when we run the animation on the compositor thread, we stop updating style on the main thread as the animation progresses, which reduces the total amount of work that we need to do. However, if the page does anything that flushes style or layout (that is, requests up-to-date style or layout information, such as getComputedStyle(), getBoundingClientRect(), or offsetTop), we recompute the current style on the main thread.

Running an animation on the compositor thread involves takes some existing optimizations that browsers have and makes them even more effective, which I'd like to explain in a little more detail. When an element has an active layer (a surface into which its contents are painted, that is given to the compositor thread to be composited), we implement transform and opacity by setting transform or opacity on the layer and having the compositor apply the transform or opacity when compositing. So when we want to run an animation on the compositor thread, we:

  1. force the element to have an active layer,
  2. set the future values of transform or opacity (in the form of timing functions and keyframes) on the layer instead of just the current value, and
  3. let the compositor update the transform or opacity over time.

Even when we support off-main-thread compositing we don't run transform and opacity animations on the compositor thread in all cases. The biggest is that we don't support compositor-thread animation of 3-D transforms in a preserve-3d scene. This means that if an element or its parent uses 'transform-style: preserve-3d', we don't run animations of its transform on the compositor. This is something that we hope to fix quite soon. Also, if the animation is also animating height, width, top, right, bottom, or left, then we do not run transform animations on the compositor because they would get out-of-sync with the size or position changes coming from animations of those other properties. We also don't support compositor-thread animation of elements with SVG transforms.

[Demo added 22:50] If you want to see the benefits, you can compare this demo of the smoothness benefits between Firefox 40 (or older) and Firefox 41 (or newer).

Many people contributed to getting this shipped. I'd particularly like to thank David Zbarsky (who implemented sending animations to the compositor thread and running them there), Nick Cameron (who implemented suppressing the work we do for such animations on the main thread), Brian Birtles, Robert O'Callahan, Chris Jones, Matt Woodrow, Boris Zbarsky, Markus Stange, Jonathan Watt, Cameron McCormack, Alice0775 White, Virtual_ManPL, and Elbart.

(I'd also note that we've often called this project OMTA or off-main-thread animations. However, since the animations are specifically running on the compositor thread, I prefer to call it that.)

Related links: