dxgi: Support Alt+Enter for d3d12 swapchains.

Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zhiyi Zhang 2020-10-09 17:56:42 +08:00 committed by Alexandre Julliard
parent 1bda5913fc
commit e62b6fa12d
8 changed files with 95 additions and 69 deletions

View file

@ -2272,18 +2272,37 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapCha
BOOL *fullscreen, IDXGIOutput **target)
{
struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain4(iface);
BOOL windowed;
HRESULT hr;
TRACE("iface %p, fullscreen %p, target %p.\n", iface, fullscreen, target);
if (fullscreen)
if (fullscreen || target)
{
wined3d_mutex_lock();
*fullscreen = !wined3d_swapchain_state_is_windowed(swapchain->state);
windowed = wined3d_swapchain_state_is_windowed(swapchain->state);
wined3d_mutex_unlock();
}
if (target && (*target = swapchain->target))
IDXGIOutput_AddRef(*target);
if (fullscreen)
*fullscreen = !windowed;
if (target)
{
if (!windowed)
{
if (!swapchain->target && FAILED(hr = IDXGISwapChain4_GetContainingOutput(iface,
&swapchain->target)))
return hr;
*target = swapchain->target;
IDXGIOutput_AddRef(*target);
}
else
{
*target = NULL;
}
}
return S_OK;
}
@ -2927,6 +2946,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
struct wined3d_swapchain_desc wined3d_desc;
VkWin32SurfaceCreateInfoKHR surface_desc;
VkPhysicalDevice vk_physical_device;
struct dxgi_factory *dxgi_factory;
VkFenceCreateInfo fence_desc;
uint32_t queue_family_index;
VkSurfaceKHR vk_surface;
@ -3002,7 +3022,9 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
return hr;
}
if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, &swapchain->state)))
dxgi_factory = unsafe_impl_from_IDXGIFactory((IDXGIFactory *)factory);
if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, dxgi_factory->wined3d,
&swapchain->state)))
{
IDXGIOutput_Release(output);
return hr;

View file

@ -6272,7 +6272,6 @@ static void test_window_association(IUnknown *device, BOOL is_d3d12)
output = NULL;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &output);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
todo_wine_if(is_d3d12 && tests[i].todo_on_d3d12)
ok(fullscreen == tests[i].expect_fullscreen
|| broken(tests[i].broken_d3d10 && fullscreen),
"Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);

View file

@ -520,7 +520,7 @@ unsigned int wined3d_bind_flags_from_dxgi_usage(DXGI_USAGE dxgi_usage)
#define DXGI_WINED3D_SWAPCHAIN_FLAGS \
(WINED3D_SWAPCHAIN_USE_CLOSEST_MATCHING_MODE | WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT \
| WINED3D_SWAPCHAIN_HOOK | WINED3D_SWAPCHAIN_RESTORE_WINDOW_STATE)
| WINED3D_SWAPCHAIN_REGISTER_STATE | WINED3D_SWAPCHAIN_RESTORE_WINDOW_STATE)
unsigned int dxgi_swapchain_flags_from_wined3d(unsigned int wined3d_flags)
{

View file

@ -34,7 +34,7 @@ void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain)
TRACE("Destroying swapchain %p.\n", swapchain);
wined3d_unhook_swapchain(swapchain);
wined3d_swapchain_state_unregister(&swapchain->state);
wined3d_swapchain_set_gamma_ramp(swapchain, 0, &swapchain->orig_gamma);
/* Release the swapchain's draw buffers. Make sure swapchain->back_buffers[0]
@ -1288,7 +1288,7 @@ static enum wined3d_format_id adapter_format_from_backbuffer_format(const struct
}
static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *state,
const struct wined3d_swapchain_desc *desc, HWND window)
const struct wined3d_swapchain_desc *desc, HWND window, struct wined3d *wined3d)
{
HRESULT hr;
@ -1320,6 +1320,9 @@ static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *stat
GetWindowRect(window, &state->original_window_rect);
state->device_window = window;
if (desc->flags & WINED3D_SWAPCHAIN_REGISTER_STATE)
wined3d_swapchain_state_register(state, wined3d);
return hr;
}
@ -1350,7 +1353,7 @@ static HRESULT wined3d_swapchain_init(struct wined3d_swapchain *swapchain, struc
FIXME("Unimplemented swap effect %#x.\n", desc->swap_effect);
window = desc->device_window ? desc->device_window : device->create_parms.focus_window;
if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window)))
if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window, device->wined3d)))
{
ERR("Failed to initialise swapchain state, hr %#x.\n", hr);
goto err;
@ -1627,9 +1630,6 @@ HRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device, struct win
desc, parent, parent_ops, &object)))
return hr;
if (desc->flags & WINED3D_SWAPCHAIN_HOOK)
wined3d_hook_swapchain(object);
if (desc->flags & WINED3D_SWAPCHAIN_IMPLICIT)
{
wined3d_mutex_lock();
@ -2275,21 +2275,22 @@ BOOL CDECL wined3d_swapchain_state_is_windowed(const struct wined3d_swapchain_st
void CDECL wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state)
{
wined3d_swapchain_state_unregister(state);
heap_free(state);
}
HRESULT CDECL wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc,
HWND window, struct wined3d_swapchain_state **state)
HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state **state)
{
struct wined3d_swapchain_state *s;
HRESULT hr;
TRACE("desc %p, window %p, state %p.\n", desc, window, state);
TRACE("desc %p, window %p, wined3d %p, state %p.\n", desc, window, wined3d, state);
if (!(s = heap_alloc_zero(sizeof(*s))))
return E_OUTOFMEMORY;
if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window)))
if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window, wined3d)))
{
heap_free(s);
return hr;

View file

@ -289,7 +289,7 @@
@ cdecl wined3d_swapchain_set_palette(ptr ptr)
@ cdecl wined3d_swapchain_set_window(ptr ptr)
@ cdecl wined3d_swapchain_state_create(ptr ptr ptr)
@ cdecl wined3d_swapchain_state_create(ptr ptr ptr ptr)
@ cdecl wined3d_swapchain_state_destroy(ptr)
@ cdecl wined3d_swapchain_state_is_windowed(ptr)
@ cdecl wined3d_swapchain_state_resize_target(ptr ptr)

View file

@ -56,25 +56,26 @@ struct wined3d_window_hook
unsigned int count;
};
struct wined3d_hooked_swapchain
struct wined3d_registered_swapchain_state
{
struct wined3d_swapchain *swapchain;
struct wined3d_swapchain_state *state;
struct wined3d *wined3d;
DWORD thread_id;
};
struct wined3d_hook_table
struct wined3d_swapchain_state_table
{
struct wined3d_window_hook *hooks;
SIZE_T hooks_size;
SIZE_T hook_count;
struct wined3d_hooked_swapchain *swapchains;
SIZE_T swapchains_size;
SIZE_T swapchain_count;
struct wined3d_registered_swapchain_state *states;
SIZE_T states_size;
SIZE_T state_count;
};
static struct wined3d_wndproc_table wndproc_table;
static struct wined3d_hook_table hook_table;
static struct wined3d_swapchain_state_table swapchain_state_table;
static CRITICAL_SECTION wined3d_cs;
static CRITICAL_SECTION_DEBUG wined3d_cs_debug =
@ -425,13 +426,13 @@ static BOOL wined3d_dll_destroy(HINSTANCE hInstDLL)
}
heap_free(wndproc_table.entries);
heap_free(hook_table.swapchains);
for (i = 0; i < hook_table.hook_count; ++i)
heap_free(swapchain_state_table.states);
for (i = 0; i < swapchain_state_table.hook_count; ++i)
{
WARN("Leftover hook table entry %p.\n", &hook_table.hooks[i]);
UnhookWindowsHookEx(hook_table.hooks[i].hook);
WARN("Leftover swapchain state hook %p.\n", &swapchain_state_table.hooks[i]);
UnhookWindowsHookEx(swapchain_state_table.hooks[i].hook);
}
heap_free(hook_table.hooks);
heap_free(swapchain_state_table.hooks);
heap_free(wined3d_settings.logo);
UnregisterClassA(WINED3D_OPENGL_WINDOW_CLASS_NAME, hInstDLL);
@ -573,8 +574,8 @@ static LRESULT CALLBACK wined3d_wndproc(HWND window, UINT message, WPARAM wparam
static LRESULT CALLBACK wined3d_hook_proc(int code, WPARAM wparam, LPARAM lparam)
{
struct wined3d_registered_swapchain_state *registered_state;
struct wined3d_swapchain_desc swapchain_desc;
struct wined3d_swapchain *swapchain;
struct wined3d_wndproc *entry;
struct wined3d_output *output;
MSG *msg = (MSG *)lparam;
@ -586,28 +587,28 @@ static LRESULT CALLBACK wined3d_hook_proc(int code, WPARAM wparam, LPARAM lparam
{
wined3d_wndproc_mutex_lock();
for (i = 0; i < hook_table.swapchain_count; ++i)
for (i = 0; i < swapchain_state_table.state_count; ++i)
{
swapchain = hook_table.swapchains[i].swapchain;
registered_state = &swapchain_state_table.states[i];
if (swapchain->state.device_window != msg->hwnd)
if (registered_state->state->device_window != msg->hwnd)
continue;
if ((entry = wined3d_find_wndproc(msg->hwnd, swapchain->device->wined3d))
if ((entry = wined3d_find_wndproc(msg->hwnd, registered_state->wined3d))
&& (entry->flags & (WINED3D_REGISTER_WINDOW_NO_WINDOW_CHANGES
| WINED3D_REGISTER_WINDOW_NO_ALT_ENTER)))
continue;
wined3d_swapchain_get_desc(swapchain, &swapchain_desc);
swapchain_desc = registered_state->state->desc;
swapchain_desc.windowed = !swapchain_desc.windowed;
if (!(output = wined3d_get_output_from_window(swapchain->device->wined3d,
swapchain->state.device_window)))
if (!(output = wined3d_get_output_from_window(registered_state->wined3d,
registered_state->state->device_window)))
{
ERR("Failed to get output from window %p.\n", swapchain->state.device_window);
ERR("Failed to get output from window %p.\n", registered_state->state->device_window);
break;
}
swapchain_desc.output = output;
wined3d_swapchain_state_set_fullscreen(&swapchain->state, &swapchain_desc, NULL);
wined3d_swapchain_state_set_fullscreen(registered_state->state, &swapchain_desc, NULL);
wined3d_wndproc_mutex_unlock();
@ -764,82 +765,84 @@ static struct wined3d_window_hook *wined3d_find_hook(DWORD thread_id)
{
unsigned int i;
for (i = 0; i < hook_table.hook_count; ++i)
for (i = 0; i < swapchain_state_table.hook_count; ++i)
{
if (hook_table.hooks[i].thread_id == thread_id)
return &hook_table.hooks[i];
if (swapchain_state_table.hooks[i].thread_id == thread_id)
return &swapchain_state_table.hooks[i];
}
return NULL;
}
void wined3d_hook_swapchain(struct wined3d_swapchain *swapchain)
void wined3d_swapchain_state_register(struct wined3d_swapchain_state *state,
struct wined3d *wined3d)
{
struct wined3d_hooked_swapchain *swapchain_entry;
struct wined3d_registered_swapchain_state *state_entry;
struct wined3d_window_hook *hook;
wined3d_wndproc_mutex_lock();
if (!wined3d_array_reserve((void **)&hook_table.swapchains, &hook_table.swapchains_size,
hook_table.swapchain_count + 1, sizeof(*swapchain_entry)))
if (!wined3d_array_reserve((void **)&swapchain_state_table.states, &swapchain_state_table.states_size,
swapchain_state_table.state_count + 1, sizeof(*state_entry)))
{
wined3d_wndproc_mutex_unlock();
return;
}
swapchain_entry = &hook_table.swapchains[hook_table.swapchain_count++];
swapchain_entry->swapchain = swapchain;
swapchain_entry->thread_id = GetWindowThreadProcessId(swapchain->state.device_window, NULL);
state_entry = &swapchain_state_table.states[swapchain_state_table.state_count++];
state_entry->state = state;
state_entry->wined3d = wined3d;
state_entry->thread_id = GetWindowThreadProcessId(state->device_window, NULL);
if ((hook = wined3d_find_hook(swapchain_entry->thread_id)))
if ((hook = wined3d_find_hook(state_entry->thread_id)))
{
++hook->count;
wined3d_wndproc_mutex_unlock();
return;
}
if (!wined3d_array_reserve((void **)&hook_table.hooks, &hook_table.hooks_size,
hook_table.hook_count + 1, sizeof(*hook)))
if (!wined3d_array_reserve((void **)&swapchain_state_table.hooks, &swapchain_state_table.hooks_size,
swapchain_state_table.hook_count + 1, sizeof(*hook)))
{
--hook_table.swapchain_count;
--swapchain_state_table.state_count;
wined3d_wndproc_mutex_unlock();
return;
}
hook = &hook_table.hooks[hook_table.hook_count++];
hook->thread_id = swapchain_entry->thread_id;
hook = &swapchain_state_table.hooks[swapchain_state_table.hook_count++];
hook->thread_id = state_entry->thread_id;
hook->hook = SetWindowsHookExW(WH_GETMESSAGE, wined3d_hook_proc, 0, hook->thread_id);
hook->count = 1;
wined3d_wndproc_mutex_unlock();
}
void wined3d_unhook_swapchain(struct wined3d_swapchain *swapchain)
void wined3d_swapchain_state_unregister(struct wined3d_swapchain_state *state)
{
struct wined3d_hooked_swapchain *swapchain_entry, *last_swapchain_entry;
struct wined3d_registered_swapchain_state *state_entry, *last_state_entry;
struct wined3d_window_hook *hook, *last_hook;
unsigned int i;
wined3d_wndproc_mutex_lock();
for (i = 0; i < hook_table.swapchain_count; ++i)
for (i = 0; i < swapchain_state_table.state_count; ++i)
{
swapchain_entry = &hook_table.swapchains[i];
state_entry = &swapchain_state_table.states[i];
if (swapchain_entry->swapchain != swapchain)
if (state_entry->state != state)
continue;
if ((hook = wined3d_find_hook(swapchain_entry->thread_id)) && !--hook->count)
if ((hook = wined3d_find_hook(state_entry->thread_id)) && !--hook->count)
{
UnhookWindowsHookEx(hook->hook);
last_hook = &hook_table.hooks[--hook_table.hook_count];
last_hook = &swapchain_state_table.hooks[--swapchain_state_table.hook_count];
if (hook != last_hook)
*hook = *last_hook;
}
last_swapchain_entry = &hook_table.swapchains[--hook_table.swapchain_count];
if (swapchain_entry != last_swapchain_entry)
*swapchain_entry = *last_swapchain_entry;
last_state_entry = &swapchain_state_table.states[--swapchain_state_table.state_count];
if (state_entry != last_state_entry)
*state_entry = *last_state_entry;
break;
}

View file

@ -3522,9 +3522,7 @@ struct wined3d
};
BOOL wined3d_filter_messages(HWND window, BOOL filter) DECLSPEC_HIDDEN;
void wined3d_hook_swapchain(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags) DECLSPEC_HIDDEN;
void wined3d_unhook_swapchain(struct wined3d_swapchain *swapchain) DECLSPEC_HIDDEN;
void wined3d_unregister_window(HWND window) DECLSPEC_HIDDEN;
BOOL wined3d_get_app_name(char *app_name, unsigned int app_name_size) DECLSPEC_HIDDEN;
@ -5082,10 +5080,13 @@ struct wined3d_swapchain_state
HWND device_window;
};
void wined3d_swapchain_state_register(struct wined3d_swapchain_state *state,
struct wined3d *wined3d) DECLSPEC_HIDDEN;
void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_state *state,
HWND window, const RECT *window_rect) DECLSPEC_HIDDEN;
HRESULT wined3d_swapchain_state_setup_fullscreen(struct wined3d_swapchain_state *state,
HWND window, int x, int y, int width, int height) DECLSPEC_HIDDEN;
void wined3d_swapchain_state_unregister(struct wined3d_swapchain_state *state) DECLSPEC_HIDDEN;
struct wined3d_swapchain_ops
{

View file

@ -904,7 +904,7 @@ enum wined3d_shader_type
#define WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT 0x00004000u
#define WINED3D_SWAPCHAIN_GDI_COMPATIBLE 0x00008000u
#define WINED3D_SWAPCHAIN_IMPLICIT 0x00010000u
#define WINED3D_SWAPCHAIN_HOOK 0x00020000u
#define WINED3D_SWAPCHAIN_REGISTER_STATE 0x00020000u
#define WINED3D_SWAPCHAIN_NO_WINDOW_CHANGES 0x00040000u
#define WINED3D_SWAPCHAIN_RESTORE_WINDOW_STATE 0x00080000u
@ -2804,7 +2804,7 @@ void __cdecl wined3d_swapchain_set_palette(struct wined3d_swapchain *swapchain,
void __cdecl wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWND window);
HRESULT __cdecl wined3d_swapchain_state_create(const struct wined3d_swapchain_desc *desc,
HWND window, struct wined3d_swapchain_state **state);
HWND window, struct wined3d *wined3d, struct wined3d_swapchain_state **state);
void __cdecl wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state);
BOOL __cdecl wined3d_swapchain_state_is_windowed(const struct wined3d_swapchain_state *state);
HRESULT __cdecl wined3d_swapchain_state_resize_target(struct wined3d_swapchain_state *state,