Guest User

Untitled

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