How can I tell (for testing purposes) if Hardware Acceleration has been enabled for a CSS animation?
I have the following code which essentially enlarges an element and makes it fullscreen (without using the HTML5 fullscreen API). It runs like a stuttering asthmatic tortoise on most mobiles when using a jQuery animation so I have used CSS3 instead.
Here is the jsFiddle example:
This adds a class and the element transitions from one state to the next using a CSS transition. This is faster than jQuery but is still stuttery on iOS and android.
But I read here that you can force the transition to be accelerated using the GPU by specifying a 3d transform that essentially does nothing, like this:
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
However, after adding that to my CSS I see no visual improvement.
Is there a way to see if hardware acceleration has been enabled through dev tools in any browser? I don't need to detect this with script, I just want to know for testing purposes.
A CSS property transition on an element is hardware-accelerated if all these conditions are met:
Generally, the requirements for these conditions are:
opacity
, transform: translate
/ scale
/ rotate
, etc) are acceleratabletransform: translate3d
)To identify whether this is enabled:
chrome://settings
If acceleration is enabled, then:
chrome://gpu
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.
If acceleration is enabled, then:
about:config
layers.acceleration.disabled
If layer acceleration is enabled (if the value is false
), then:
about:support
If it does not begin with 0/
, and a rendering API is shown (eg. OpenGL, Direct3D), then GPU acceleration is active.
defaults write com.apple.Safari IncludeInternalDebugMenu 1
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:
transform: translate
can receive the full benefit of acceleration (because the element's layer can simply be recomposited by the GPU).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).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:
Displaying the borders of composited layers can be done in one of two ways:
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.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.
To draw the borders of composited layers:
about:config
layers.draw-borders
and enable itNow 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
.
(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.
Here's an alternative method which works for me in Safari 7.0.3 (credit to David Calhoun):
Now trigger the CSS transition on the element. If it has a coloured border, then it has its own compositing layer.
For more details, check out these excellent articles: