Direct2D中资源的创建顺序
资源类型
Direct2D中有两种类型的资源,设备无关资源和设备相关资源,设备无关的资源可以一次创建,永久使用(在程序生存期内),且通常创建于系统内存中,设备相关的资源和设备有相同的生命周期,一旦设备丢失,则资源也需重建。这类资源一般在显存中创建。
设备无关的资源包括
- ID2D1DrawingStateBlock
- ID2D1Factory
- ID2D1Geometry及继承自它的接口
- ID2D1GeometrySink和ID2D1SimplifiedGeometrySink
- ID2D1StrokeStyle
设备相关的资源包括
- ID2D1Brush及继承自它的接口
- ID2D1Layer
- ID2D1RenderTarget及继承自它的接口
创建顺序
通常来说,先创建设备无关的资源,再创建设备相关的资源,因为ID2D1Factory是设备无关的资源,也是所有其他D2D资源的创建者。包括ID2D1RenderTarget。
一个案例
先看下面的代码,这段代码创建窗口,然后调用函数CreateDeviceIndependentResources创建设备无关的资源,其中包括ID2D1Factory。
HWND hwnd = CreateWindowEx(NULL, L"DirectWrite Hello, World", // window class name L"Draw Text", // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position 600, // initial x size 600, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; CreateDeviceIndependentResources(hwnd);
下面这段代码响应WM_PAINT消息,调用Render函数来绘制字体。
switch (message) { case WM_PAINT: Render(hwnd); ValidateRect(hwnd, NULL) ; return 0 ;
Render函数中调用CreateDeviceDependentResources,该函数创建设备相关的资源,包括ID2D1RenderTarget。
VOID Render(HWND hwnd) { // Create device dependent resources CreateDeviceDependentResources(hwnd); g_pRT->BeginDraw(); g_pRT->SetTransform(D2D1::IdentityMatrix()); g_pRT->Clear(D2D1::ColorF(D2D1::ColorF::White)); DrawText(hwnd); g_pRT->EndDraw(); }
这段代码是有问题的,因为CreateDeviceDependentResources在CreateDeviceIndependentResources之前被调用了,这是因为在调用函数UpdateWindow时,系统就发出了WM_PAINT消息,从而激发Render函数被调用,继而CreateDeviceDependentResources函数被调用。但是这时CreateDeviceIndependentResources还未被调用,所以导致ID2D1Factory还不存在的时候,ID2D1RenderTarget就要创建,这肯定是错误的,因为后者是由前者创建的。
修复
将CreateDeviceIndependentResources放到函数UpdateWindow之前调用。这样,在UpdateWindw函数发出WM_PAINT消息时,ID2D1Factory已经创建好了,所以ID2D1RenderTarget也可以顺利被创建。