Advertisement
Guest User

Untitled

a guest
Oct 4th, 2022
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.24 KB | None | 0 0
  1. #ifndef UNICODE
  2. #define UNICODE
  3. #endif
  4.  
  5. #include <Windows.h>
  6. #include <d2d1_1.h>
  7. #include <dwrite_1.h>
  8. #include <d3d11_1.h>
  9. #include <d2d1effects.h>
  10.  
  11. #pragma comment(lib, "d2d1.lib")
  12. #pragma comment(lib, "dwrite.lib")
  13. #pragma comment(lib, "d3d11.lib")
  14. #pragma comment(lib, "dxguid.lib")
  15.  
  16. #define DEBUG
  17.  
  18. template <class T> void SafeRelease(T** ppT) {
  19.     if (*ppT) {
  20.         (*ppT)->Release();
  21.         *ppT = nullptr;
  22.     }
  23. }
  24.  
  25. class MainWindow {
  26. public:
  27.     struct {
  28.         HWND hwnd;
  29.  
  30.         ID2D1Factory1* d2dFactory;
  31.         IDWriteFactory1* dwriteFactory;
  32.  
  33.         ID3D11Device1* d3dDevice;
  34.         ID3D11DeviceContext1* d3dDeviceContext;
  35.         ID2D1Device* d2dDevice;
  36.         ID2D1DeviceContext* d2dDeviceContext;
  37.         ID2D1Bitmap1* d2dTargetBitmap;
  38.         IDXGIDevice1* dxgiDevice;
  39.         IDXGISwapChain1* dxgiSwapChain;
  40.  
  41.         ID2D1BitmapRenderTarget* d2dBitmapRenderTarget;
  42.         ID2D1Bitmap* d2dBitmap;
  43.         ID2D1Effect* d2dEffect;
  44.  
  45.         IDWriteTextFormat* textFormat;
  46.         PCWSTR text;
  47.         ID2D1SolidColorBrush* defaultBrush;
  48.     } state;
  49.  
  50.     PCWSTR w_className = L"direct2d_template_MainWindow_class";
  51.     PCWSTR w_title = L"Direct2D Template";
  52.  
  53.     MainWindow() : state({ }) {
  54.         ZeroMemory(&state, sizeof(state));
  55.     }
  56.  
  57.     static LRESULT CALLBACK WindowProcedure(
  58.         HWND hwnd,
  59.         UINT msg,
  60.         WPARAM wparam,
  61.         LPARAM lparam
  62.     ) {
  63.         MainWindow* win = nullptr;
  64.  
  65.         if (msg == WM_CREATE) {
  66.             CREATESTRUCT* pCreate = (CREATESTRUCT*) lparam;
  67.             win = (MainWindow*) pCreate->lpCreateParams;
  68.             SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR) win);
  69.  
  70.             if (FAILED(D2D1CreateFactory(
  71.                 D2D1_FACTORY_TYPE_SINGLE_THREADED,
  72.                 __uuidof(ID2D1Factory1),
  73.                 reinterpret_cast<void**>(&win->state.d2dFactory)
  74.             ))) return -1;
  75.  
  76.             if (FAILED(DWriteCreateFactory(
  77.                 DWRITE_FACTORY_TYPE_SHARED,
  78.                 __uuidof(IDWriteFactory1),
  79.                 reinterpret_cast<IUnknown**>(&win->state.dwriteFactory)
  80.             ))) return -1;
  81.  
  82.             if (!win->CreateDirect3DDevice()) return -1;
  83.             if (!win->CreateDirect2DDevice()) return -1;
  84.             if (!win->CreateSwapChain(hwnd)) return -1;
  85.             if (!win->ConfigureSwapChain(hwnd)) return -1;
  86.  
  87.             if (FAILED(win->state.dwriteFactory->CreateTextFormat(
  88.                 L"Work Sans",
  89.                 nullptr,
  90.                 DWRITE_FONT_WEIGHT_NORMAL,
  91.                 DWRITE_FONT_STYLE_NORMAL,
  92.                 DWRITE_FONT_STRETCH_NORMAL,
  93.                 13.2f,
  94.                 L"en-us",
  95.                 &win->state.textFormat
  96.             ))) return -1;
  97.  
  98.             if (!win->CreateBrushes()) return -1;
  99.  
  100.             if (FAILED(win->state.d2dDeviceContext->CreateEffect(
  101.                 CLSID_D2D1GaussianBlur, &win->state.d2dEffect
  102.             ))) return -1;
  103.  
  104.             return 0;
  105.         } else {
  106.             win = (MainWindow*) GetWindowLongPtrW(hwnd, GWLP_USERDATA);
  107.         }
  108.  
  109.         switch (msg) {
  110.             case WM_PAINT: {
  111.                 if (!win->HandlePaint()) {
  112. #ifdef DEBUG
  113.                     OutputDebugStringW(L"Error: Failed to handle WM_PAINT.\n");
  114. #endif
  115.                     return 1;
  116.                 }
  117.                 return 0;
  118.             }
  119.             case WM_SIZE: {
  120.                 if (!win->HandleResize(LOWORD(lparam), HIWORD(lparam))) {
  121. #ifdef DEBUG
  122.                     OutputDebugStringW(L"Error: Failed to handle WM_PAINT.\n");
  123. #endif
  124.                     return 1;
  125.                 }
  126.                 return 0;
  127.             }
  128.             case WM_DESTROY: {
  129.                 PostQuitMessage(0);
  130.                 return 0;
  131.             }
  132.             default:
  133.                 return DefWindowProcW(hwnd, msg, wparam, lparam);
  134.         }
  135.     }
  136.  
  137.     bool Init(HINSTANCE hInstance, int nCmdShow) {
  138.         WNDCLASSEXW wclass = { };
  139.         ZeroMemory(&wclass, sizeof(wclass));
  140.  
  141.         wclass.cbSize = sizeof(WNDCLASSEX);
  142.         wclass.hInstance = hInstance;
  143.         wclass.lpszClassName = w_className;
  144.         wclass.lpfnWndProc = MainWindow::WindowProcedure;
  145.  
  146.         if (RegisterClassExW(&wclass) == 0) {
  147. #ifdef DEBUG
  148.             OutputDebugStringW(L"Error: Failed to register window class.\n");
  149. #endif
  150.             return false;
  151.         }
  152.  
  153.         state.hwnd = CreateWindowExW(
  154.             0,
  155.             w_className,
  156.             w_title,
  157.             WS_OVERLAPPEDWINDOW,
  158.             CW_USEDEFAULT, CW_USEDEFAULT,
  159.             420, 320,
  160.             NULL,
  161.             NULL,
  162.             hInstance,
  163.             this
  164.         );
  165.  
  166.         if (state.hwnd == NULL) {
  167. #ifdef DEBUG
  168.             OutputDebugStringW(L"Error: Failed to create window.\n");
  169. #endif
  170.             return false;
  171.         }
  172.  
  173.         ShowWindow(state.hwnd, nCmdShow);
  174.  
  175.         return true;
  176.     }
  177.  
  178.     void MainLoop() {
  179.         MSG msg = { };
  180.  
  181.         while (true) {
  182.             if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  183.                 if (msg.message == WM_QUIT)
  184.                     break;
  185.  
  186.                 TranslateMessage(&msg);
  187.                 DispatchMessageW(&msg);
  188.             }
  189.         }
  190.     };
  191.  
  192.     bool CreateDirect3DDevice() {
  193.         if (!state.d3dDevice || !state.d3dDeviceContext) {
  194.             D3D_FEATURE_LEVEL d3dFeatureLevels[] = {
  195.                 D3D_FEATURE_LEVEL_11_1,
  196.                 D3D_FEATURE_LEVEL_11_0,
  197.                 D3D_FEATURE_LEVEL_10_1,
  198.                 D3D_FEATURE_LEVEL_10_0,
  199.                 D3D_FEATURE_LEVEL_9_3,
  200.                 D3D_FEATURE_LEVEL_9_2,
  201.                 D3D_FEATURE_LEVEL_9_1
  202.             };
  203.  
  204.             D3D_FEATURE_LEVEL d3dSupportedFeatureLevel;
  205.  
  206.             ID3D11Device* temp_d3dDevice;
  207.             ID3D11DeviceContext* temp_d3dDeviceContext;
  208.  
  209.             if (FAILED(D3D11CreateDevice(
  210.                 nullptr,
  211.                 D3D_DRIVER_TYPE_HARDWARE,
  212.                 NULL,
  213.                 D3D11_CREATE_DEVICE_BGRA_SUPPORT,
  214.                 d3dFeatureLevels,
  215.                 ARRAYSIZE(d3dFeatureLevels),
  216.                 D3D11_SDK_VERSION,
  217.                 &temp_d3dDevice,
  218.                 &d3dSupportedFeatureLevel,
  219.                 &temp_d3dDeviceContext
  220.             ))) return false;
  221.  
  222.             if (FAILED(temp_d3dDevice->QueryInterface(
  223.                 IID_PPV_ARGS(&state.d3dDevice)
  224.             ))) return false;
  225.  
  226.             if (FAILED(temp_d3dDeviceContext->QueryInterface(
  227.                 IID_PPV_ARGS(&state.d3dDeviceContext)
  228.             ))) return false;
  229.         }
  230.  
  231.         return true;
  232.     }
  233.  
  234.     bool CreateDirect2DDevice() {
  235.         if (!state.dxgiDevice) {
  236.             if (!state.d3dDevice) return false;
  237.  
  238.             if (FAILED(state.d3dDevice->QueryInterface(
  239.                 IID_PPV_ARGS(&state.dxgiDevice)
  240.             ))) return false;
  241.         }
  242.  
  243.         if (!state.d2dDevice) {
  244.             if (FAILED(state.d2dFactory->CreateDevice(
  245.                 state.dxgiDevice,
  246.                 &state.d2dDevice
  247.             ))) return false;
  248.         }
  249.  
  250.         if (!state.d2dDeviceContext) {
  251.             if (FAILED(state.d2dDevice->CreateDeviceContext(
  252.                 D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
  253.                 &state.d2dDeviceContext
  254.             ))) return false;
  255.  
  256.             state.d2dDeviceContext->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
  257.             state.d2dDeviceContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_DEFAULT);
  258.         }
  259.  
  260.         return true;
  261.     }
  262.  
  263.     bool CreateSwapChain(HWND hwnd) {
  264.         if (!state.dxgiSwapChain) {
  265.             DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { };
  266.  
  267.             swapChainDesc.Width = 0;
  268.             swapChainDesc.Height = 0;
  269.             swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
  270.             swapChainDesc.BufferCount = 2;
  271.             swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  272.             swapChainDesc.SampleDesc.Count = 1;
  273.             swapChainDesc.SampleDesc.Quality = 0;
  274.             swapChainDesc.Stereo = false;
  275.             swapChainDesc.Flags = 0;
  276.             swapChainDesc.Scaling = DXGI_SCALING_NONE;
  277.             swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
  278.  
  279.             IDXGIAdapter* dxgiAdapter;
  280.             if (FAILED(state.dxgiDevice->GetAdapter(&dxgiAdapter))) return false;
  281.  
  282.             IDXGIFactory2* dxgiFactory;
  283.             if (FAILED(dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory)))) return false;
  284.  
  285.             if (FAILED(dxgiFactory->CreateSwapChainForHwnd(
  286.                 state.d3dDevice,
  287.                 hwnd,
  288.                 &swapChainDesc,
  289.                 nullptr,
  290.                 nullptr,
  291.                 &state.dxgiSwapChain
  292.             ))) return false;
  293.  
  294.             state.dxgiDevice->SetMaximumFrameLatency(1);
  295.  
  296.             SafeRelease(&dxgiFactory);
  297.             SafeRelease(&dxgiAdapter);
  298.         }
  299.  
  300.         return true;
  301.     }
  302.  
  303.     bool ConfigureSwapChain(HWND hwnd) {
  304.         if (state.dxgiSwapChain) {
  305.             UINT dpi = GetDpiForWindow(hwnd);
  306.  
  307.             D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(
  308.                 D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
  309.                 D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
  310.                 dpi,
  311.                 dpi,
  312.                 nullptr
  313.             );
  314.  
  315.             IDXGISurface* dxgiSurface = nullptr;
  316.             if (FAILED(state.dxgiSwapChain->GetBuffer(
  317.                 0,
  318.                 IID_PPV_ARGS(&dxgiSurface)
  319.             ))) return false;
  320.  
  321.             if (FAILED(state.d2dDeviceContext->CreateBitmapFromDxgiSurface(
  322.                 dxgiSurface,
  323.                 bitmapProperties,
  324.                 &state.d2dTargetBitmap
  325.             ))) return false;
  326.  
  327.             state.d2dDeviceContext->SetTarget(state.d2dTargetBitmap);
  328.  
  329.             SafeRelease(&dxgiSurface);
  330.         }
  331.  
  332.         return true;
  333.     }
  334.  
  335.     bool HandlePaint() {
  336.         PAINTSTRUCT ps;
  337.         BeginPaint(state.hwnd, &ps);
  338.  
  339.         if (state.d2dDeviceContext && state.dxgiSwapChain) {
  340.             state.d2dDeviceContext->BeginDraw();
  341.             // Begin Draw
  342.  
  343.             state.d2dDeviceContext->Clear(D2D1::ColorF(1, 1, 1, 1));
  344.  
  345.             PCWSTR text = L"ใƒ†ใ‚นใƒˆ";
  346.  
  347.             D2D1_SIZE_F clientSize = state.d2dDeviceContext->GetSize();
  348.  
  349.             state.d2dDeviceContext->DrawTextW(
  350.                 text,
  351.                 wcslen(text),
  352.                 state.textFormat,
  353.                 D2D1::RectF(10, 10, 100, 100),
  354.                 state.defaultBrush
  355.             );
  356.  
  357.             if (FAILED(state.d2dDeviceContext->CreateCompatibleRenderTarget(
  358.                 &state.d2dBitmapRenderTarget
  359.             ))) return false;
  360.  
  361.             if (FAILED(state.d2dBitmapRenderTarget->GetBitmap(
  362.                 &state.d2dBitmap
  363.             ))) return false;
  364.  
  365.             state.d2dEffect->SetInput(0, state.d2dBitmap);
  366.             state.d2dEffect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, 32.0f);
  367.  
  368.             state.d2dDeviceContext->DrawImage(state.d2dEffect);
  369.  
  370.             // End Draw
  371.             HRESULT hresult = state.d2dDeviceContext->EndDraw();
  372.  
  373.             SafeRelease(&state.d2dBitmapRenderTarget);
  374.  
  375.             if (FAILED(hresult)) {
  376.                 if (hresult == D2DERR_RECREATE_TARGET) {
  377.                     state.d2dDeviceContext->SetTarget(nullptr);
  378.                     SafeRelease(&state.d2dDeviceContext);
  379.  
  380.                     if (!CreateDirect2DDevice()) return false;
  381.                     if (!CreateSwapChain(state.hwnd)) return false;
  382.                     if (!ConfigureSwapChain(state.hwnd)) return false;
  383.                 }
  384.  
  385.                 return false;
  386.             }
  387.  
  388.             state.dxgiSwapChain->Present(1, 0);
  389.         }
  390.  
  391.         EndPaint(state.hwnd, &ps);
  392.         return true;
  393.     }
  394.  
  395.     bool HandleResize(UINT nwidth, UINT nheight) {
  396.         if (state.dxgiSwapChain) {
  397.             state.d2dDeviceContext->SetTarget(nullptr);
  398.             SafeRelease(&state.d2dTargetBitmap);
  399.  
  400.             HRESULT hresult = state.dxgiSwapChain->ResizeBuffers(
  401.                 2,
  402.                 nwidth,
  403.                 nheight,
  404.                 DXGI_FORMAT_B8G8R8A8_UNORM,
  405.                 0
  406.             );
  407.  
  408.             if (hresult == DXGI_ERROR_DEVICE_REMOVED || hresult == DXGI_ERROR_DEVICE_RESET) {
  409.                 if (!CreateDirect3DDevice()) return false;
  410.                 if (!CreateDirect2DDevice()) return false;
  411.                 if (!CreateSwapChain(state.hwnd)) return false;
  412.             }
  413.  
  414.             ConfigureSwapChain(state.hwnd);
  415.  
  416.             InvalidateRect(state.hwnd, NULL, FALSE);
  417.         }
  418.         return true;
  419.     }
  420.  
  421.     bool CreateBrushes() {
  422.         if (FAILED(state.d2dDeviceContext->CreateSolidColorBrush(
  423.             D2D1::ColorF(0, 0, 0, 1),
  424.             &state.defaultBrush
  425.         ))) return false;
  426.  
  427.         return true;
  428.     }
  429.  
  430.     void DiscardBrushes() {
  431.         SafeRelease(&state.defaultBrush);
  432.     }
  433. };
  434.  
  435. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int nCmdShow) {
  436.     MainWindow* win = new MainWindow;
  437.  
  438.     if (!win->Init(hInstance, nCmdShow)) {
  439. #ifdef DEBUG
  440.         OutputDebugStringW(L"Error: Failed to initialize window.\n");
  441. #endif
  442.         return 1;
  443.     }
  444.  
  445.     win->MainLoop();
  446.  
  447.     return 0;
  448. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement