Created
March 22, 2019 15:35
-
-
Save yuyoyuppe/ee6afa12e7a72db122a9aca0d449ae76 to your computer and use it in GitHub Desktop.
Proof of concept that ... DXGI_ALPHA_MODE_PREMULTIPLIED doesn't work. Just use small borderless window and set bg_color to rgba(x,x,x,1)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef UNICODE | |
#define UNICODE | |
#endif | |
#include <windows.h> | |
#pragma comment(lib, "user32.lib") | |
#include <wrl.h> | |
#include <dxgi1_3.h> | |
#include <d3d11_2.h> | |
#include <d2d1_2.h> | |
#include <d2d1_2helper.h> | |
#include <dcomp.h> | |
#define DIRECTINPUT_VERSION 0x0800 | |
#include <dinput.h> | |
#include <tchar.h> | |
#include <imgui.h> | |
#include <imgui_impl_win32.h> | |
#include <imgui_impl_dx11.h> | |
#pragma comment(lib, "dxgi") | |
#pragma comment(lib, "d3d11") | |
#pragma comment(lib, "d2d1") | |
#pragma comment(lib, "dcomp") | |
using Microsoft::WRL::ComPtr; | |
#include <dbghelp.h> | |
#include <shellapi.h> | |
#include <shlobj.h> | |
#include <strsafe.h> | |
#include <cstdlib> | |
#include <vector> | |
struct ComException | |
{ | |
HRESULT result; | |
ComException(HRESULT const value) : | |
result(value) | |
{} | |
}; | |
void HR(HRESULT const result) | |
{ | |
if(S_OK != result) | |
{ | |
throw ComException(result); | |
} | |
} | |
// Data | |
static ComPtr<ID3D11Device> g_pd3dDevice = NULL; | |
static ComPtr<ID3D11DeviceContext> g_pd3dDeviceContext = NULL; | |
static ComPtr<IDXGISwapChain1> g_pSwapChain = NULL; | |
static ComPtr<ID3D11RenderTargetView> g_mainRenderTargetView = NULL; | |
// Forward declarations of helper functions | |
void CleanupDeviceD3D(); | |
void CreateRenderTarget(); | |
void CleanupRenderTarget(); | |
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); | |
void GetAllWindowsFromProcessID(DWORD dwProcessID, std::vector<HWND> &vhWnds) | |
{ | |
// find all hWnds (vhWnds) associated with a process id (dwProcessID) | |
HWND hCurWnd = NULL; | |
do | |
{ | |
hCurWnd = FindWindowEx(NULL, hCurWnd, NULL, NULL); | |
DWORD dwProcessID = 0; | |
GetWindowThreadProcessId(hCurWnd, &dwProcessID); | |
if(dwProcessID == dwProcessID) | |
{ | |
vhWnds.push_back(hCurWnd); // add the found hCurWnd to the vector | |
break; | |
} | |
} while(hCurWnd != NULL); | |
} | |
int __stdcall wWinMain(HINSTANCE module, HINSTANCE, PWSTR, int) | |
{ | |
WNDCLASS wc = {}; | |
wc.hCursor = LoadCursor(nullptr, IDC_ARROW); | |
wc.hInstance = module; | |
wc.lpszClassName = L"window"; | |
wc.style = CS_HREDRAW | CS_VREDRAW; | |
wc.lpfnWndProc = WndProc; | |
RegisterClass(&wc); | |
HWND const hwnd = CreateWindowEx(WS_EX_NOREDIRECTIONBITMAP | WS_EX_OVERLAPPEDWINDOW /*| WS_EX_TRANSPARENT | WS_EX_LAYERED click-through, but always*/, | |
wc.lpszClassName, L"title", | |
WS_POPUP, | |
0, 0, | |
1920, 1080, | |
nullptr, nullptr, module, nullptr); | |
HR(D3D11CreateDevice(nullptr, // Adapter | |
D3D_DRIVER_TYPE_HARDWARE, | |
nullptr, // Module | |
D3D11_CREATE_DEVICE_BGRA_SUPPORT, | |
nullptr, 0, // Highest available feature level | |
D3D11_SDK_VERSION, | |
g_pd3dDevice.GetAddressOf(), | |
nullptr, // Actual feature level | |
g_pd3dDeviceContext.GetAddressOf())); // Device context | |
ComPtr<IDXGIDevice> dxgiDevice; | |
HR(g_pd3dDevice.As(&dxgiDevice)); | |
ComPtr<IDXGIFactory2> dxFactory; | |
HR(CreateDXGIFactory2( | |
DXGI_CREATE_FACTORY_DEBUG, | |
__uuidof(dxFactory), | |
reinterpret_cast<void **>(dxFactory.GetAddressOf()))); | |
DXGI_SWAP_CHAIN_DESC1 description = {}; | |
description.Format = DXGI_FORMAT_B8G8R8A8_UNORM; | |
description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; | |
description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; | |
description.BufferCount = 3; | |
description.SampleDesc.Count = 1; | |
description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED; | |
description.Scaling = DXGI_SCALING_STRETCH; | |
description.SampleDesc.Quality = 0; | |
description.Width = 1920; | |
description.Height = 1080; | |
HR(dxFactory->CreateSwapChainForComposition(dxgiDevice.Get(), | |
&description, | |
nullptr, // Don’t restrict | |
g_pSwapChain.GetAddressOf())); | |
// Create a single-threaded Direct2D factory with debugging information | |
ComPtr<ID2D1Factory2> d2Factory; | |
D2D1_FACTORY_OPTIONS const options = { D2D1_DEBUG_LEVEL_INFORMATION }; | |
HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, | |
options, | |
d2Factory.GetAddressOf())); | |
// Create the Direct2D device that links back to the Direct3D device | |
ComPtr<ID2D1Device1> d2Device; | |
HR(d2Factory->CreateDevice(dxgiDevice.Get(), | |
d2Device.GetAddressOf())); | |
// Create the Direct2D device context that is the actual render target | |
// and exposes drawing commands | |
ComPtr<ID2D1DeviceContext> dc; | |
HR(d2Device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, | |
dc.GetAddressOf())); | |
// Retrieve the swap chain's back buffer | |
ComPtr<IDXGISurface2> surface; | |
HR(g_pSwapChain->GetBuffer( | |
0, // index | |
__uuidof(surface), | |
reinterpret_cast<void **>(surface.GetAddressOf()))); | |
ComPtr<IDCompositionDevice> dcompDevice; | |
HR(DCompositionCreateDevice( | |
dxgiDevice.Get(), | |
__uuidof(dcompDevice), | |
reinterpret_cast<void **>(dcompDevice.GetAddressOf()))); | |
ComPtr<IDCompositionTarget> target; | |
HR(dcompDevice->CreateTargetForHwnd(hwnd, | |
true, // Top most | |
target.GetAddressOf())); | |
ComPtr<IDCompositionVisual> visual; | |
HR(dcompDevice->CreateVisual(visual.GetAddressOf())); | |
HR(visual->SetContent(g_pSwapChain.Get())); | |
HR(target->SetRoot(visual.Get())); | |
HR(dcompDevice->Commit()); | |
// Show the window | |
::ShowWindow(hwnd, SW_SHOWDEFAULT); | |
::UpdateWindow(hwnd); | |
// Setup Dear ImGui context | |
IMGUI_CHECKVERSION(); | |
ImGui::CreateContext(); | |
ImGuiIO& io = ImGui::GetIO(); (void)io; | |
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; | |
// Setup Dear ImGui style | |
ImGui::StyleColorsDark(); | |
// Setup Platform/Renderer bindings | |
ImGui_ImplWin32_Init(hwnd); | |
ImGui_ImplDX11_Init(g_pd3dDevice.Get(), g_pd3dDeviceContext.Get()); | |
// Our state | |
bool show_demo_window = true; | |
ImVec4 clear_color = ImVec4(0.f, 0.f, 0.0f, 0.0001f); | |
CleanupRenderTarget(); | |
g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(1024), (UINT)HIWORD(1024), DXGI_FORMAT_UNKNOWN, 0); | |
CreateRenderTarget(); | |
MSG message; | |
while(BOOL result = GetMessage(&message, 0, 0, 0)) | |
{ | |
if(-1 != result) DispatchMessage(&message); | |
// Start the Dear ImGui frame | |
ImGui_ImplDX11_NewFrame(); | |
ImGui_ImplWin32_NewFrame(); | |
ImGui::NewFrame(); | |
if(show_demo_window) | |
ImGui::ShowDemoWindow(&show_demo_window); | |
ImGui::Render(); | |
g_pd3dDeviceContext->OMSetRenderTargets(1, g_mainRenderTargetView.GetAddressOf(), NULL); | |
g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView.Get(), (float*)&clear_color); | |
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); | |
g_pSwapChain->Present(1, 0); // Present with vsync | |
} | |
} | |
void CleanupDeviceD3D() | |
{ | |
CleanupRenderTarget(); | |
if(g_pSwapChain) { g_pSwapChain->Release(); } | |
if(g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); } | |
if(g_pd3dDevice) { g_pd3dDevice->Release(); } | |
} | |
void CreateRenderTarget() | |
{ | |
ID3D11Texture2D* pBackBuffer; | |
g_pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer)); | |
g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView); | |
pBackBuffer->Release(); | |
} | |
void CleanupRenderTarget() | |
{ | |
if(g_mainRenderTargetView) { g_mainRenderTargetView->Release(); } | |
} | |
// Win32 message handler | |
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); | |
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) | |
{ | |
ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam); | |
switch(msg) | |
{ | |
case WM_SYSCOMMAND: | |
if((wParam & 0xfff0) == SC_KEYMENU) | |
return 0; | |
break; | |
case WM_DESTROY: | |
::PostQuitMessage(0); | |
return 0; | |
} | |
return ::DefWindowProc(hWnd, msg, wParam, lParam); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment