wined3d: Support multiple outputs.

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 2021-01-25 22:22:19 +08:00 committed by Alexandre Julliard
parent 3904390ec5
commit 98f490bdfc
8 changed files with 62 additions and 85 deletions

View file

@ -10455,9 +10455,8 @@ static void test_multi_adapter(void)
}
adapter_count = IDirect3D8_GetAdapterCount(d3d);
todo_wine_if(expected_adapter_count > 1)
ok(adapter_count == expected_adapter_count, "Got unexpected adapter count %u, expected %u.\n",
adapter_count, expected_adapter_count);
ok(adapter_count == expected_adapter_count, "Got unexpected adapter count %u, expected %u.\n",
adapter_count, expected_adapter_count);
for (i = 0; i < adapter_count; ++i)
{

View file

@ -14149,9 +14149,8 @@ static void test_multi_adapter(void)
}
adapter_count = IDirect3D9_GetAdapterCount(d3d);
todo_wine_if(expected_adapter_count > 1)
ok(adapter_count == expected_adapter_count, "Got unexpected adapter count %u, expected %u.\n",
adapter_count, expected_adapter_count);
ok(adapter_count == expected_adapter_count, "Got unexpected adapter count %u, expected %u.\n",
adapter_count, expected_adapter_count);
for (i = 0; i < adapter_count; ++i)
{

View file

@ -429,7 +429,6 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_factory_create_swapchain(IWineDX
struct wined3d_swapchain_desc wined3d_desc;
struct IDXGIOutput *containing_output;
struct d3d11_swapchain *object;
struct IDXGIAdapter *adapter;
HRESULT hr;
TRACE("iface %p, factory %p, window %p, desc %p, fullscreen_desc %p, output %p, swapchain %p.\n",
@ -438,20 +437,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_factory_create_swapchain(IWineDX
if (FAILED(hr = dxgi_get_output_from_window(factory, window, &containing_output)))
{
WARN("Failed to get output from window %p, hr %#x.\n", window, hr);
/* FIXME: As wined3d only supports one output currently, even if a window is on a
* non-primary output, the swapchain will use the primary output. Keep this behaviour
* until all outputs are correctly enumerated. Otherwise it will create a regression
* for applications that specify a device window on a non-primary output */
if (FAILED(hr = IDXGIFactory_EnumAdapters(factory, 0, &adapter)))
return hr;
hr = IDXGIAdapter_EnumOutputs(adapter, 0, &containing_output);
IDXGIAdapter_Release(adapter);
if (FAILED(hr))
return hr;
FIXME("Using the primary output for the device window that is on a non-primary output.\n");
return hr;
}
hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, containing_output, window, desc,

View file

@ -3000,9 +3000,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
VkFenceCreateInfo fence_desc;
uint32_t queue_family_index;
VkSurfaceKHR vk_surface;
IUnknown *device_parent;
VkInstance vk_instance;
IDXGIAdapter *adapter;
IDXGIOutput *output;
VkBool32 supported;
VkDevice vk_device;
@ -3043,27 +3041,11 @@ 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;
if (FAILED(hr = dxgi_get_output_from_window((IDXGIFactory *)factory, window, &output)))
{
WARN("Failed to get output from window %p, hr %#x.\n", window, hr);
/* FIXME: As wined3d only supports one output currently, even if a window is on a
* non-primary output, the swapchain will use the primary output. Keep this behaviour
* until all outputs are correctly enumerated. Otherwise it will create a regression
* for applications that specify a device window on a non-primary output */
if (FAILED(hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output)))
{
IDXGIAdapter_Release(adapter);
return hr;
}
FIXME("Using the primary output for the device window that is on a non-primary output.\n");
return hr;
}
IDXGIAdapter_Release(adapter);
hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, output, window, swapchain_desc,
fullscreen_desc);

View file

@ -2178,22 +2178,6 @@ done:
DestroyWindow(creation_desc.OutputWindow);
}
static HMONITOR get_primary_if_right_side_secondary(const DXGI_OUTPUT_DESC *output_desc)
{
HMONITOR primary, secondary;
MONITORINFO mi;
POINT pt = {0, 0};
primary = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
pt.x = output_desc->DesktopCoordinates.right;
secondary = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
mi.cbSize = sizeof(mi);
if (secondary && secondary != primary
&& GetMonitorInfoW(primary, &mi) && (mi.dwFlags & MONITORINFOF_PRIMARY))
return primary;
return NULL;
}
static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
{
unsigned int adapter_idx, output_idx, output_count;
@ -2207,7 +2191,6 @@ static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
POINT points[4 * 16];
unsigned int i, j;
HMONITOR monitor;
HMONITOR primary;
BOOL fullscreen;
ULONG refcount;
HRESULT hr;
@ -2287,8 +2270,6 @@ static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
wine_dbgstr_rect(&output_desc.DesktopCoordinates),
wine_dbgstr_rect(&monitor_info.rcMonitor));
primary = get_primary_if_right_side_secondary(&output_desc);
for (adapter_idx = 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory, adapter_idx, &adapter));
++adapter_idx)
{
@ -2379,8 +2360,6 @@ static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
output_idx, i);
hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
/* Hack to prevent test failures with secondary on the right until multi-monitor support is improved. */
todo_wine_if(primary && monitor != primary)
ok(hr == S_OK || broken(hr == DXGI_ERROR_UNSUPPORTED),
"Adapter %u output %u point %u: Failed to get containing output, hr %#x.\n",
adapter_idx, output_idx, i, hr);
@ -5652,9 +5631,8 @@ done:
IDXGIFactory_Release(factory);
expected_output_count = GetSystemMetrics(SM_CMONITORS);
todo_wine_if(expected_output_count > 1)
ok(output_count == expected_output_count, "Expect output count %d, got %d\n",
expected_output_count, output_count);
ok(output_count == expected_output_count, "Expect output count %d, got %d\n",
expected_output_count, output_count);
}
struct message

View file

@ -140,6 +140,7 @@ static HRESULT wined3d_output_init(struct wined3d_output *output, unsigned int o
output->ordinal = ordinal;
lstrcpyW(output->device_name, device_name);
output->adapter = adapter;
output->screen_format = WINED3DFMT_UNKNOWN;
output->kmt_adapter = open_adapter_desc.hAdapter;
output->kmt_device = create_device_desc.hDevice;
output->vidpn_source_id = open_adapter_desc.VidPnSourceId;
@ -3105,16 +3106,46 @@ static struct wined3d_adapter *wined3d_adapter_no3d_create(unsigned int ordinal,
return adapter;
}
static BOOL wined3d_adapter_create_output(struct wined3d_adapter *adapter, const WCHAR *output_name)
{
struct wined3d_output *outputs;
HRESULT hr;
if (!adapter->outputs && !(adapter->outputs = heap_calloc(1, sizeof(*adapter->outputs))))
{
return FALSE;
}
else
{
if (!(outputs = heap_realloc(adapter->outputs,
sizeof(*adapter->outputs) * (adapter->output_count + 1))))
return FALSE;
adapter->outputs = outputs;
}
if (FAILED(hr = wined3d_output_init(&adapter->outputs[adapter->output_count],
adapter->output_count, adapter, output_name)))
{
ERR("Failed to initialise output %s, hr %#x.\n", wine_dbgstr_w(output_name), hr);
return FALSE;
}
++adapter->output_count;
TRACE("Initialised output %s.\n", wine_dbgstr_w(output_name));
return TRUE;
}
BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, unsigned int ordinal, const LUID *luid,
const struct wined3d_adapter_ops *adapter_ops)
{
unsigned int output_idx = 0, primary_idx = 0;
DISPLAY_DEVICEW display_device;
unsigned int output_idx;
BOOL ret = FALSE;
HRESULT hr;
adapter->ordinal = ordinal;
adapter->output_count = 0;
adapter->outputs = NULL;
if (luid)
{
@ -3132,23 +3163,29 @@ BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, unsigned int ordinal,
TRACE("adapter %p LUID %08x:%08x.\n", adapter, adapter->luid.HighPart, adapter->luid.LowPart);
display_device.cb = sizeof(display_device);
EnumDisplayDevicesW(NULL, ordinal, &display_device, 0);
TRACE("Display device: %s.\n", debugstr_w(display_device.DeviceName));
strcpyW(adapter->device_name, display_device.DeviceName);
if (!(adapter->outputs = heap_calloc(1, sizeof(*adapter->outputs))))
while (EnumDisplayDevicesW(NULL, output_idx++, &display_device, 0))
{
ERR("Failed to allocate outputs.\n");
return FALSE;
}
/* Detached outputs are not enumerated */
if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
continue;
if (FAILED(hr = wined3d_output_init(&adapter->outputs[0], 0, adapter,
display_device.DeviceName)))
{
ERR("Failed to initialise output, hr %#x.\n", hr);
goto done;
if (display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
primary_idx = adapter->output_count;
if (!wined3d_adapter_create_output(adapter, display_device.DeviceName))
goto done;
}
TRACE("Initialised %d outputs for adapter %p.\n", adapter->output_count, adapter);
/* Make the primary output first */
if (primary_idx)
{
struct wined3d_output tmp = adapter->outputs[0];
adapter->outputs[0] = adapter->outputs[primary_idx];
adapter->outputs[0].ordinal = 0;
adapter->outputs[primary_idx] = tmp;
adapter->outputs[primary_idx].ordinal = primary_idx;
}
adapter->output_count = 1;
memset(&adapter->driver_uuid, 0, sizeof(adapter->driver_uuid));
memset(&adapter->device_uuid, 0, sizeof(adapter->device_uuid));

View file

@ -497,9 +497,7 @@ static struct wined3d_output * wined3d_get_output_from_window(const struct wined
}
}
/* Because wined3d only supports one output right now. A window can be on non-primary outputs
* and thus fails to get its correct output. In this case, return the primary output for now */
return &wined3d->adapters[0]->outputs[0];
return NULL;
}
static struct wined3d_wndproc *wined3d_find_wndproc(HWND window, struct wined3d *wined3d)

View file

@ -3368,8 +3368,6 @@ struct wined3d_adapter
GUID device_uuid;
LUID luid;
WCHAR device_name[CCHDEVICENAME]; /* for use with e.g. ChangeDisplaySettings() */
void *formats;
size_t format_size;