Skip to content

Instantly share code, notes, and snippets.

@yuyoyuppe
Created March 22, 2019 15:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yuyoyuppe/ee6afa12e7a72db122a9aca0d449ae76 to your computer and use it in GitHub Desktop.
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)
#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