DxgiAPI.cpp
1 #include "pch.h" 2 3 #include "DxgiAPI.h" 4 5 #include <common/Display/dpi_aware.h> 6 7 //#define DEBUG_DEVICES 8 #define SEPARATE_D3D_FOR_CAPTURE 9 10 namespace 11 { 12 DxgiAPI::D3D CreateD3D() 13 { 14 DxgiAPI::D3D d3d; 15 UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; 16 #if defined(DEBUG_DEVICES) 17 flags |= D3D11_CREATE_DEVICE_DEBUG; 18 #endif 19 HRESULT hr = 20 D3D11CreateDevice(nullptr, 21 D3D_DRIVER_TYPE_HARDWARE, 22 nullptr, 23 flags, 24 nullptr, 25 0, 26 D3D11_SDK_VERSION, 27 d3d.d3dDevice.put(), 28 nullptr, 29 nullptr); 30 if (hr == DXGI_ERROR_UNSUPPORTED) 31 { 32 hr = D3D11CreateDevice(nullptr, 33 D3D_DRIVER_TYPE_WARP, 34 nullptr, 35 flags, 36 nullptr, 37 0, 38 D3D11_SDK_VERSION, 39 d3d.d3dDevice.put(), 40 nullptr, 41 nullptr); 42 } 43 winrt::check_hresult(hr); 44 45 d3d.dxgiDevice = d3d.d3dDevice.as<IDXGIDevice>(); 46 winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice(d3d.dxgiDevice.get(), d3d.d3dDeviceInspectable.put())); 47 48 winrt::com_ptr<IDXGIAdapter> adapter; 49 winrt::check_hresult(d3d.dxgiDevice->GetParent(winrt::guid_of<IDXGIAdapter>(), adapter.put_void())); 50 winrt::check_hresult(adapter->GetParent(winrt::guid_of<IDXGIFactory2>(), d3d.dxgiFactory2.put_void())); 51 52 d3d.d3dDevice->GetImmediateContext(d3d.d3dContext.put()); 53 winrt::check_bool(d3d.d3dContext); 54 auto contextMultithread = d3d.d3dContext.as<ID3D11Multithread>(); 55 contextMultithread->SetMultithreadProtected(true); 56 57 return d3d; 58 } 59 } 60 61 DxgiAPI::DxgiAPI() 62 { 63 const D2D1_FACTORY_OPTIONS d2dFactoryOptions = { 64 #if defined(DEBUG_DEVICES) 65 D2D1_DEBUG_LEVEL_INFORMATION 66 #else 67 D2D1_DEBUG_LEVEL_NONE 68 #endif 69 }; 70 71 winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, d2dFactoryOptions, d2dFactory2.put())); 72 73 winrt::check_hresult(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, 74 winrt::guid_of<IDWriteFactory>(), 75 reinterpret_cast<IUnknown**>(writeFactory.put()))); 76 77 auto d3d = CreateD3D(); 78 d3dDevice = d3d.d3dDevice; 79 dxgiDevice = d3d.dxgiDevice; 80 d3dDeviceInspectable = d3d.d3dDeviceInspectable; 81 dxgiFactory2 = d3d.dxgiFactory2; 82 d3dContext = d3d.d3dContext; 83 #if defined(SEPARATE_D3D_FOR_CAPTURE) 84 auto d3dFC = CreateD3D(); 85 d3dForCapture = d3dFC; 86 #else 87 d3dForCapture = d3d; 88 #endif 89 winrt::check_hresult(d2dFactory2->CreateDevice(dxgiDevice.get(), d2dDevice1.put())); 90 winrt::check_hresult(DCompositionCreateDevice( 91 dxgiDevice.get(), 92 winrt::guid_of<IDCompositionDevice>(), 93 compositionDevice.put_void())); 94 } 95 96 DxgiWindowState DxgiAPI::CreateD2D1RenderTarget(HWND window) const 97 { 98 RECT rect = {}; 99 winrt::check_bool(GetClientRect(window, &rect)); 100 101 const DXGI_SWAP_CHAIN_DESC1 desc = { 102 .Width = static_cast<UINT>(rect.right - rect.left), 103 .Height = static_cast<UINT>(rect.bottom - rect.top), 104 .Format = static_cast<DXGI_FORMAT>(winrt::DirectXPixelFormat::B8G8R8A8UIntNormalized), 105 .SampleDesc = { .Count = 1, .Quality = 0 }, 106 .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT, 107 .BufferCount = 2, 108 .Scaling = DXGI_SCALING_STRETCH, 109 .SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD, 110 .AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED, 111 }; 112 113 DxgiWindowState state; 114 winrt::com_ptr<ID2D1DeviceContext> rt; 115 d2dDevice1->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, rt.put()); 116 state.rt = rt; 117 118 winrt::check_hresult(dxgiFactory2->CreateSwapChainForComposition(d3dDevice.get(), 119 &desc, 120 nullptr, 121 state.swapChain.put())); 122 winrt::com_ptr<IDXGISurface> surface; 123 winrt::check_hresult(state.swapChain->GetBuffer(0, winrt::guid_of<IDXGISurface>(), surface.put_void())); 124 125 const D2D1_BITMAP_PROPERTIES1 properties = { 126 .pixelFormat = { .format = DXGI_FORMAT_B8G8R8A8_UNORM, .alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED }, 127 .bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW 128 }; 129 winrt::com_ptr<ID2D1Bitmap1> bitmap; 130 winrt::check_hresult(rt->CreateBitmapFromDxgiSurface(surface.get(), 131 properties, 132 bitmap.put())); 133 rt->SetTarget(bitmap.get()); 134 winrt::check_hresult(compositionDevice->CreateTargetForHwnd(window, 135 true, 136 state.compositionTarget.put())); 137 138 winrt::com_ptr<IDCompositionVisual> visual; 139 winrt::check_hresult(compositionDevice->CreateVisual(visual.put())); 140 winrt::check_hresult(visual->SetContent(state.swapChain.get())); 141 winrt::check_hresult(state.compositionTarget->SetRoot(visual.get())); 142 winrt::check_hresult(compositionDevice->Commit()); 143 144 return state; 145 }