資源類型
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也可以順利被創建。