mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
Commit 02fe9f5bdf
introduced linking the
Windows build of the demos with d3d12 and dxgi, while also still linking
to libvkd3d-utils.la. That happens to more or less work on Wine; we get
vkd3d-utils' D3D12CreateDevice(), and Wine's
IDXGIFactory2_CreateSwapChainForHwnd(), but because Wine's
implementation of d3d12 swapchains uses vkd3d, we're able to use the
resulting swapchain buffers even though the instance of vkd3d used by
Wine may not be the same instance of vkd3d used by the demos. Perhaps
unsurprisingly, things don't go nearly as well on Windows.
We could of course stop linking the demos to vkd3d-utils on Windows, but
that's not that interesting; we're trying to show what vkd3d can do
here, not what d3d12 can do.
240 lines
6.9 KiB
C
240 lines
6.9 KiB
C
/*
|
|
* Copyright 2016 Józef Kucia for CodeWeavers
|
|
* Copyright 2016 Henri Verbeet for CodeWeavers
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#define DEMO_WIN32_WINDOW_CLASS_NAME L"demo_wc"
|
|
|
|
struct demo_window_win32
|
|
{
|
|
struct demo_window w;
|
|
|
|
HINSTANCE instance;
|
|
HWND window;
|
|
};
|
|
|
|
#ifndef VKD3D_CROSSTEST
|
|
static VkSurfaceKHR demo_window_win32_create_vk_surface(struct demo_window *window, VkInstance vk_instance)
|
|
{
|
|
struct demo_window_win32 *window_win32 = CONTAINING_RECORD(window, struct demo_window_win32, w);
|
|
struct VkWin32SurfaceCreateInfoKHR surface_desc;
|
|
VkSurfaceKHR vk_surface;
|
|
|
|
surface_desc.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
|
surface_desc.pNext = NULL;
|
|
surface_desc.flags = 0;
|
|
surface_desc.hinstance = window_win32->instance;
|
|
surface_desc.hwnd = window_win32->window;
|
|
if (vkCreateWin32SurfaceKHR(vk_instance, &surface_desc, NULL, &vk_surface) < 0)
|
|
return VK_NULL_HANDLE;
|
|
|
|
return vk_surface;
|
|
}
|
|
#endif
|
|
|
|
static void demo_window_win32_destroy(struct demo_window *window)
|
|
{
|
|
struct demo_window_win32 *window_win32 = CONTAINING_RECORD(window, struct demo_window_win32, w);
|
|
|
|
DestroyWindow(window_win32->window);
|
|
}
|
|
|
|
static void demo_window_win32_destroyed(struct demo_window *window)
|
|
{
|
|
struct demo_window_win32 *window_win32 = CONTAINING_RECORD(window, struct demo_window_win32, w);
|
|
|
|
demo_window_cleanup(&window_win32->w);
|
|
free(window_win32);
|
|
}
|
|
|
|
static struct demo_window *demo_window_win32_create(struct demo *demo, const char *title,
|
|
unsigned int width, unsigned int height, void *user_data)
|
|
{
|
|
struct demo_window_win32 *window_win32;
|
|
RECT rect = {0, 0, width, height};
|
|
int title_size;
|
|
WCHAR *title_w;
|
|
DWORD style;
|
|
|
|
if (!(window_win32 = malloc(sizeof(*window_win32))))
|
|
return NULL;
|
|
|
|
#ifdef VKD3D_CROSSTEST
|
|
if (!demo_window_init(&window_win32->w, demo, user_data))
|
|
#else
|
|
if (!demo_window_init(&window_win32->w, demo, user_data,
|
|
demo_window_win32_create_vk_surface, demo_window_win32_destroy))
|
|
#endif
|
|
{
|
|
free(window_win32);
|
|
return NULL;
|
|
}
|
|
|
|
title_size = MultiByteToWideChar(CP_UTF8, 0, title, -1, NULL, 0);
|
|
if (!(title_w = calloc(title_size, sizeof(*title_w))))
|
|
{
|
|
demo_window_cleanup(&window_win32->w);
|
|
free(window_win32);
|
|
return NULL;
|
|
}
|
|
MultiByteToWideChar(CP_UTF8, 0, title, -1, title_w, title_size);
|
|
|
|
window_win32->instance = GetModuleHandle(NULL);
|
|
|
|
style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE;
|
|
AdjustWindowRect(&rect, style, FALSE);
|
|
window_win32->window = CreateWindowExW(0, DEMO_WIN32_WINDOW_CLASS_NAME, title_w, style, CW_USEDEFAULT,
|
|
CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, window_win32->instance, NULL);
|
|
free(title_w);
|
|
if (!window_win32->window)
|
|
{
|
|
demo_window_cleanup(&window_win32->w);
|
|
free(window_win32);
|
|
return NULL;
|
|
}
|
|
SetWindowLongPtrW(window_win32->window, GWLP_USERDATA, (LONG_PTR)window_win32);
|
|
|
|
return &window_win32->w;
|
|
}
|
|
|
|
static void demo_win32_get_dpi(struct demo *demo, double *dpi_x, double *dpi_y)
|
|
{
|
|
struct demo_win32 *win32 = &demo->u.win32;
|
|
|
|
*dpi_x = *dpi_y = win32->GetDpiForSystem();
|
|
}
|
|
|
|
static demo_key demo_key_from_win32_vkey(DWORD vkey)
|
|
{
|
|
static const struct
|
|
{
|
|
DWORD vkey;
|
|
demo_key demo_key;
|
|
}
|
|
lookup[] =
|
|
{
|
|
{VK_ESCAPE, DEMO_KEY_ESCAPE},
|
|
{VK_LEFT, DEMO_KEY_LEFT},
|
|
{VK_RIGHT, DEMO_KEY_RIGHT},
|
|
{VK_UP, DEMO_KEY_UP},
|
|
{VK_DOWN, DEMO_KEY_DOWN},
|
|
};
|
|
unsigned int i;
|
|
|
|
if (vkey >= '0' && vkey <= '9')
|
|
return vkey;
|
|
if (vkey >= 'A' && vkey <= 'Z')
|
|
return vkey;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(lookup); ++i)
|
|
{
|
|
if (lookup[i].vkey == vkey)
|
|
return lookup[i].demo_key;
|
|
}
|
|
|
|
return DEMO_KEY_UNKNOWN;
|
|
}
|
|
|
|
static LRESULT CALLBACK demo_win32_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
struct demo_window_win32 *window_win32 = (void *)GetWindowLongPtrW(window, GWLP_USERDATA);
|
|
|
|
switch (message)
|
|
{
|
|
case WM_PAINT:
|
|
if (window_win32 && window_win32->w.expose_func)
|
|
window_win32->w.expose_func(&window_win32->w, window_win32->w.user_data);
|
|
return 0;
|
|
|
|
case WM_KEYDOWN:
|
|
if (!window_win32->w.key_press_func)
|
|
break;
|
|
window_win32->w.key_press_func(&window_win32->w,
|
|
demo_key_from_win32_vkey(wparam), window_win32->w.user_data);
|
|
return 0;
|
|
|
|
case WM_DESTROY:
|
|
demo_window_win32_destroyed(&window_win32->w);
|
|
return 0;
|
|
}
|
|
|
|
return DefWindowProcW(window, message, wparam, lparam);
|
|
}
|
|
|
|
static void demo_win32_process_events(struct demo *demo)
|
|
{
|
|
MSG msg = {0};
|
|
|
|
for (;;)
|
|
{
|
|
if (!demo->idle_func)
|
|
{
|
|
if (GetMessageW(&msg, NULL, 0, 0) == -1)
|
|
break;
|
|
}
|
|
else if (!PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
|
|
{
|
|
demo->idle_func(demo, demo->user_data);
|
|
continue;
|
|
}
|
|
|
|
if (msg.message == WM_QUIT)
|
|
break;
|
|
TranslateMessage(&msg);
|
|
DispatchMessageW(&msg);
|
|
if (!demo->window_count)
|
|
PostQuitMessage(0);
|
|
}
|
|
}
|
|
|
|
static void demo_win32_cleanup(struct demo *demo)
|
|
{
|
|
UnregisterClassW(DEMO_WIN32_WINDOW_CLASS_NAME, GetModuleHandle(NULL));
|
|
}
|
|
|
|
static inline UINT demo_win32_GetDpiForSystem(void)
|
|
{
|
|
return 96;
|
|
}
|
|
|
|
static bool demo_win32_init(struct demo_win32 *win32)
|
|
{
|
|
WNDCLASSEXW wc;
|
|
|
|
wc.cbSize = sizeof(wc);
|
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|
wc.lpfnWndProc = demo_win32_window_proc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = GetModuleHandle(NULL);
|
|
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
|
|
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
|
|
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = DEMO_WIN32_WINDOW_CLASS_NAME;
|
|
wc.hIconSm = LoadIconW(NULL, IDI_WINLOGO);
|
|
if (!RegisterClassExW(&wc))
|
|
return false;
|
|
|
|
if ((win32->GetDpiForSystem = (void *)GetProcAddress(GetModuleHandleA("user32"), "GetDpiForSystem")))
|
|
SetProcessDPIAware();
|
|
else
|
|
win32->GetDpiForSystem = demo_win32_GetDpiForSystem;
|
|
|
|
return true;
|
|
}
|