Archive for the ‘Direct2D’ Category

Currently documentation on Direct2D seems to be a little bit sparse. Only a few samples and not much community content exist. Here I concentrate the sources I ran across ‚til now.

Just like the code the docs also experienced a way of change during the last incarnations. In the Windows 7 Beta SDK there was compiled Help content that disappeared with the March DirectX SDK and was replaced by the online MSDN content. With the Windows 7 RC SDK offline content has reappeared, in the form of Document Explorer Help. I prefer the last-mentioned because it’s quicker as MSDN online and does not collapse sibling branches if you change to another branch.

* Samples: The sample code contained in the SDK installed folders (C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\Multimedia\Direct2D) differs from the code in the Document Explorer Help file. Be sure to check both.

Direct2D has a bag full of functions for manipulation of geometries. You can intersect polygons or unite them, test for the relation between two geometries and much more.

Sometimes you may need to get the resulting coordinates from such an operation. Or you want to use D2D as a geometric object manipulation library. This is not as easy as it should be.

From the D2D related blogs I got the hint: ‚You have to implement the sink interface and grab the data from there.‘. As there is not much documentation yet and only a handful of samples I didn’t find code so I tried to implement it myself.

But some background first.

The base interface for geometries in Direct2D is ID2D1Geometry. It has methods to operate on geometries like CombineWithGeometry, ComputeArea or Widen. These methods write the result of the operation to an ID2D1SimplifiedGeometrySink you have to provide. The geometry operation calls the sink’s methods BeginFigure, AddLines, EndFigure, Close and so on.

Normally the sink is used to create contents for a new ID2D1PathGeometry, a geometry derivate that can consist of figures and segments, just like the path objects in GDI, GDI+ or WPF. The path geometry’s Open method creates a new sink and returns it’s interface pointer so the sink can be used to fill the path. Now you can call the sink’s methods or pass the sink through to the geometry operations as mentioned above.

If you imitate an ID2D1SimplifiedGeometrySink you can give its pointer to the geometry operations and AddLines for example may be called by the geometry. As AddLines is your code, you can do what you like with the coordinates. So, let’s implement a sink. I needed a ID2D1TessellationSink because I wanted to grab the triangles created by the ID2D1GeometryTesselate method. First comes the definition of the class derived from the ID2D1TessellationSink interface in MySink.h:

My class takes an ID2D1TesselationSink pointer in the ctor that is used to pipe through the data to create a mesh (see the ID2D1Mesh interface). You can port the idea to a simplified or a normal geometry sink.

In the Windows 7 Developer training I learned that we should not test the OS version in order to check which new features can be used. We now shall test each feature individually (I think today it’s so confusing that you can’t determine which OS service pack implements which extension).

When I asked to show some examples how the test for individual features can be done I got no answer.

Today I had the problem to implement a C++ DLL that should use Direct2D if it was available. My first idea was to just use delay-load for my D2D1.DLL import. But this would not work under XP because the late load of d2d1.dll would fail.

So I decided to dynamically load Direct2D. The architecture of Direct2D comes to my aid because D2D uses the factory pattern to construct all objects. That leads to the consequence that the D2D1.DLL has few exports. Ideally it only had the D2D1CreateFactory export so it would be very easy to get it’s proc address and forget about it. Direct2D adds some helper functions that ease the handling of frequently-used structures (like D2D1InvertMatrix). In my case I was lucky because I didn’t need them so I just needed to call GetProcAddress once for D2D1CreateFactory.

I declared a global smart pointer for the factory and a HMODULE variable for the D2D1.DLL handle and then I inserted the following code into my DllMain in the DLL_PROCESS_ATTACH branch. It was a bit tricky to find the correct function prototype for D2D1CreateFactory because the docs state four different variants and the sample code uses another one.