In Windows 7 we have invested heavily in building a new 2D drawing API in the DirectX family called Direct2D. This API was developed to fill several holes in our Windows graphics platform. One of the most important things to rectify was the lack of hardware acceleration for regular 2D application rendering. With the release of Windows Vista, GDI hardware acceleration was removed. We also wanted to modernize the feature set for 2D rendering with antialiasing and alpha blending support, as well as add interoperability with the other modern graphics APIs. Finally, we also wanted to ensure that server side rendering was addressed as part of developing a new API.
In order to understand how we got to Direct2D, we first look way back in history to when Windows was first developed. The original rendering system (which still exists to this day) was GDI (Graphics Device Interface). This was originally written for 16 bit Windows, but was updated for 32 bit Windows for Windows 95 and Windows NT. Since GDI was developed so long ago for computers with meager abilities, it does not have features such as anti-aliased primitives, and most APIs do not have alpha support.
Around the Windows 95 time frame, the first version of DirectX was released and DirectDraw was one of the first components. The idea here was to give even more direct access to hardware than the WinG effort allowed, which in turn meant that hardware accelerated blitting was enabled. This stack had some cooperation with GDI, but really was a parallel universe in its own right.
As graphics hardware evolved, GDI gained the ability to be hardware-accelerated through a set of DDIs (Device Driver Interface). Many video cards came to implement these DDIs, and it became commonplace to buy a video card to improve your Windows performance. Eventually Direct3D came onto the scene with DirectX 2, and also created its own set of DDIs. Video cards started to devote more and more silicon to implementing 3D graphics faster and faster to keep up with a very demanding gaming market. The result was that there were two different realms of hardware acceleration and graphics programming – one built around Direct3D and the other around GDI.
The fact that Direct3D and GDI were built up from different places with different goals meant that they did not work together as well as some people expected. Features like GetDC were implemented, which helped to bridge the gap, but there were always some frustrations with scenarios where a lot of interleaved rendering was needed. This did not remove the need for such scenarios to be solved, however.
Around the turn of the century, the limitations of GDI became more apparent. Microsoft invested in a set of extensions to GDI that would be able to fill in some of these gaps in functionality, which became GDI+. Some of these extensions included different pixel depth formats, alpha blending support in bitmap operations and brushes, anti-aliased primitive rendering and more complex primitive rendering. GDI+ also included imaging support such as the ability to open PNG and JPG files. With all of the operations that GDI+ added, though, there was no hardware acceleration support for the operations that it performed.
GDI+ enjoyed considerable popularity in the managed world because it was the workhorse of the System.Windows.Drawing namespace. Pretty much every Windows Forms application that employed custom rendering used GDI+ to do the work. But GDI+, being built on top of GDI, inherited all of the same issues with regard to Direct3D interoperability; in fact, because it was always rasterizing in software, some scenarios became even worse.
When it came time to plan Windows 7, it was clear that we needed to address the shortcomings with regard to interoperability, uneven hardware acceleration and capability. Doing this while retaining the existing APIs would have been very difficult. GDI has a very long history and a very large application compatibility space, and trying to wedge alpha blending (for example) into the core GDI API set would have been very difficult to do without risk to existing customers. Since GDI+ was built on top of GDI and had a certain preexisting contract, adding hardware acceleration to it would have been very difficult.
The solution was to create a new API that could encapsulate the functionality that we wanted, as well as take the interoperability concerns into account. The MIL code (this is the native component in WPF that does the rendering) was a convenient starting point, since it had the rendering features that were needed and provided both software rendering and hardware fallback.
One of the first things that needed to be done was to change over the rendering code to be based on D3D10.1 rather than D3D9. This decision was made since there were several other technologies being built around this version of the runtime as a basis (10level9, WARP, D3D primitive remoting), and because we see hardware built around this architecture as being the future. This allowed us to design D3D10.1 interoperability, and hence allow these other technologies to interoperate with Direct2D as well.
Another interoperability work item was leveraging work done in the window manager and in DXGI to make sure that Direct2D and GDI could work together. You can draw with Direct2D to GDI targets, as well as draw with GDI to Direct2D targets. While these features are not free from a performance perspective, they do allow applications to be built mixing the two APIs to allow people to move over to the brave new world.
A significant chunk of work that was done was to try and make the API expressive from a performance viewpoint. WPF does significant resource management on the behalf of the developer, but this is difficult to do with an immediate mode API that gives control to the developer. This might sound simple, but there are a lot of design decisions around making sure that GPU memory is not allocated without the user asking for it and still allowing people to build what they want. The design of the D2D factory and the resource / threading model that follows from it allow server side rendering to scale appropriately in a way that GDI cannot.
The way that text and imaging was approached was to leverage DirectWrite and WIC, respectively. This represents an approach that we are moving towards which is more componentized. Direct2D takes care of hardware accelerating the rasterization of DirectWrite text and hardware accelerating bitmaps taken from WIC, in a complementary fashion rather than a subsuming one.
In the end, what we have built is a hardware accelerated 2D rendering API (with software fallback) with a modern primitive rendering set that allows interoperability with previous APIs as well as the state of the art APIs. We feel that this will be a worthy replacement for GDI and GDI+ for most application development scenarios, and will also be able to complement D3D10.1 in some game development scenarios as well. The componentized fashion that was used to build the full set of technologies will also allow developers to mix and match pieces to build things that were hard to build before, such as being able to render subpixel positioned text directly into Direct3D textures with support for any font. We hope that this technology will be useful, and we would love to hear feedback on how to make it better in the future.
For more information about Direct2D, you can read the following:
MSDN Documentation: http://msdn.microsoft.com/en-us/library/dd370990(VS.85).aspx
PDC talk: http://channel9.msdn.com/pdc2008/PC18/