I am an experienced computer graphics programmer, mainly using Direct3D 9.0c, OpenGL and general algorithms. I am currently evaluating Direct2D as a rendering technology for a professional medical imaging application. As for rendering, this is an x64 desktop application in windowed mode (not in fullscreen mode).
Already with my initial steps, I am struggling with a task that, as I thought, would be no problem: rendering a single-channel bitmap on the screen.
By running Windows 8.1 on the machine, I create an ID2D1DeviceContext with a Direct3D chain buffer surface as the rendering target. A swap chain is created from the HWND format and the DXGI_FORMAT_B8G8R8A8_UNORM buffer. Note: See also code snippets at the end .
Then I create a bitmap with the pixel format DXGI_FORMAT_R8_UNORM and alpha mode D2d1_ALPHA_MODE_IGNORE . When calling DrawBitmap(...) in the device context, the debugging debugging point is "D2d DEBUG ERROR - this operation is incompatible with the pixel format of the bitmap image".
I know that this conclusion is completely clear. Also, when changing the pixel format to DXGI_FORMAT_R8G8B8A8_UNORM using DXGI_ALPHA_MODE_IGNORE everything works well and I see a bitmap. However, I just can't believe it! Graphics cards have supported single-channel textures since then - every 3D graphics application can use them without thinking twice. This happens without talking.
I tried to find something here and on Google without success. The only hint I could find was the MSDN Direct2D page with supported formats ( ). The documentation suggests - not to mention this - that DXGI_FORMAT_R8_UNORM is not really supported in bitmap format. I also find alpha mask messages (using DXGI_FORMAT_A8_UNORM ), but this is not what I need.
What am I missing, that I cannot convince Direct2D to create and draw a bitmap in grayscale? Or is it true that Direct2D does not support drawing bitmaps of R8 or R16?
Any help is really appreciated as I do not know how to solve it. If I cannot get these trivial basics to work, I think I will have to stop digging deeper into Direct2D: - (.
And here are the code fragments of relevance. Note that they may not compile since I have ported this on the fly from my C ++ / CLI code to plain C ++. In addition, I dropped all error checking and other noises:
Creating a device, device context, and creating swap chains (D3D and Direct2D):
// Direct2D factory creation D2D1_FACTORY_OPTIONS options = {}; options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; ID2D1Factory1* d2dFactory; D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, options, &d2dFactory); // Direct3D device creation const auto type = D3D_DRIVER_TYPE_HARDWARE; const auto flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; ID3D11Device* d3dDevice; D3D11CreateDevice(nullptr, type, nullptr, flags, nullptr, 0, D3D11_SDK_VERSION, &d3dDevice, nullptr, nullptr); // Direct2D device creation IDXGIDevice* dxgiDevice; d3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice)); ID2D1Device* d2dDevice; d2dFactory->CreateDevice(dxgiDevice, &d2dDevice); // Swap chain creation DXGI_SWAP_CHAIN_DESC1 desc = {}; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; desc.SampleDesc.Count = 1; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferCount = 2; IDXGIAdapter* dxgiAdapter; dxgiDevice->GetAdapter(&dxgiAdapter); IDXGIFactory2* dxgiFactory; dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&dxgiFactory)); IDXGISwapChain1* swapChain; dxgiFactory->CreateSwapChainForHwnd(d3dDevice, hwnd, &swapChainDesc, nullptr, nullptr, &swapChain); // Direct2D device context creation const auto options = D2D1_DEVICE_CONTEXT_OPTIONS_NONE; ID2D1DeviceContext* deviceContext; d2dDevice->CreateDeviceContext(options, &deviceContext); // create render target bitmap from swap chain IDXGISurface* swapChainSurface; swapChain->GetBuffer(0, __uuidof(swapChainSurface), reinterpret_cast<void **>(&swapChainSurface)); D2D1_BITMAP_PROPERTIES1 bitmapProperties; bitmapProperties.dpiX = 0.0f; bitmapProperties.dpiY = 0.0f; bitmapProperties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW; bitmapProperties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM; bitmapProperties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; bitmapProperties.colorContext = nullptr; ID2D1Bitmap1* swapChainBitmap = nullptr; deviceContext->CreateBitmapFromDxgiSurface(swapChainSurface, &bitmapProperties, &swapChainBitmap); // set swap chain bitmap as render target of D2D device context deviceContext->SetTarget(swapChainBitmap);
Create a single-channel D2D bitmap:
const D2D1_SIZE_U size = { 512, 512 }; const UINT32 pitch = 512; D2D1_BITMAP_PROPERTIES1 d2dProperties; ZeroMemory(&d2dProperties, sizeof(D2D1_BITMAP_PROPERTIES1)); d2dProperties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE; d2dProperties.pixelFormat.format = DXGI_FORMAT_R8_UNORM; char* sourceData = new char[512*512]; ID2D1Bitmap1* d2dBitmap; deviceContext->DeviceContextPointer->CreateBitmap(size, sourceData, pitch, d2dProperties, &d2dBitmap);
Bitmap Image (FAILING):
deviceContext->BeginDraw(); D2D1_COLOR_F d2dColor = {}; deviceContext->Clear(d2dColor);