Tag Archives: compositor

WP7 performance tip: translate transforms

In my previous blog post, I described a control called the PivotIndicator.

The PivotIndicator is made of a small rectangle that is animated on an X axis: its position is updated every time the selected item of the Pivot changes. Here is the code which setup this animation:

var border = new Border { /* init properties... */ };
var animation = new DoubleAnimation
{
    Duration = new Duration(TimeSpan.FromSeconds(0.5)),
};

Storyboard.SetTarget(this.animation, this.border);
Storyboard.SetTargetProperty(this.animation, new PropertyPath(Canvas.LeftProperty));

The problem I noticed was that this animation wasn’t fluid. In particular, when the PivotItem contains a lot of items…

As you probably already know, the WP7 platform introduces a Compositor thread. This thread does not exist in the “desktop” version of Silverlight. The idea is that this thread can handle simple animations independently from the UI thread (which can be quite busy…) and leverage the GPU.

Now, in my code, I’m using a DoubleAnimation to animate a Canvas.Left property. What is wrong with that ? Actually, the problem is the property I’m animating, not the animation itself. When I setup an animation using Canvas.Left, there is absolutely no way the Compositor thread can handle it. Why ?

Because when the property changes, it triggers a layout update in the Canvas. This process is totally “CPU-bound” and executes on the UI thread. The dependency property changes, it calls InvalidateLayout which update the position of the item (by calling .Arrange() on each of its child). In this case, the GPU & the compositor thread cannot be used.

Now, the trick is to do the exact same animation with a different code:

var border = new Border { /* init properties... */ };
var translateTransform = new TranslateTransform();
border.RenderTransform = translateTransform;
var animation = new DoubleAnimation
{
    Duration = new Duration(TimeSpan.FromSeconds(0.5)),
};

Storyboard.SetTarget(this.animation, translateTransform);
Storyboard.SetTargetProperty(this.animation, new PropertyPath(TranslateTransform.XProperty));

Notice that all I change is using an TranslateTransform: the target of the animation is not the border but the translate transform it self. A TranslateTransform is an operation which can be handled by the GPU. Now, his animation is handled by the Compositor Thread and will be fluid even though the UI thread gets very busy !

Hope it helps 🙂