Bagikan melalui



Special Windows 10 issue 2015

Volume 30 Number 11

Graphics and Animation - Windows Composition Turns 10

By Kenny Kerr | Windows 2015

The Windows composition engine, otherwise known as the Desktop Window Manager (DWM), gets a new API for Windows 10. DirectComposition was the primary interface for composition, but, as a classic COM API, it was largely inaccessible to the average app developer. The new Windows composition API is built on the Windows Runtime (WinRT) and provides the foundation for high-performance rendering by blending the world of immediate-mode graphics offered by Direct2D and Direct3D with a retained visual tree that now sports much-improved animation and effects capabilities.

I first wrote about the DWM back in 2006 when Windows Vista was in beta (goo.gl/19jCyR). It allowed you to control the extent of the blur effect for a given window and to create custom chrome that blended nicely with the desktop. Figure 1 illustrates the height of this achievement in Windows 7. It was possible to produce hardware-accelerated rendering with Direct3D and Direct2D to create stunning visuals for your app (goo.gl/IufcN1). You could even blend the old world of GDI and USER controls with the DWM (goo.gl/9ITISE). Still, any keen observer could tell that the DWM had more to offer—a lot more. The Windows Flip 3D feature in Windows 7 was convincing proof.

Windows Aero
Figure 1 Windows Aero

Windows 8 introduced a new API for the DWM called DirectComposition, its name giving tribute to the DirectX family of classic COM APIs that inspired its design. DirectComposition began to give developers a clearer picture of what the DWM was capable of doing. It also offered improved terminology. The DWM is really the Windows composition engine, and it was able to produce the dazzling effects in Windows Vista and Windows 7 because it fundamentally changed the way desktop windows were rendered. By default, the composition engine created a redirection surface for each top-level window. I described this in detail in my June 2014 column (goo.gl/oMlVa4). These redirection surfaces formed part of a visual tree, and DirectComposition allowed apps to make use of this same technology to provide a lightweight retained-mode API for high-performance graphics. DirectComposition offered a visual tree and surface management that allowed the app to offload the production of effects and animations to the composition engine. I described these capabilities in my August (goo.gl/CNwnWR) and September 2014 columns (goo.gl/y7ZMLL). I even produced a course on high-performance rendering with DirectComposition for Pluralsight (goo.gl/fgg0XN).

Windows 8 debuted with DirectComposition, along with impressive improvements to the rest of the DirectX family of APIs, but it also ushered in a new era for the Windows API that would forever change the way that developers look at the OS. The introduction of the Windows Runtime overshadowed everything else. Microsoft promised a fresh new way to build apps and access OS services that spelled the eventual retirement of the so-called Win32 API that had long been the dominant way to build apps and interact with the OS. Windows 8 got off to a rocky start, but Windows 8.1 fixed a lot of problems and Windows 10 now provides a far more comprehensive API that will satisfy many more developers interested in building first-class apps, nay, serious applications, for Windows.

Windows 10 shipped in July 2015 with a preview of the new composition API that wasn’t yet ready for production. It was still subject to change and therefore couldn’t be used in Universal Windows apps submitted to the Windows Store. That’s just as well because the composition API that’s now available for production has changed substantially, and for the better. This Windows 10 update is also the first time that the same composition API is available on all form factors, giving further credence to the universal part of the Universal Windows Platform. Composition works the same regardless of whether you’re targeting your multi-display desktop powerhouse or the small smartphone in your pocket.

Naturally, the thing everyone likes about the Windows Runtime is that it finally delivers on the promise of a common language runtime for Windows. If you prefer to code in C#, you can use the Windows Runtime directly via the support built into the Microsoft .NET Framework. If, like me, you prefer to use C++, you can use the Windows Runtime with no intermediate or costly abstractions. The Windows Runtime is built on COM rather than .NET and as such is ideally suited for C++ consumption. I’ll use Modern C++ for the Windows Runtime (moderncpp.com), the standard C++ language projection, but you can follow along in your favorite language as the API is the same, regardless. I’ll even offer up some examples in C# to illustrate how seamlessly the Windows Runtime can support different languages.

The Windows composition API distances itself from its DirectX roots. While DirectComposition provided a device object, modeled after the Direct3D and Direct2D devices, the new Windows composition API starts with a compositor. It does, however, serve the same purpose, acting as the factory for composition resources. Beyond that, Windows composition is very similar to DirectComposition. There’s a composition target that represents the relationship between a window and its visual tree. The differences become more apparent as you look more closely at visuals. A DirectComposition visual had a content property that provided a bitmap of some kind. The bitmap was one of three things: a composition surface, a DXGI swap chain or the redirection surface of another window. A typical DirectComposition application consisted of visuals and surfaces, with surfaces acting as the content or bitmaps for the different visuals. As depicted in Figure 2, a composition visual tree is a slightly different beast. The new visual object has no content property and is instead rendered with a composition brush. This turns out to be a more flexible abstraction. While the brush can just render a bitmap as before, simple solid color brushes can be created very efficiently and more elaborate brushes can be defined, at least conceptually, in a manner not unlike how Direct2D provides effects that can be treated as images. The right abstraction makes all the difference.

The Windows Composition Visual Tree
Figure 2 The Windows Composition Visual Tree

Let’s walk through some practical examples to illustrate how this all works and give you a glimpse of what’s possible. Again, you can pick your favorite WinRT language projection. You can create a compositor with modern C++, as follows:

using namespace Windows::UI::Composition;
Compositor compositor;

Likewise, you can do the same with C#:

using Windows.UI.Composition;
Compositor compositor = new Compositor();

You can even use the more flamboyant syntax offered by C++/CX:

using namespace Windows::UI::Composition;
Compositor ^ compositor = ref new Compositor();

These are all equivalent from an API perspective and merely reflect the differences in language projection. There are basically two ways in which you can write a Universal Windows app today. Perhaps the most common approach is to use the OS’s Windows.UI.Xaml namespace. If XAML isn’t that important to your app, you can also use the underlying application model directly with no dependency on XAML. I described the WinRT application model in my August 2013 column (goo.gl/GI3OKP). Using this approach, you simply need a minimal implementation of the IFrameworkView and IFrameworkViewSource interfaces and you’re good to go. Figure 3 provides a basic outline in C# that you can use to get started. Windows composition also offers deep integration with XAML, but let’s start with a simple XAML-free application as it provides a simpler playground in which to learn about composition. I’ll get back to XAML a little later on in this article.

Figure 3 Windows Runtime Application Model in C#

using Windows.ApplicationModel.Core;
using Windows.UI.Core;
class View : IFrameworkView, IFrameworkViewSource
{
  static void Main()
  {
    CoreApplication.Run(new View());
  }
  public IFrameworkView CreateView()
  {
     return this;
  }
  public void SetWindow(CoreWindow window)
  {
    // Prepare composition resources here...
  }
  public void Run()
  {
    CoreWindow window = CoreWindow.GetForCurrentThread();
    window.Activate();
    window.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessUntilQuit);
  }
  public void Initialize(CoreApplicationView applicationView) { }
  public void Load(string entryPoint) { }
  public void Uninitialize() { }
}

It is within the app’s SetWindow method (see Figure 3) that the compositor should be constructed. In fact, this is the earliest point in the app’s lifecycle that this can occur because the compositor depends on the window’s dispatcher and this is the point at which both window and dispatcher are finally in existence. The relationship between the compositor and the app view can then be established by creating a composition target:

CompositionTarget m_target = nullptr;
// ...
m_target = compositor.CreateTargetForCurrentView();

It’s vital that the app keep the composition target alive, so be sure to make it a member variable of your IFrameworkView implementation. As I mentioned before, the composition target represents the relationship between the window or view and its visual tree. All you can do with a composition target is set the root visual. Typically, this will be a container visual:

ContainerVisual root = compositor.CreateContainerVisual();
m_target.Root(root);

Here I’m using C++, which lacks language support for properties, so the Root property is projected as accessor methods. C# is very similar with the addition of property syntax:

ContainerVisual root = compositor.CreateContainerVisual();
m_target.Root = root;

DirectComposition provided only one kind of visual, which supported different kinds of surfaces for representing bitmap content. Windows composition offers small class hierarchies that represent different kinds of visuals, brushes, and animations, yet there’s only one kind of surface and it can only be created using C++ because it’s part of the Windows composition interop API intended for use by frameworks like XAML and more sophisticated app developers.

The visual class hierarchy is shown in Figure 4. A CompositionObject is a resource backed by the compositor. All composition objects may potentially have their properties animated. A Visual provides a slew of properties for controlling many aspects of the visual’s relative position, appearance, clipping and rendering options. It includes a transform matrix property, as well as shortcuts for scale and rotation. This is a powerful base class. By contrast, ContainerVisual is a relatively simple class that simply adds a Children property. While you can create container visuals directly, a SpriteVisual adds the ability to associate a brush so that the visual can actually render pixels of its own.

Composition Visuals
Figure 4 Composition Visuals

Given a root container visual, I can create any number of child visuals:

VisualCollection children = root.Children();

These can also be container visuals, but more likely they’ll be sprite visuals. I could add three visuals as children of the root visual using a for loop in C++:

using namespace Windows::Foundation::Numerics;
for (unsigned i = 0; i != 3; ++i)
{
  SpriteVisual visual = compositor.CreateSpriteVisual();
  visual.Size(Vector2{ 300.0f, 200.0f });
  visual.Offset(Vector3{ 50 + 20.0f * i, 50 + 20.0f * i });
  children.InsertAtTop(visual);
}

You can easily imagine the app window in Figure 5, and yet this code won’t result in anything being rendered because there’s no brush associated with these visuals. The brush class hierarchy is shown in Figure 6. A CompositionBrush is simply a base class for brushes and provides no functionality of its own. A CompositionColorBrush is the simplest kind, offering only a color property for rendering solid color visuals. This might not sound very exciting, but don’t forget that you can connect animations to that color property. The CompositionEffectBrush and CompositionSurfaceBrush classes are related, but are more complex brushes because they’re backed by other resources. A CompositionSurfaceBrush will render a composition surface for any attached visuals. It has a variety of properties that control bitmap drawing, such as interpolation, alignment, and stretch, not to mention the surface itself. A Composition­EffectBrush takes a number of surface brushes to produce various effects.

Child Visuals in a Window
Figure 5 Child Visuals in a Window

Composition Brushes
Figure 6 Composition Brushes

Creating and applying a color brush is straightforward. Here’s an example in C#:

using Windows.UI;
CompositionColorBrush brush = compositor.CreateColorBrush();
brush.Color = Color.FromArgb(0xDC, 0x5B, 0x9B, 0xD5);
visual.Brush = brush;

The Color structure comes courtesy of the Windows.UI namespace and sports alpha, red, green, and blue as 8-bit color values, a departure from the DirectComposition and Direct2D preference for floating-point color values. A nice feature of this approach to visuals and brushes is that the color property can be changed at any time, and any visuals referring to the same brush will be updated automatically. Indeed, as I’ve hinted at before, the color property can even be animated. So how does that work? This brings us to the animation classes.

The animation class hierarchy is shown in Figure 7. The CompositionAnimation base class provides the ability to store named values for use with expressions. I’ll talk more about expressions in a moment. A KeyFrameAnimation provides typical keyframe-based animation properties like duration, iteration and stop behavior. The various keyframe animation classes offer type-specific methods for inserting keyframes, as well as type-specific animation properties. For example, ColorKeyFrameAnimation lets you insert keyframes with color values and a property to control the color space for interpolating between keyframes.

Composition Animations
Figure 7 Composition Animations

Creating an animation object and then applying that animation to a particular composition object is surprisingly easy. Suppose I want to animate the opacity of a visual. I could set the visual’s opacity to 50 percent directly with a scalar value in C++, as follows:

visual.Opacity(0.5f);

Alternatively, I can create a scalar animation object with keyframes to produce an animation variable from 0.0 through 1.0, representing 0 percent through 100 percent opacity:

ScalarKeyFrameAnimation animation =
  compositor.CreateScalarKeyFrameAnimation();
animation.InsertKeyFrame(0.0f, 0.0f); // Optional
animation.InsertKeyFrame(1.0f, 1.0f);

The first parameter of InsertKeyFrame is the relative offset from the start of the animation (0.0) to the end of the animation (1.0). The second parameter is the value of the animation variable at that point in the animation timeline. So this animation will smoothly transition the value from 0.0 to 1.0 over the duration of the animation. I can then set the overall duration of this animation, as follows:

using namespace Windows::Foundation;
animation.Duration(TimeSpan::FromSeconds(1));

With the animation ready to go, I simply need to connect it to the composition object and property of my choice:

visual.StartAnimation(L"Opacity", animation);

The StartAnimation method is actually inherited from the CompositionObject base class, meaning that you can animate the properties of a variety of different classes. This is another departure from DirectComposition, where each animatable property provided overloads for scalar values, as well as animation objects. Windows composition offers a much richer property system that opens the door to some very interesting capabilities. In particular, it supports the ability to write textual expressions that cut down on the amount of code that needs to be written for more interesting animations and effects. These expressions are parsed at run time, compiled and then efficiently executed by the Windows composition engine.

Imagine you need to rotate a visual along the Y axis and give it the appearance of depth. The visual’s RotationAngle property, measured in radians, isn’t enough because that won’t produce a transformation that includes perspective. As the visual rotates, the edge closest to the human eye should appear larger, while the opposite edge should appear smaller. Figure 8 shows a number of rotating visuals that illustrate this behavior.

Rotating Visuals
Figure 8 Rotating Visuals

How would you accomplish such an animated effect? Well, let’s start with a scalar keyframe animation for the rotation angle:

ScalarKeyFrameAnimation animation = compositor.CreateScalarKeyFrameAnimation();
animation.InsertKeyFrame(1.0f, 2.0f * Math::Pi,
  compositor.CreateLinearEasingFunction());
animation.Duration(TimeSpan::FromSeconds(2));
animation.IterationBehavior(AnimationIterationBehavior::Forever);

The linear easing function overrides the default acceleration/deceleration function to produce a continuous rotating motion. I then need to define a custom object with a property I can refer to from within an expression. The compositor provides a property set for just this purpose:

CompositionPropertySet rotation = compositor.CreatePropertySet();
rotation.InsertScalar(L"Angle", 0.0f);

A property set is also a composition object, so I can use the StartAnimation method to animate my custom property just as easily as any built-in property:

rotation.StartAnimation(L"Angle", animation);

I now have an object whose Angle property is in motion. Now I need to define a transform matrix to produce the desired effect, while delegating to this animated property for the rotation angle itself. Enter expressions:

ExpressionAnimation expression =
  compositor.CreateExpressionAnimation(
    L"pre * Matrix4x4.CreateFromAxisAngle(axis, rotation.Angle) * post");

An expression animation is not a keyframe animation object, so there’s no relative keyframe offsets at which animation variables might change (based on some interpolation function). Instead, expressions simply refer to parameters that may themselves be animated in the more traditional sense. Still, it’s up to me to define what “pre,” “axis,” “rotation,” and “post” are. Let’s start with the axis parameter:

expression.SetVector3Parameter(L"axis", Vector3{ 0.0f, 1.0f, 0.0f });

The CreateFromAxisAngle method inside the expression expects an axis to rotate around and this defines the axis around the Y axis. It also expects an angle of rotation and for that we can defer to the rotation property set with its animated “Angle” property:

expression.SetReferenceParameter(L"rotation", rotation);

To ensure that the rotation occurs through the center of the visual rather than the left edge, I need to pre-multiply the rotation matrix created by CreateFromAxisAngle with a translation that logically shifts the axis to the point of rotation:

expression.SetMatrix4x4Parameter(
  L"pre", Matrix4x4::Translation(-width / 2.0f, -height / 2.0f, 0.0f));

Remember that matrix multiplication is not commutative, so the pre and post matrixes really are just that. Finally, after the rotation matrix, I can add some perspective and then restore the visual to its original location:

expression.SetMatrix4x4Parameter(
  L"post", Matrix4x4::PerspectiveProjection(width * 2.0f) *
    Matrix4x4::Translation(width / 2.0f, height / 2.0f, 0.0f));

This satisfies all the parameters referred to by the expression and I can now simply use the expression animation to animate the visual using its TransformMatrix property:

visual.StartAnimation(L"TransformMatrix", expression);

So I’ve explored various ways to create, fill and animate visuals, but what if I need to render visuals directly? DirectComposition offered both preallocated surfaces and sparsely allocated bitmaps called virtual surfaces that were allocated on demand and also resizable. Windows composition seemingly provides no ability to create surfaces. There’s a CompositionDrawingSurface class, but no way to create it without outside help. The answer comes from the Windows composition interop API. WinRT classes might implement additional COM interfaces not directly visible if all you have is a component’s Windows metadata. Given the knowledge of these cloaked interfaces, you can easily query for them in C++. Naturally, this is going to be a bit more work as you’re stepping outside of the neat abstractions provided to mainstream developers by the Windows composition API. The first thing I need to do is create a rendering device and I’ll use Direct3D 11 because Windows composition doesn’t yet support Direct3D 12:

ComPtr<ID3D11Device> direct3dDevice;

I’ll then prepare the device creation flags:

unsigned flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT |
                 D3D11_CREATE_DEVICE_SINGLETHREADED;
#ifdef _DEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

The BGRA support allows me to use the more approachable Direct2D API for rendering with this device, and then the D3D11CreateDevice function creates the hardware device itself:

check(D3D11CreateDevice(nullptr, // Adapter
                        D3D_DRIVER_TYPE_HARDWARE,
                        nullptr, // Module
                        flags,
                        nullptr, 0, // Highest available feature level
                        D3D11_SDK_VERSION,
                        set(direct3dDevice),
                        nullptr, // Actual feature level
                        nullptr)); // Device context

I then need to query for the device’s DXGI interface, because that’s what I’ll need to create a Direct2D device:

ComPtr<IDXGIDevice3> dxgiDevice = direct3dDevice.As<IDXGIDevice3>();

Now it’s time to create the Direct2D device itself:

ComPtr<ID2D1Device> direct2dDevice;

Here, again, I’ll enable the debug layer for added diagnostics:

D2D1_CREATION_PROPERTIES properties = {};
#ifdef _DEBUG
properties.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif

I could first create a Direct2D factory to create the device. That would be useful if I needed to create any device-independent resources. Here I’ll just use the shortcut provided by the D2D1­CreateDevice function:

check(D2D1CreateDevice(get(dxgiDevice), properties, set(direct2dDevice)));

The rendering device is ready. I have a Direct2D device I can use to render whatever I can imagine. Now I need to tell the Windows composition engine about this rendering device. This is where those cloaked interfaces come in. Given the compositor that I’ve used throughout, I can query for the ICompositorInterop interface:

namespace abi = ABI::Windows::UI::Composition;
ComPtr<abi::ICompositorInterop> compositorInterop;
check(compositor->QueryInterface(set(compositorInterop)));

ICompositorInterop provides methods for creating a composition surface from a DXGI surface, which would certainly be handy if you want to include an existing swap chain in a composition visual tree, but it provides something else that’s far more interesting. Its CreateGraphicsDevice method will create a CompositionGraphicsDevice object given a rendering device. The CompositionGraphicsDevice class is a normal class in the Windows composition API, rather than a cloaked interface, but it doesn’t provide a constructor so you need to use C++ and the ICompositorInterop interface to create it:

CompositionGraphicsDevice device = nullptr;
check(compositorInterop->CreateGraphicsDevice(get(direct2dDevice), set(device)));

Because CompositionGraphicsDevice is a WinRT type, I can again use modern C++, rather than pointers and manual error handling. And it’s the CompositionGraphicsDevice that finally allows me to create a composition surface:

using namespace Windows::Graphics::DirectX;
CompositionDrawingSurface surface =
  compositionDevice.CreateDrawingSurface(Size{ 100, 100 },
    DirectXPixelFormat::B8G8R8A8UIntNormalized,
    CompositionAlphaMode::Premultiplied);

Here I’m creating a composition surface 100 x 100 pixels in size. Note that this represents physical pixels rather than the logical and DPI-aware coordinates assumed and provided by the rest of Windows composition. The surface also provides 32-bit alpha-blended rendering supported by Direct2D. Of course, Direct3D and Direct2D are not yet offered through the Windows Runtime, so it’s back to cloaked interfaces to actually draw to this surface:

ComPtr<abi::ICompositionDrawingSurfaceInterop> surfaceInterop;
check(surface->QueryInterface(set(surfaceInterop)));

Much like DirectComposition before it, Windows composition provides BeginDraw and EndDraw methods on the IComposition­DrawingSurfaceInterop interface that subsume and take the place of the typical calls to the Direct2D method calls that go by the same names:

ComPtr<ID2D1DeviceContext> dc;
POINT offset = {};
check(surfaceInterop->BeginDraw(nullptr, // Update rect
                                __uuidof(dc),
                                reinterpret_cast<void **>(set(dc)),
                                &offset));

Windows composition takes the original rendering device provided at the time the composition device was created and uses it to create a device context or render target. I can optionally provide a clipping rectangle in physical pixels, but here I’m just opting for unrestricted access to the rendering surface. BeginDraw also returns an offset, again in physical pixels, indicating the origin of the intended drawing surface. This will not necessarily be the top-left corner of the render target, and care must be taken to adjust or transform any drawing commands to properly accommodate this offset. Again, don’t call BeginDraw on the render target as Windows composition has already done that for you. This render target is logically owned by the composition API and care must be taken not to hold on to it following the call to EndDraw. The render target is now ready to go, but isn’t aware of the logical or effective DPI for the view. I can use the Windows::Graphics::Display namespace to get the logical DPI for the current view and set the DPI that will be used by Direct2D for rendering:

using namespace Windows::Graphics::Display;
DisplayInformation display = DisplayInformation::GetForCurrentView();
float const dpi = display.LogicalDpi();
dc->SetDpi(dpi, dpi);

The final step before rendering can commence is to handle the composition offset somehow. One simple solution is to use the offset to produce a transform matrix. Just remember that Direct2D trades in logical pixels, so I need to use not only the offset, but also the newly established DPI value:

dc->SetTransform(D2D1::Matrix3x2F::Translation(offset.x * 96.0f / dpi,
                                               offset.y * 96.0f / dpi));

At this point, you can draw to your heart’s content before calling the EndDraw method on the surface’s interop interface to ensure that any batched Direct2D drawing commands are processed and changes to the surface are reflected in the composition visual tree:

check(surfaceInterop->EndDraw());

Of course, I haven’t yet associated the surface with a visual and, as I’ve mentioned, visuals no longer provide a content property and must be rendered using a brush. Fortunately, the compositor will create a brush to represent a preexisting surface:

CompositionSurfaceBrush brush = compositor.CreateSurfaceBrush(surface);

I can then create a normal sprite brush and use this brush to bring the visual to light:

SpriteVisual visual = compositor.CreateSpriteVisual();
visual.Brush(brush);
visual.Size(Vector2{ ... });

If that’s not enough interoperability for you, you can even take a XAML element and retrieve the underlying composition visual. Here’s an example in C#:

using Windows.UI.Xaml.Hosting;
Visual visual = ElementCompositionPreview.GetElementVisual(button);

Despite its seemingly temporary status, ElementCompositionPreview is in fact ready for production and may be used by apps submitted to the Windows Store. Given any UI element, the static GetElementVisual method will return the visual from the underlying composition visual tree. Notice that it returns a Visual rather than a ContainerVisual or SpriteVisual, so you can’t directly work with visual children or apply a brush, but you can adjust the many visual properties offered by Windows composition. The ElementCompositionPreview helper class provides some additional static methods for adding child visuals in a controlled way. You can change the visual’s offset and things like UI hit testing will continue to work at the XAML level. You can even apply an animation directly with Windows composition without breaking the XAML infrastructure built upon it. Let’s create a simple scalar animation to rotate the button. I need to retrieve the compositor from the visual, then creating an animation object works as before:

Compositor compositor = visual.Compositor;
ScalarKeyFrameAnimation animation = compositor.CreateScalarKeyFrameAnimation();

Let’s build a simple animation to slowly rotate the button forever with a linear easing function:

animation.InsertKeyFrame(1.0f, (float) (2 * Math.PI),
  compositor.CreateLinearEasingFunction());

I can then indicate that a single rotation should take 3 seconds and continue forever:

animation.Duration = TimeSpan.FromSeconds(3);
animation.IterationBehavior = AnimationIterationBehavior.Forever;

Finally, I can simply connect the animation to the visual provided by XAML, instructing the compositing engine to animate its RotationAngle property:

visual.StartAnimation("RotationAngle", animation);

Although you may be able to pull this off with XAML alone, the Windows composition engine provides far more power and flexibility given that it resides at a much lower level of abstraction and can undoubtedly provide better performance. As another example, Windows composition provides quaternion animations not currently supported by XAML.

There’s so much more to talk about when it comes to the Windows composition engine. In my humble opinion, this is the most groundbreaking WinRT API to date. The amount of power at your disposal is staggering and, yet, unlike so many other large UI and graphics APIs, it doesn’t introduce a performance tradeoff or even a prohibitive learning curve. In many ways, Windows composition is representative of all that’s good and exciting about the Windows platform.

You can find the Windows Composition team on Twitter: @WinComposition.


Kenny Kerr is a computer programmer based in Canada, as well as an author for Pluralsight and a Microsoft MVP. He blogs at kennykerr.ca and you can follow him on Twitter: @kennykerr.

Thanks to the following Microsoft technical experts for reviewing this article: Mark Aldham, James Clarke, John Serna, Jeffrey Stall and Nick Waggoner