dxgi: Implement d3d12_swapchain_SetFullscreenState().

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Conor McCarthy 2019-08-01 00:59:49 +04:30 committed by Alexandre Julliard
parent 712d3ca1e4
commit 9b493d42c4
8 changed files with 231 additions and 110 deletions

View File

@ -152,6 +152,24 @@ static HRESULT dxgi_get_output_from_window(IDXGIAdapter *adapter, HWND window, I
return DXGI_ERROR_NOT_FOUND;
}
static HRESULT dxgi_swapchain_set_fullscreen_state(struct wined3d_swapchain_state *state,
const struct wined3d_swapchain_desc *swapchain_desc, IDXGIOutput *output)
{
struct dxgi_output *dxgi_output;
struct dxgi_adapter *adapter;
HRESULT hr;
dxgi_output = unsafe_impl_from_IDXGIOutput(output);
adapter = dxgi_output->adapter;
wined3d_mutex_lock();
hr = wined3d_swapchain_state_set_fullscreen(state, swapchain_desc,
adapter->factory->wined3d, adapter->ordinal, NULL);
wined3d_mutex_unlock();
return hr;
}
static HRESULT dxgi_swapchain_resize_target(IDXGISwapChain1 *swapchain,
struct wined3d_swapchain_state *state, const DXGI_MODE_DESC *target_mode_desc)
{
@ -391,6 +409,7 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen
{
struct d3d11_swapchain *swapchain = d3d11_swapchain_from_IDXGISwapChain1(iface);
struct wined3d_swapchain_desc swapchain_desc;
struct wined3d_swapchain_state *state;
HRESULT hr;
TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target);
@ -401,31 +420,35 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen
return DXGI_ERROR_INVALID_CALL;
}
if (fullscreen)
if (target)
{
if (target)
{
IDXGIOutput_AddRef(target);
}
else if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(iface, &target)))
{
WARN("Failed to get default target output for swapchain, hr %#x.\n", hr);
return hr;
}
IDXGIOutput_AddRef(target);
}
else if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(iface, &target)))
{
WARN("Failed to get target output for swapchain, hr %#x.\n", hr);
return hr;
}
wined3d_mutex_lock();
state = wined3d_swapchain_get_state(swapchain->wined3d_swapchain);
wined3d_swapchain_get_desc(swapchain->wined3d_swapchain, &swapchain_desc);
swapchain_desc.windowed = !fullscreen;
hr = wined3d_swapchain_set_fullscreen(swapchain->wined3d_swapchain, &swapchain_desc, NULL);
hr = dxgi_swapchain_set_fullscreen_state(state, &swapchain_desc, target);
wined3d_mutex_unlock();
if (FAILED(hr))
{
if (target)
IDXGIOutput_Release(target);
IDXGIOutput_Release(target);
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
if (!fullscreen)
{
IDXGIOutput_Release(target);
target = NULL;
}
if (swapchain->target)
IDXGIOutput_Release(swapchain->target);
swapchain->target = target;
@ -866,14 +889,10 @@ HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_devi
swapchain->target = NULL;
if (fullscreen)
{
struct wined3d_swapchain_state *state;
desc->windowed = FALSE;
if (FAILED(hr = wined3d_swapchain_set_fullscreen(swapchain->wined3d_swapchain,
desc, NULL)))
{
WARN("Failed to set fullscreen state, hr %#x.\n", hr);
wined3d_swapchain_decref(swapchain->wined3d_swapchain);
goto cleanup;
}
state = wined3d_swapchain_get_state(swapchain->wined3d_swapchain);
if (FAILED(hr = IDXGISwapChain1_GetContainingOutput(&swapchain->IDXGISwapChain1_iface,
&swapchain->target)))
@ -882,6 +901,15 @@ HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_devi
wined3d_swapchain_decref(swapchain->wined3d_swapchain);
goto cleanup;
}
if (FAILED(hr = dxgi_swapchain_set_fullscreen_state(state, desc, swapchain->target)))
{
WARN("Failed to set fullscreen state, hr %#x.\n", hr);
IDXGIOutput_Release(swapchain->target);
wined3d_swapchain_decref(swapchain->wined3d_swapchain);
goto cleanup;
}
}
wined3d_mutex_unlock();
@ -1067,6 +1095,7 @@ struct d3d12_swapchain
IWineDXGIFactory *factory;
HWND window;
IDXGIOutput *target;
DXGI_SWAP_CHAIN_DESC1 desc;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
};
@ -1865,6 +1894,12 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
if (swapchain->vk_instance)
vk_funcs->p_vkDestroySurfaceKHR(swapchain->vk_instance, swapchain->vk_surface, NULL);
if (swapchain->target)
{
WARN("Destroying fullscreen swapchain.\n");
IDXGIOutput_Release(swapchain->target);
}
if (swapchain->device)
ID3D12Device_Release(swapchain->device);
@ -2165,9 +2200,57 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetBuffer(IDXGISwapChain3 *ifac
static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreenState(IDXGISwapChain3 *iface,
BOOL fullscreen, IDXGIOutput *target)
{
FIXME("iface %p, fullscreen %#x, target %p stub!\n", iface, fullscreen, target);
struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface);
DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc = &swapchain->fullscreen_desc;
const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc = &swapchain->desc;
struct wined3d_swapchain_desc wined3d_desc;
HWND window = swapchain->window;
HRESULT hr;
return E_NOTIMPL;
TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target);
if (!fullscreen && target)
{
WARN("Invalid call.\n");
return DXGI_ERROR_INVALID_CALL;
}
if (target)
{
IDXGIOutput_AddRef(target);
}
else if (FAILED(hr = IDXGISwapChain3_GetContainingOutput(iface, &target)))
{
WARN("Failed to get target output for swapchain, hr %#x.\n", hr);
return hr;
}
if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, swapchain_desc, fullscreen_desc)))
goto fail;
wined3d_mutex_lock();
wined3d_desc.windowed = !fullscreen;
hr = dxgi_swapchain_set_fullscreen_state(swapchain->state, &wined3d_desc, target);
wined3d_mutex_unlock();
if (FAILED(hr))
goto fail;
fullscreen_desc->Windowed = wined3d_desc.windowed;
if (!fullscreen)
{
IDXGIOutput_Release(target);
target = NULL;
}
if (swapchain->target)
IDXGIOutput_Release(swapchain->target);
swapchain->target = target;
return S_OK;
fail:
IDXGIOutput_Release(target);
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
}
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapChain3 *iface,
@ -2180,8 +2263,8 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapCha
if (fullscreen)
*fullscreen = !swapchain->fullscreen_desc.Windowed;
if (target)
*target = NULL;
if (target && (*target = swapchain->target))
IDXGIOutput_AddRef(*target);
return S_OK;
}
@ -2299,6 +2382,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetContainingOutput(IDXGISwapCh
TRACE("iface %p, output %p.\n", iface, output);
if (swapchain->target)
{
IDXGIOutput_AddRef(*output = swapchain->target);
return S_OK;
}
device_parent = vkd3d_get_device_parent(swapchain->device);
if (SUCCEEDED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter)))
@ -2726,10 +2815,13 @@ 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_adapter *dxgi_adapter;
VkFenceCreateInfo fence_desc;
uint32_t queue_family_index;
VkSurfaceKHR vk_surface;
IUnknown *device_parent;
VkInstance vk_instance;
IDXGIAdapter *adapter;
VkBool32 supported;
VkDevice vk_device;
VkFence vk_fence;
@ -2768,9 +2860,15 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
return DXGI_ERROR_UNSUPPORTED;
}
device_parent = vkd3d_get_device_parent(device);
if (FAILED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter)))
return hr;
dxgi_adapter = unsafe_impl_from_IDXGIAdapter(adapter);
IDXGIAdapter_Release(adapter);
if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, swapchain_desc, fullscreen_desc)))
return hr;
if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window, &swapchain->state)))
if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window,
dxgi_adapter->factory->wined3d, dxgi_adapter->ordinal, &swapchain->state)))
return hr;
if (swapchain_desc->BufferUsage && swapchain_desc->BufferUsage != DXGI_USAGE_RENDER_TARGET_OUTPUT)

View File

@ -4155,7 +4155,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
skip("Test %u: Could not change fullscreen state.\n", i);
continue;
}
todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
todo_wine_if(!is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDXGISwapChain_Present(swapchain, 0, flags[i]);
@ -4164,8 +4164,8 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
fullscreen = FALSE;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &output);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
todo_wine_if(is_d3d12) ok(!!output, "Test %u: Got unexpected output.\n", i);
ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
ok(!!output, "Test %u: Got unexpected output.\n", i);
if (output)
IDXGIOutput_ReleaseOwnership(output);
@ -4173,7 +4173,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
fullscreen = FALSE;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
/* Calling IDXGISwapChain_Present() will exit fullscreen. */
hr = IDXGISwapChain_Present(swapchain, 0, flags[i]);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
@ -4185,7 +4185,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
/* Still fullscreen on vista and 2008. */
todo_wine ok(!fullscreen || broken(fullscreen), "Test %u: Got unexpected fullscreen status.\n", i);
else
todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
if (output)
IDXGIOutput_Release(output);
@ -4198,11 +4198,11 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
* compositing. D3d12 fullscreen mode acts just like borderless
* fullscreen window mode. */
hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
fullscreen = FALSE;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
todo_wine_if(!is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDXGISwapChain_Present(swapchain, 0, flags[i]);
@ -4218,7 +4218,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
fullscreen = FALSE;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
todo_wine_if(is_d3d12) ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
ok(fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
/* A visible, but with bottom z-order window still causes the
* swapchain to exit fullscreen mode. */
SetWindowPos(occluding_window, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
@ -4232,7 +4232,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
fullscreen = TRUE;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
todo_wine ok(is_d3d12 ? fullscreen : !fullscreen,
todo_wine_if(!is_d3d12) ok(is_d3d12 ? fullscreen : !fullscreen,
"Test %u: Got unexpected fullscreen status.\n", i);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
@ -4245,10 +4245,10 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
if (flags[i] == DXGI_PRESENT_TEST)
todo_wine ok(is_d3d12 ? fullscreen : !fullscreen,
todo_wine_if(!is_d3d12) ok(is_d3d12 ? fullscreen : !fullscreen,
"Test %u: Got unexpected fullscreen status.\n", i);
else
todo_wine_if(!is_d3d12) ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
todo_wine ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
/* Even though d3d12 doesn't exit fullscreen, a
* IDXGISwapChain_ResizeBuffers() is still needed for subsequent
@ -4267,7 +4267,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
* IDXGISwapChain_GetFullscreenState() before IDXGISwapChain_Present(). */
ShowWindow(occluding_window, SW_HIDE);
hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
ShowWindow(occluding_window, SW_SHOW);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
@ -4303,7 +4303,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
fullscreen = TRUE;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
todo_wine_if(!is_d3d12) ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
todo_wine ok(!fullscreen, "Test %u: Got unexpected fullscreen status.\n", i);
DestroyWindow(occluding_window);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
@ -4312,7 +4312,7 @@ static void test_swapchain_present(IUnknown *device, BOOL is_d3d12)
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
todo_wine_if(is_d3d12) ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
}
@ -5558,11 +5558,11 @@ static void test_output_ownership(IUnknown *device, BOOL is_d3d12)
skip("Failed to change fullscreen state.\n");
goto done;
}
todo_wine_if(is_d3d12) ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
fullscreen = FALSE;
hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
todo_wine_if(is_d3d12) ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
todo_wine_if(is_d3d12) ok(fullscreen, "Got unexpected fullscreen state.\n");
ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
ok(fullscreen, "Got unexpected fullscreen state.\n");
if (is_d3d12)
wait_vidpn_exclusive_ownership(&check_ownership_desc, STATUS_SUCCESS, FALSE);
else

View File

@ -5428,7 +5428,8 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
return hr;
}
}
if (FAILED(hr = wined3d_swapchain_set_fullscreen(swapchain, swapchain_desc, mode)))
if (FAILED(hr = wined3d_swapchain_state_set_fullscreen(&swapchain->state,
swapchain_desc, device->wined3d, device->adapter->ordinal, mode)))
return hr;
/* Switch from fullscreen to windowed. */

View File

@ -80,13 +80,13 @@ static void swapchain_cleanup(struct wined3d_swapchain *swapchain)
if (swapchain->state.desc.auto_restore_display_mode)
{
if (FAILED(hr = wined3d_set_adapter_display_mode(swapchain->device->wined3d,
swapchain->device->adapter->ordinal, &swapchain->original_mode)))
swapchain->device->adapter->ordinal, &swapchain->state.original_mode)))
ERR("Failed to restore display mode, hr %#x.\n", hr);
if (swapchain->state.desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT)
{
wined3d_swapchain_state_restore_from_fullscreen(&swapchain->state,
swapchain->state.device_window, &swapchain->original_window_rect);
swapchain->state.device_window, &swapchain->state.original_window_rect);
wined3d_device_release_focus_window(swapchain->device);
}
}
@ -736,16 +736,53 @@ void swapchain_set_max_frame_latency(struct wined3d_swapchain *swapchain, const
swapchain->max_frame_latency = device->max_frame_latency >= 2 ? device->max_frame_latency - 1 : 1;
}
static enum wined3d_format_id adapter_format_from_backbuffer_format(struct wined3d_swapchain *swapchain,
static enum wined3d_format_id adapter_format_from_backbuffer_format(const struct wined3d_adapter *adapter,
enum wined3d_format_id format_id)
{
const struct wined3d_adapter *adapter = swapchain->device->adapter;
const struct wined3d_format *backbuffer_format;
backbuffer_format = wined3d_get_format(adapter, format_id, WINED3D_BIND_RENDER_TARGET);
return pixelformat_for_depth(backbuffer_format->byte_count * CHAR_BIT);
}
static HRESULT wined3d_swapchain_state_init(struct wined3d_swapchain_state *state,
const struct wined3d_swapchain_desc *desc, HWND window,
struct wined3d *wined3d, unsigned int adapter_idx)
{
HRESULT hr;
state->desc = *desc;
if (FAILED(hr = wined3d_get_adapter_display_mode(wined3d, adapter_idx, &state->original_mode, NULL)))
{
ERR("Failed to get current display mode, hr %#x.\n", hr);
return hr;
}
if (!desc->windowed)
{
if (desc->flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH)
{
struct wined3d_adapter *adapter = wined3d->adapters[adapter_idx];
state->d3d_mode.width = desc->backbuffer_width;
state->d3d_mode.height = desc->backbuffer_height;
state->d3d_mode.format_id = adapter_format_from_backbuffer_format(adapter, desc->backbuffer_format);
state->d3d_mode.refresh_rate = desc->refresh_rate;
state->d3d_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
}
else
{
state->d3d_mode = state->original_mode;
}
}
GetWindowRect(window, &state->original_window_rect);
state->device_window = window;
return hr;
}
static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
{
@ -775,24 +812,17 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
swapchain->swapchain_ops = &swapchain_gl_ops;
window = desc->device_window ? desc->device_window : device->create_parms.focus_window;
if (FAILED(hr = wined3d_swapchain_state_init(&swapchain->state, desc, window, device->wined3d, adapter->ordinal)))
return hr;
swapchain->device = device;
swapchain->parent = parent;
swapchain->parent_ops = parent_ops;
swapchain->ref = 1;
swapchain->win_handle = window;
swapchain->state.device_window = window;
swapchain->swap_interval = WINED3D_SWAP_INTERVAL_DEFAULT;
swapchain_set_max_frame_latency(swapchain, device);
if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d,
adapter->ordinal, &swapchain->original_mode, NULL)))
{
ERR("Failed to get current display mode, hr %#x.\n", hr);
goto err;
}
GetWindowRect(window, &swapchain->original_window_rect);
GetClientRect(window, &client_rect);
if (desc->windowed)
{
@ -811,8 +841,8 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
if (desc->backbuffer_format == WINED3DFMT_UNKNOWN)
{
desc->backbuffer_format = swapchain->original_mode.format_id;
TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->original_mode.format_id));
desc->backbuffer_format = swapchain->state.original_mode.format_id;
TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->state.original_mode.format_id));
}
}
else
@ -863,30 +893,16 @@ static HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3
/* MSDN says we're only allowed a single fullscreen swapchain per device,
* so we should really check to see if there is a fullscreen swapchain
* already. Does a single head count as full screen? */
if (!desc->windowed)
if (!desc->windowed && desc->flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH)
{
if (desc->flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH)
/* Change the display settings */
if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d,
adapter->ordinal, &swapchain->state.d3d_mode)))
{
/* Change the display settings */
swapchain->d3d_mode.width = desc->backbuffer_width;
swapchain->d3d_mode.height = desc->backbuffer_height;
swapchain->d3d_mode.format_id = adapter_format_from_backbuffer_format(swapchain,
desc->backbuffer_format);
swapchain->d3d_mode.refresh_rate = desc->refresh_rate;
swapchain->d3d_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d,
adapter->ordinal, &swapchain->d3d_mode)))
{
WARN("Failed to set display mode, hr %#x.\n", hr);
goto err;
}
displaymode_set = TRUE;
}
else
{
swapchain->d3d_mode = swapchain->original_mode;
WARN("Failed to set display mode, hr %#x.\n", hr);
goto err;
}
displaymode_set = TRUE;
}
if (swapchain->state.desc.backbuffer_count > 0)
@ -963,7 +979,7 @@ err:
if (displaymode_set)
{
if (FAILED(wined3d_set_adapter_display_mode(device->wined3d,
adapter->ordinal, &swapchain->original_mode)))
adapter->ordinal, &swapchain->state.original_mode)))
ERR("Failed to restore display mode.\n");
ClipCursor(NULL);
}
@ -1184,7 +1200,7 @@ void wined3d_swapchain_activate(struct wined3d_swapchain *swapchain, BOOL activa
if (device->wined3d->flags & WINED3D_RESTORE_MODE_ON_ACTIVATE)
{
if (FAILED(wined3d_set_adapter_display_mode(device->wined3d,
device->adapter->ordinal, &swapchain->d3d_mode)))
device->adapter->ordinal, &swapchain->state.d3d_mode)))
ERR("Failed to set display mode.\n");
}
@ -1272,7 +1288,7 @@ HRESULT CDECL wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapcha
{
if (!desc->windowed)
return WINED3DERR_INVALIDCALL;
format_id = swapchain->original_mode.format_id;
format_id = swapchain->state.original_mode.format_id;
}
if (format_id != desc->backbuffer_format)
@ -1500,15 +1516,15 @@ void wined3d_swapchain_state_restore_from_fullscreen(struct wined3d_swapchain_st
state->exstyle = 0;
}
HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapchain,
const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode)
HRESULT CDECL wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state,
const struct wined3d_swapchain_desc *swapchain_desc, struct wined3d *wined3d,
unsigned int adapter_idx, const struct wined3d_display_mode *mode)
{
struct wined3d_swapchain_state *state = &swapchain->state;
struct wined3d_device *device = swapchain->device;
struct wined3d_display_mode actual_mode;
HRESULT hr;
TRACE("swapchain %p, desc %p, mode %p.\n", swapchain, swapchain_desc, mode);
TRACE("state %p, swapchain_desc %p, wined3d %p, adapter_idx %u, mode %p.\n",
state, swapchain_desc, wined3d, adapter_idx, mode);
if (state->desc.flags & WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH)
{
@ -1520,21 +1536,22 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha
{
if (!swapchain_desc->windowed)
{
const struct wined3d_adapter *adapter = wined3d->adapters[adapter_idx];
actual_mode.width = swapchain_desc->backbuffer_width;
actual_mode.height = swapchain_desc->backbuffer_height;
actual_mode.refresh_rate = swapchain_desc->refresh_rate;
actual_mode.format_id = adapter_format_from_backbuffer_format(swapchain,
actual_mode.format_id = adapter_format_from_backbuffer_format(adapter,
swapchain_desc->backbuffer_format);
actual_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
}
else
{
actual_mode = swapchain->original_mode;
actual_mode = state->original_mode;
}
}
if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state,
device->wined3d, device->adapter->ordinal, &actual_mode)))
if (FAILED(hr = wined3d_swapchain_state_set_display_mode(state, wined3d, adapter_idx, &actual_mode)))
return hr;
}
else
@ -1542,8 +1559,7 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha
if (mode)
WARN("WINED3D_SWAPCHAIN_ALLOW_MODE_SWITCH is not set, ignoring mode.\n");
if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal,
&actual_mode, NULL)))
if (FAILED(hr = wined3d_get_adapter_display_mode(wined3d, adapter_idx, &actual_mode, NULL)))
{
ERR("Failed to get display mode, hr %#x.\n", hr);
return WINED3DERR_INVALIDCALL;
@ -1558,13 +1574,12 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha
if (state->desc.windowed)
{
/* Switch from windowed to fullscreen */
if (FAILED(hr = wined3d_swapchain_state_setup_fullscreen(state,
state->device_window, width, height)))
if (FAILED(hr = wined3d_swapchain_state_setup_fullscreen(state, state->device_window, width, height)))
return hr;
}
else
{
HWND window = swapchain->state.device_window;
HWND window = state->device_window;
BOOL filter;
/* Fullscreen -> fullscreen mode change */
@ -1573,14 +1588,14 @@ HRESULT CDECL wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapcha
ShowWindow(window, SW_SHOW);
wined3d_filter_messages(window, filter);
}
swapchain->d3d_mode = actual_mode;
state->d3d_mode = actual_mode;
}
else if (!state->desc.windowed)
{
/* Fullscreen -> windowed switch */
RECT *window_rect = NULL;
if (state->desc.flags & WINED3D_SWAPCHAIN_RESTORE_WINDOW_RECT)
window_rect = &swapchain->original_window_rect;
window_rect = &state->original_window_rect;
wined3d_swapchain_state_restore_from_fullscreen(state, state->device_window, window_rect);
}
@ -1595,19 +1610,23 @@ void CDECL wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *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, unsigned int adapter_idx, struct wined3d_swapchain_state **state)
{
struct wined3d_swapchain_state *s;
HRESULT hr;
TRACE("desc %p, window %p, wined3d %p, adapter_idx %u, state %p.\n",
desc, window, wined3d, adapter_idx, state);
TRACE("desc %p, window %p, state %p.\n", desc, window, state);
if (!(s = heap_alloc_zero(sizeof(*s))))
return E_OUTOFMEMORY;
s->desc = *desc;
s->device_window = window;
if (FAILED(hr = wined3d_swapchain_state_init(s, desc, window, wined3d, adapter_idx)))
return hr;
*state = s;
return WINED3D_OK;
return hr;
}

View File

@ -273,14 +273,14 @@
@ cdecl wined3d_swapchain_incref(ptr)
@ cdecl wined3d_swapchain_present(ptr ptr ptr ptr long long)
@ cdecl wined3d_swapchain_resize_buffers(ptr long long long long long long)
@ cdecl wined3d_swapchain_set_fullscreen(ptr ptr ptr)
@ cdecl wined3d_swapchain_set_gamma_ramp(ptr long ptr)
@ 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 long ptr)
@ cdecl wined3d_swapchain_state_destroy(ptr)
@ cdecl wined3d_swapchain_state_resize_target(ptr ptr long ptr)
@ cdecl wined3d_swapchain_state_set_fullscreen(ptr ptr ptr long ptr)
@ cdecl wined3d_texture_add_dirty_region(ptr long ptr)
@ cdecl wined3d_texture_blt(ptr long ptr ptr long ptr long ptr long)

View File

@ -565,7 +565,8 @@ static LRESULT CALLBACK wined3d_hook_proc(int code, WPARAM wparam, LPARAM lparam
wined3d_swapchain_get_desc(swapchain, &swapchain_desc);
swapchain_desc.windowed = !swapchain_desc.windowed;
wined3d_swapchain_set_fullscreen(swapchain, &swapchain_desc, NULL);
wined3d_swapchain_state_set_fullscreen(&swapchain->state, &swapchain_desc,
swapchain->device->wined3d, swapchain->device->adapter->ordinal, NULL);
wined3d_wndproc_mutex_unlock();

View File

@ -4178,6 +4178,9 @@ struct wined3d_swapchain_state
{
struct wined3d_swapchain_desc desc;
struct wined3d_display_mode original_mode, d3d_mode;
RECT original_window_rect;
/* Window styles to restore when switching fullscreen mode. */
LONG style;
LONG exstyle;
@ -4206,8 +4209,6 @@ struct wined3d_swapchain
struct wined3d_texture **back_buffers;
struct wined3d_texture *front_buffer;
struct wined3d_display_mode original_mode, d3d_mode;
RECT original_window_rect;
struct wined3d_gamma_ramp orig_gamma;
BOOL render_to_fbo, reapply_mode;
const struct wined3d_format *ds_format;

View File

@ -2684,18 +2684,19 @@ HRESULT __cdecl wined3d_swapchain_present(struct wined3d_swapchain *swapchain, c
HRESULT __cdecl wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapchain, unsigned int buffer_count,
unsigned int width, unsigned int height, enum wined3d_format_id format_id,
enum wined3d_multisample_type multisample_type, unsigned int multisample_quality);
HRESULT __cdecl wined3d_swapchain_set_fullscreen(struct wined3d_swapchain *swapchain,
const struct wined3d_swapchain_desc *desc, const struct wined3d_display_mode *mode);
HRESULT __cdecl wined3d_swapchain_set_gamma_ramp(const struct wined3d_swapchain *swapchain,
DWORD flags, const struct wined3d_gamma_ramp *ramp);
void __cdecl wined3d_swapchain_set_palette(struct wined3d_swapchain *swapchain, struct wined3d_palette *palette);
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, unsigned int adapter_idx, struct wined3d_swapchain_state **state);
void __cdecl wined3d_swapchain_state_destroy(struct wined3d_swapchain_state *state);
HRESULT __cdecl wined3d_swapchain_state_resize_target(struct wined3d_swapchain_state *state,
struct wined3d *wined3d, unsigned int adapter_idx, const struct wined3d_display_mode *mode);
HRESULT __cdecl wined3d_swapchain_state_set_fullscreen(struct wined3d_swapchain_state *state,
const struct wined3d_swapchain_desc *desc, struct wined3d *wined3d,
unsigned int adapter_idx, const struct wined3d_display_mode *mode);
HRESULT __cdecl wined3d_texture_add_dirty_region(struct wined3d_texture *texture,
UINT layer, const struct wined3d_box *dirty_region);