| name | direct2d-rendering |
| description | Direct2D and DirectWrite graphics rendering patterns for Windows. Use when implementing 2D graphics, text rendering, hardware-accelerated drawing, handling device loss, or working with ID2D1DeviceContext. |
| metadata | {"author":"RedSalamander","version":"1.0"} |
Direct2D/DirectWrite Rendering
Graphics Stack
- Direct2D 1.1 - Hardware-accelerated 2D graphics
- DirectWrite - Advanced text rendering
- Direct3D 11 - GPU resources and swap chain
- DXGI 1.3 - Display management
Key Patterns
Creating Resources
wil::com_ptr<ID2D1SolidColorBrush> _brush;
THROW_IF_FAILED(_d2dContext->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black), &_brush));
BeginDraw/EndDraw with RAII
{
HRESULT hr = S_OK;
{
_d2dContext->BeginDraw();
auto endDraw = wil::scope_exit([&] { hr = _d2dContext->EndDraw(); });
_d2dContext->Clear(D2D1::ColorF(1.0f, 1.0f, 1.0f));
}
if (hr == D2DERR_RECREATE_TARGET)
{
RecreateDeviceResources();
}
}
Text with DirectWrite
wil::com_ptr<IDWriteTextLayout> layout;
THROW_IF_FAILED(_dwriteFactory->CreateTextLayout(
text.c_str(), static_cast<UINT32>(text.length()),
_textFormat.get(), maxWidth, maxHeight, &layout));
_d2dContext->DrawTextLayout(D2D1::Point2F(x, y), layout.get(), _brush.get());
Best Practices
- Validate device state before rendering
- Handle D2DERR_RECREATE_TARGET for device loss
- Cache brushes and layouts - minimize recreation
- Use dirty region updates for performance
- Handle DPI changes - recalculate layouts
DPI Awareness
void OnDpiChanged(UINT dpi)
{
_d2dContext->SetDpi(static_cast<float>(dpi), static_cast<float>(dpi));
IconCache::SetDpi(dpi);
RecreateDeviceDependentResources();
}
In this repo, DPI handling for retained DirectX UI should follow one shared invalidation path:
- top-level hosts handle
WM_DPICHANGED,
- child or hybrid windows with DPI-sensitive chrome also handle
WM_DPICHANGED_AFTERPARENT,
- the handler refreshes D2D DPI, invalidates cached text/layout/popup metrics, reapplies layout, and repaints,
- popup surfaces and other retained overlays should recompute geometry instead of requiring close/reopen after a DPI transition.
Text Rendering (ColorTextView)
- Use
IDWriteTextLayout for complex text scenarios
- Implement virtualization for large documents
- Cache frequently used resources (brushes, layouts)
- Handle Unicode properly with UTF-16 encoding
- Optimize for smooth scrolling with async layout updates
Performance Considerations
- Async Operations: Use thread pools for heavy computations
- Caching: Implement LRU caches for expensive resources
- Memory: Monitor usage, implement cleanup strategies
- Rendering: Use offscreen rendering and dirty region updates
- Measurements: Profile performance-critical paths
For rendering-path changes in this repo, profiling is not a post-hoc suggestion. New rendering work or rendering optimizations should:
- name the user-visible scenario,
- add or reuse instrumentation,
- use deterministic selftest coverage where practical,
- archive validation runs under
Specs/TestRuns/,
- if the work closes a plan, move that plan to
Specs/Plans/Done/ and merge the lasting rendering contract into the authoritative spec.
Device Loss Handling
HRESULT hr = _d2dContext->EndDraw();
if (hr == D2DERR_RECREATE_TARGET) {
DiscardDeviceResources();
CreateDeviceResources();
} else if (FAILED(hr)) {
Debug::Error(L"EndDraw failed: {:#x}", hr);
}