Recently, I wrote a batch of articles on Windows Phone for the Nokia Developer Community:
The netbook is upgraded now: Samsung 250 GB hard disk and an additional 512 MB RAM. W7′s performance index (graphics) doubled to 2.0 by adding the memory. I just got an ebay hit (4x 512MB for 1,5€) so I tried that and I think it will suffice for the time being. I got a neopren cover so the netbook will survive in a backpack (hopefully).
I got a dual DVB-T USB TV receiver that is media center compatible (MSI DIGIVOX Duo). Media center runs very smooth even on such an impotent machine. The MSI drivers seem to be a bit instable because I got machine hangs several times when I switched TV on.
I just bought a netbook!
It is meant to be used by my daughter when she enters her next class in August, but I’m not sure if it will be available then (I might need it as my mobile connection to the world). We used it last weekend on a trip to Hamburg as mobile internet station. Thanks to a WiFi hotspot in the camp site I avoided to use a borrowed UMTS stick.
We are thrilled! The light device is much easier to take with you than a regular notebook but equally useful on tour. I wouldn’t want to develop on this machine but as a surf staton it’s phenomenal compared to my mobile phone.
I selected the Lenovo Ideapad S10e for price/features. I installed Windows 7 RC on a 150GB HD and it runs very smooth even with only 512MB (- shared video memory). But the memory upgrade is ordered already anyway.
The Windows 7 installation was from a 4GB USB stick I prepared from the DVD ISO image. That was a very simple task (see hints in Daniel Melanchton’s blog, in german).
The W7 performance index is 1.0 only due to the 3D graphics performance but the Intel GMA driver is bad and hopefully fixed soon. Windows Update offered to install a newer driver version and I agreed. That was a fault! After the next reboot the cursor was replaced by a big random bitmap of maybe 100×100 pixels. I had to revert to the last driver version to get my cursor back!
All other devices work fine, even ACPI is OK!
Update: An english language description of preparing a bootable USB stick for Windows 7 setup is now available here.
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.
DirectX Blog - new, not much content yet
* Forum: There is no dedicated MSDN forum yet. Some valuable help was given in the XNA forum, Direct3D subforum.
* Hands-On-Labs from the Windows 7 Developer Trainings: Sorry, can’t post. But reminds of the MSDN samples and the code in the PDC talk.
* Codeproject article: Direct2D: Hardware Acceleration in Windows 7 Plotting
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 ID2D1Geometry Tesselate method. First comes the definition of the class derived from the ID2D1TessellationSink interface in MySink.h:
class MySink : public ID2D1TessellationSink
__in_ecount(trianglesCount) CONST D2D1_TRIANGLE *triangles, UINT trianglesCount
unsigned long STDMETHODCALLTYPE AddRef();
unsigned long STDMETHODCALLTYPE Release();
HRESULT STDMETHODCALLTYPE QueryInterface(IID const& riid, void** ppvObject);
LONG volatile m_cRefCount;
And now the implementation in MySink.cpp:
MySink::MySink(ID2D1TessellationSink *pSink) : m_cRefCount(0)
m_spSink = pSink;
STDMETHODIMP_(void) MySink::AddTriangles(__in_ecount(trianglesCount) CONST D2D1_TRIANGLE *triangles, UINT trianglesCount)
// here you can copy the triangles data...
STDMETHODIMP_(unsigned long) MySink::AddRef()
STDMETHODIMP_(unsigned long) MySink::Release()
if (InterlockedDecrement(&m_cRefCount) == 0)
STDMETHODIMP MySink::QueryInterface(IID const& riid, void** ppvObject)
if (__uuidof(ID2D1TessellationSink) == riid)
*ppvObject = dynamic_cast
else if (__uuidof(IUnknown) == riid)
*ppvObject = dynamic_cast
*ppvObject = NULL;
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.
if (NULL != (hD2D1Lib = AfxLoadLibrary("D2D1.DLL")))
typedef HRESULT(STDAPICALLTYPE* FPCF)(D2D1_FACTORY_TYPE, REFIID, CONST D2D1_FACTORY_OPTIONS *, void**);
FPCF pfn = (FPCF) GetProcAddress(hD2D1Lib, "D2D1CreateFactory");
if (pfn == NULL || FAILED(pfn(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), NULL, (void**)&g_spFactory)))
g_spFactory = NULL;
hD2D1Lib = NULL;
What’s left is not to forget to call AfxFreeLibrary again in the DLL_PROCESS_DETACH branch.
In my implementation I can now simply test the g_spFactory pointer to decide if I can use Direct2D features.
I hope someone reads my thoughts on Direct2D and (maybe) other things I come across.