diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index f3b74389d29..36beb84aa28 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -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; diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index f747e236f31..2838a025e57 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -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); diff --git a/dlls/dxgi/utils.c b/dlls/dxgi/utils.c index 665413e4c62..af72f83b6b0 100644 --- a/dlls/dxgi/utils.c +++ b/dlls/dxgi/utils.c @@ -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) { diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index d0d93417a18..b35fb5af65a 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -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; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index d11e06d0c34..77b22b3c907 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -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) diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index c98aee18bdd..001b7dd1255 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -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; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d932f60fa95..bbb0a60d7bb 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -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 { diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 238961006a0..61ab0e90953 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -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,