CSS: Is Transition: Left/Top Gpu Accelerated

CSS: is transition: left/top GPU accelerated?

It's not accelerated. You have to use the specific CSS3 properties for it to be accelerateable. I think you'll find these links interesting:

http://www.html5rocks.com/en/tutorials/speed/html5/

http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome

Does animating the value of a CSS3 transform with javascript rule out hardware acceleration?

Test if Hardware Acceleration has been enabled for a CSS animation?

Overview

A CSS property transition on an element is hardware-accelerated if all these conditions are met:

  1. Hardware-accelerated layer compositing is enabled in the browser
  2. The CSS property being transitioned is acceleratable
  3. The element has been given its own compositing layer

Generally, the requirements for these conditions are:

  1. The relevant hardware-acceleration options must be enabled, and the device's GPU and graphics drivers must not be blacklisted
  2. Only compositing CSS properties (opacity, transform: translate / scale / rotate, etc) are acceleratable
  3. Each browser has specific reasons for deciding whether to give an element its own compositing layer (or it can be forced by using a "go faster" hack like transform: translate3d)

Hardware-accelerated layer compositing

To identify whether this is enabled:

Chrome

1. General acceleration

  • Go to chrome://settings
  • Click the + Show advanced settings button
  • In the System section, inspect the status of the Use hardware acceleration when available checkbox

If acceleration is enabled, then:

2. Accelerated compositing

  • Go to chrome://gpu
  • In the Graphics Feature Status section, inspect the value of Compositing. This will be one of the following:

    • Hardware accelerated
    • Software only, hardware acceleration unavailable

More details on the Software Compositor from the docs:

In some situations hardware compositing is infeasible, e.g. if the device's graphics
drivers are blacklisted or the device lacks a GPU entirely. For these situations is
an alternative implementation to the GL renderer called the SoftwareRenderer

(Note: Chrome also has a Legacy Software Rendering Path, which is "still lingering as of May 2014, but will soon be removed entirely in Blink.")

Here's a great article with more info: Accelerated Rendering in Chrome.

Firefox

1. General acceleration

  • Go to Firefox's Preferences
  • Go to the Advanced tab
  • Go to the General subtab
  • Inspect the status of the Use hardware acceleration when available checkbox

If acceleration is enabled, then:

2. Layer acceleration

  • Go to about:config
  • Search for layers.acceleration.disabled

If layer acceleration is enabled (if the value is false), then:

3. GPU accelerated windows

  • Go to about:support
  • In the Graphics section, inspect the value of GPU Accelerated Windows

If it does not begin with 0/, and a rendering API is shown (eg. OpenGL, Direct3D), then GPU acceleration is active.

Safari

  • Enable Safari's debug menu by running this command in the Terminal:

    defaults write com.apple.Safari IncludeInternalDebugMenu 1
  • Open (or restart) Safari
  • In Safari's Debug menu, inspect the status of the Disable Accelerated Compositing option in the Drawing/Compositing Flags submenu

Acceleratable CSS properties

The only CSS property transitions which can be hardware-accelerated are those which occur in the compositing stage of the rendering process. For example:

  • opacity
  • transform: translate and its friends: translateX, translateY, translateZ, translate3d
  • transform: scale and its friends: scaleX, scaleY, scaleZ, scale3d
  • transform: rotate and its friends: rotateX, rotateY, rotateZ, rotate3d

To fully benefit from acceleration, no non-compositing properties must be transitioned. For example:

  • A transition on just transform: translate can receive the full benefit of acceleration (because the element's layer can simply be recomposited by the GPU).
  • A transition on both transform: translate and width will receive almost no benefit from acceleration (because a transition on width causes the element's layer to be repainted by the CPU for every animation frame).

Compositing layers & coloured borders

The browser's rendering engine decides (based on user preferences, CSS styles, etc) whether or not to give an element its own compositing layer.

For example, Chrome has this list of reasons, and also has this option in chrome://flags:

Compositing for RenderLayers with transitions
Enabling this option will make RenderLayers with a transition on opacity, transform or filter have their own composited layer.

If an element has not been given its own layer, then no CSS transitions on that element will be accelerated.

transform: translate3d (the "go faster" hack) generally forces an element to be given its own layer.

But even if an element has been given its own layer, transitions on non-compositing properties (width, height, left, top, etc) still cannot be accelerated, because they occur before the compositing stage (eg. in the layout or paint stages). @ChrisSpittles This is why you saw no visual improvement after adding transform: translate3d.

Most browsers can display coloured borders around composited layers, to make them easy to identify for development/debugging:

Chrome

Displaying the borders of composited layers can be done in one of two ways:

  • For all pages — Go to chrome://flags and enable Composited render layer borders ("Renders a border around composited Render Layers to help debug and study layer compositing"). You'll need to relaunch Chrome for this to take effect.
  • For individual pages — Open the Developer Tools, then open the Drawer, select the Rendering tab, and enable Show composited layer borders. Now, opening the Developer Tools on any page will cause layer borders to be shown on that page.

Now trigger the CSS transition on the element. If it has a coloured border, then it has its own compositing layer.

The border colours and their meanings are defined in debug_colors.cc. More details here and here.

Firefox

To draw the borders of composited layers:

  • Go to about:config
  • Search for layers.draw-borders and enable it

Now trigger the CSS transition on the element. If it has a coloured border, then it has its own compositing layer.

The border colours and their meanings are defined in Compositor::DrawDiagnosticsInternal.

Safari

(This does not work for me with Safari 7.0.3, but it seems it did work for some people as recently as last year.)

Launch Safari from the Terminal with the CA_COLOR_OPAQUE boolean environment variable set:

$ CA_COLOR_OPAQUE=1 /Applications/Safari.app/Contents/MacOS/Safari

Alternative method:

$ export CA_COLOR_OPAQUE=1 
$ /Applications/Safari.app/Contents/MacOS/Safari

Apparently, hardware-accelerated layers should be coloured red. More details here and here.

Update:

Here's an alternative method which works for me in Safari 7.0.3 (credit to David Calhoun):

  • In Safari's Debug menu, enable Show Compositing Borders in the Drawing/Compositing Flags submenu

Now trigger the CSS transition on the element. If it has a coloured border, then it has its own compositing layer.


References

For more details, check out these excellent articles:

  • http://blogs.adobe.com/webplatform/2014/03/18/css-animations-and-transitions-performance/
  • http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/
  • http://www.html5rocks.com/en/mobile/optimization-and-performance/
  • http://ariya.blogspot.co.uk/2011/07/fluid-animation-with-accelerated.html

What exact parts of CSS3 are GPU accelerated?

Right, this is an interesting topic, and it does really depend on the browser + graphics card. I've been meaning to do some research on this for a while, so here's a quick summary.

Webkit (Safari, Chrome, iOS, Android)

In Webkit, AnimationBase.cpp used to specify it, but it seems to have moved! Doh! Well, anyway, if you search the code for ACCELERATED_COMPOSITING, you'll find it.

Specifically, if something matches one of these, then it can be accelerated (at least in Chromium):

  • Layer has 3D or perspective transform CSS properties
  • Layer is used by element using accelerated video decoding
  • Layer is used by a element with a 3D context or accelerated 2D context
  • Layer is used for a composited plugin
  • Layer uses a CSS animation for its opacity or uses an animated webkit transform
  • Layer uses accelerated CSS filters
  • Layer has a descendant that is a compositing layer
  • Layer has a sibling with a lower z-index which has a compositing layer (in other words the layer is rendered on top of a composited layer)

Source


Gecko (Firefox)

In Gecko, https://wiki.mozilla.org/Platform/GFX/HardwareAcceleration explains their plan/implementation, much like IE, on XP the options are more limited, but every other OS gets some acceleration if the graphics card is supported properly. Firefox 4 (I think!) added acceleration for text, canvas and transforms.


Trident (IE)

IE10 seems to have pretty much everything HW accelerated. http://blogs.msdn.com/b/ie/archive/2011/04/26/understanding-differences-in-hardware-acceleration-through-paintball.aspx

It is pretty quick, so I don't really doubt their claim!

Does animating the value of a CSS3 transform with javascript rule out hardware acceleration?

It is hardware accelerated, but as Rich mentions, it's easier and more efficient to do it with CSS transitions. The thing is that animating 3d transforms with jQuery is not straightforward, if you do:

$('div').animate({
'-vendor-transform' : "translate3d(100px,0,0)";
}, 500)

It doesn't work. Even if you do:

$('div').css("-webkit-transform", "translate3d(0,0,0)");
alert($('div').css("-webkit-transform"))

You don't get back translate3d(0,0,0), you get matrix(1, 0, 0, 1, 100, 0)

So you must write a lot of custom animation code involving matrices just to get things moving on screen.

Here is a custom animated 3d transform example: http://www.eleqtriq.com/wp-content/static/demos/2010/rotation/, take a look at the source code to see if it's the level of javascript you are comfortable with.

translate3d vs css left/top and hardware acceleration

I have used translate3d extensively on iOS in lieu of CSS left/top, and I can say one thing:

It is truly faster for animating things (which jsperf does not seem to do.) My guess is, left/top is faster when benchmarking since nothing is animated and I don't think anything is displayed either.

It is when used in conjunction with transition (or -webkit-transition) that translate3d works its magic.

Why does enabling hardware-acceleration in CSS3 slow down performance?

The reason animation was slower when you added the null transform hack (translateZ(0)) is that each null 3D transform creates a new layer. When there are too many of these layers, rendering performance suffers because the browser needs to send a lot of textures to the GPU.

The problem was noticed in 2013 on Apple's homepage, which abused the null transform hack. See http://wesleyhales.com/blog/2013/10/26/Jank-Busting-Apples-Home-Page/

The OP also correctly noticed the explanation in their comment:

Moving few big objects is more performant than moving lots of small items when using 3D-acceleration because all the 3D-accelerated layers have to be transferred to the GPU and the way back. So even if the GPU does a good job, the transfer of many objects might be a problem so that using GPU acceleration might not be worth it.

How to convert this CSS animation to use GPU level, instead of updating layer tree

If you want to avoid repainting and move the animation to GPU then you could use 3D transforms to produce the effect instead of animating the width. As mentioned in this article, using 3D transforms mean that the browser would make the animation GPU accelerated.

CSS animations, transforms and transitions are not automatically GPU accelerated, and instead execute from the browser’s slower software rendering engine. So what exactly forces the browser to swap to GPU mode? Many browsers provide GPU acceleration by means of certain CSS rules.

Currently, browsers like Chrome, FireFox, Safari, IE9+ and the latest version of Opera all ship with hardware acceleration; they only use it when they have an indication that a DOM element would benefit from it. With CSS, the strongest indication is that a 3D transformation is being applied to an element.

Converting the animation into its 3D transform equivalent itself is not a big process. All that is needed is to set a initial width on all the three elements and convert the width within the @keyframes rules into their corresponding ratio value based on the initial width that is set.

A width animation is generally just a scaleX but scale3d is used since we need the animation to be moved to the GPU. Since scale3d takes 3 parameters (for scale in each of the three axes), we can provide 1 (initial scale) as the value for the other two axes. So, it would be scale3d(x ratio, 1, 1).

For example, the 10% frame provided in question has width: 11px setting and here is how we can get its equivalent scale3d value:

  • Set an initial or starting width on the element. In the below snippet, I have set it as 17px.
  • Get the scale ratio for the X-axis based on the initial width and the required width. That would be, 11px / 17px (which is 0.64).
  • So, the equivalent 3D scale transform would be scale3d(0.64, 1, 1).

@keyframes color-bar {  0% {    transform: scale3d(1,1,1);  }  10% {    transform: scale3d(0.64,1,1);  }  20% {    transform: scale3d(2.17,1,1);  }  30% {    transform: scale3d(1.76,1,1);  }  40% {    transform: scale3d(0.88,1,1);  }  50% {    transform: scale3d(0.58,1,1);  }  60% {    transform: scale3d(1.41,1,1);  }  70% {    transform: scale3d(1,1,1);  }  80% {    transform: scale3d(1.23,1,1);  }  90% {    transform: scale3d(1.88,1,1);  }  100% {    transform: scale3d(1,1,1);  }}.lines-ani {  width: 25vw;  transform: rotateY(180deg);}.lines-ani .lines {  position: relative;  width: 17px;  height: 10px;  background: red;  transform-origin: left;  animation: color-bar 1.5s 2s ease-out alternate infinite;}.lines-ani .lines:before {  position: absolute;  content: '';  top: 125%;  height: 100%;  width: 100%;  background: green;  transform-origin: left;  animation: color-bar 1.5s 1.5s ease-out alternate infinite;}.lines-ani .lines:after {  position: absolute;  content: '';  top: 250%;  height: 100%;  width: 100%;  background: green;  transform-origin: left;  animation: color-bar 1.5s 2.5s ease-out alternate infinite;}
<div class='lines-ani'>  <div class='lines'>  </div></div>

Is there a Firefox equivalent to Chrome's translateZ(0); to force GPU accelerated CSS animation?

Firefox GPU-accelerates by default when it can. So there's nothing to "force" GPU acceleration: if it's possible, it's already done.



Related Topics



Leave a reply



Submit