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:
parent
3904390ec5
commit
98f490bdfc
|
@ -10455,9 +10455,8 @@ static void test_multi_adapter(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter_count = IDirect3D8_GetAdapterCount(d3d);
|
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",
|
||||||
ok(adapter_count == expected_adapter_count, "Got unexpected adapter count %u, expected %u.\n",
|
adapter_count, expected_adapter_count);
|
||||||
adapter_count, expected_adapter_count);
|
|
||||||
|
|
||||||
for (i = 0; i < adapter_count; ++i)
|
for (i = 0; i < adapter_count; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14149,9 +14149,8 @@ static void test_multi_adapter(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
adapter_count = IDirect3D9_GetAdapterCount(d3d);
|
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",
|
||||||
ok(adapter_count == expected_adapter_count, "Got unexpected adapter count %u, expected %u.\n",
|
adapter_count, expected_adapter_count);
|
||||||
adapter_count, expected_adapter_count);
|
|
||||||
|
|
||||||
for (i = 0; i < adapter_count; ++i)
|
for (i = 0; i < adapter_count; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -429,7 +429,6 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_factory_create_swapchain(IWineDX
|
||||||
struct wined3d_swapchain_desc wined3d_desc;
|
struct wined3d_swapchain_desc wined3d_desc;
|
||||||
struct IDXGIOutput *containing_output;
|
struct IDXGIOutput *containing_output;
|
||||||
struct d3d11_swapchain *object;
|
struct d3d11_swapchain *object;
|
||||||
struct IDXGIAdapter *adapter;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
TRACE("iface %p, factory %p, window %p, desc %p, fullscreen_desc %p, output %p, swapchain %p.\n",
|
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)))
|
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);
|
WARN("Failed to get output from window %p, hr %#x.\n", window, hr);
|
||||||
|
return 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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, containing_output, window, desc,
|
hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, containing_output, window, desc,
|
||||||
|
|
|
@ -3000,9 +3000,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
|
||||||
VkFenceCreateInfo fence_desc;
|
VkFenceCreateInfo fence_desc;
|
||||||
uint32_t queue_family_index;
|
uint32_t queue_family_index;
|
||||||
VkSurfaceKHR vk_surface;
|
VkSurfaceKHR vk_surface;
|
||||||
IUnknown *device_parent;
|
|
||||||
VkInstance vk_instance;
|
VkInstance vk_instance;
|
||||||
IDXGIAdapter *adapter;
|
|
||||||
IDXGIOutput *output;
|
IDXGIOutput *output;
|
||||||
VkBool32 supported;
|
VkBool32 supported;
|
||||||
VkDevice vk_device;
|
VkDevice vk_device;
|
||||||
|
@ -3043,27 +3041,11 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
|
||||||
return DXGI_ERROR_UNSUPPORTED;
|
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)))
|
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);
|
WARN("Failed to get output from window %p, hr %#x.\n", window, hr);
|
||||||
|
return 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");
|
|
||||||
}
|
}
|
||||||
IDXGIAdapter_Release(adapter);
|
|
||||||
|
|
||||||
hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, output, window, swapchain_desc,
|
hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, output, window, swapchain_desc,
|
||||||
fullscreen_desc);
|
fullscreen_desc);
|
||||||
|
|
|
@ -2178,22 +2178,6 @@ done:
|
||||||
DestroyWindow(creation_desc.OutputWindow);
|
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)
|
static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
|
||||||
{
|
{
|
||||||
unsigned int adapter_idx, output_idx, output_count;
|
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];
|
POINT points[4 * 16];
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
HMONITOR monitor;
|
HMONITOR monitor;
|
||||||
HMONITOR primary;
|
|
||||||
BOOL fullscreen;
|
BOOL fullscreen;
|
||||||
ULONG refcount;
|
ULONG refcount;
|
||||||
HRESULT hr;
|
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(&output_desc.DesktopCoordinates),
|
||||||
wine_dbgstr_rect(&monitor_info.rcMonitor));
|
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));
|
for (adapter_idx = 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory, adapter_idx, &adapter));
|
||||||
++adapter_idx)
|
++adapter_idx)
|
||||||
{
|
{
|
||||||
|
@ -2379,8 +2360,6 @@ static void test_get_containing_output(IUnknown *device, BOOL is_d3d12)
|
||||||
output_idx, i);
|
output_idx, i);
|
||||||
|
|
||||||
hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
|
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),
|
ok(hr == S_OK || broken(hr == DXGI_ERROR_UNSUPPORTED),
|
||||||
"Adapter %u output %u point %u: Failed to get containing output, hr %#x.\n",
|
"Adapter %u output %u point %u: Failed to get containing output, hr %#x.\n",
|
||||||
adapter_idx, output_idx, i, hr);
|
adapter_idx, output_idx, i, hr);
|
||||||
|
@ -5652,9 +5631,8 @@ done:
|
||||||
IDXGIFactory_Release(factory);
|
IDXGIFactory_Release(factory);
|
||||||
|
|
||||||
expected_output_count = GetSystemMetrics(SM_CMONITORS);
|
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",
|
||||||
ok(output_count == expected_output_count, "Expect output count %d, got %d\n",
|
expected_output_count, output_count);
|
||||||
expected_output_count, output_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct message
|
struct message
|
||||||
|
|
|
@ -140,6 +140,7 @@ static HRESULT wined3d_output_init(struct wined3d_output *output, unsigned int o
|
||||||
output->ordinal = ordinal;
|
output->ordinal = ordinal;
|
||||||
lstrcpyW(output->device_name, device_name);
|
lstrcpyW(output->device_name, device_name);
|
||||||
output->adapter = adapter;
|
output->adapter = adapter;
|
||||||
|
output->screen_format = WINED3DFMT_UNKNOWN;
|
||||||
output->kmt_adapter = open_adapter_desc.hAdapter;
|
output->kmt_adapter = open_adapter_desc.hAdapter;
|
||||||
output->kmt_device = create_device_desc.hDevice;
|
output->kmt_device = create_device_desc.hDevice;
|
||||||
output->vidpn_source_id = open_adapter_desc.VidPnSourceId;
|
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;
|
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,
|
BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, unsigned int ordinal, const LUID *luid,
|
||||||
const struct wined3d_adapter_ops *adapter_ops)
|
const struct wined3d_adapter_ops *adapter_ops)
|
||||||
{
|
{
|
||||||
|
unsigned int output_idx = 0, primary_idx = 0;
|
||||||
DISPLAY_DEVICEW display_device;
|
DISPLAY_DEVICEW display_device;
|
||||||
unsigned int output_idx;
|
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
adapter->ordinal = ordinal;
|
adapter->ordinal = ordinal;
|
||||||
adapter->output_count = 0;
|
adapter->output_count = 0;
|
||||||
|
adapter->outputs = NULL;
|
||||||
|
|
||||||
if (luid)
|
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);
|
TRACE("adapter %p LUID %08x:%08x.\n", adapter, adapter->luid.HighPart, adapter->luid.LowPart);
|
||||||
|
|
||||||
display_device.cb = sizeof(display_device);
|
display_device.cb = sizeof(display_device);
|
||||||
EnumDisplayDevicesW(NULL, ordinal, &display_device, 0);
|
while (EnumDisplayDevicesW(NULL, output_idx++, &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))))
|
|
||||||
{
|
{
|
||||||
ERR("Failed to allocate outputs.\n");
|
/* Detached outputs are not enumerated */
|
||||||
return FALSE;
|
if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
|
||||||
}
|
continue;
|
||||||
|
|
||||||
if (FAILED(hr = wined3d_output_init(&adapter->outputs[0], 0, adapter,
|
if (display_device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
|
||||||
display_device.DeviceName)))
|
primary_idx = adapter->output_count;
|
||||||
{
|
|
||||||
ERR("Failed to initialise output, hr %#x.\n", hr);
|
if (!wined3d_adapter_create_output(adapter, display_device.DeviceName))
|
||||||
goto done;
|
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->driver_uuid, 0, sizeof(adapter->driver_uuid));
|
||||||
memset(&adapter->device_uuid, 0, sizeof(adapter->device_uuid));
|
memset(&adapter->device_uuid, 0, sizeof(adapter->device_uuid));
|
||||||
|
|
|
@ -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
|
return NULL;
|
||||||
* and thus fails to get its correct output. In this case, return the primary output for now */
|
|
||||||
return &wined3d->adapters[0]->outputs[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wined3d_wndproc *wined3d_find_wndproc(HWND window, struct wined3d *wined3d)
|
static struct wined3d_wndproc *wined3d_find_wndproc(HWND window, struct wined3d *wined3d)
|
||||||
|
|
|
@ -3368,8 +3368,6 @@ struct wined3d_adapter
|
||||||
GUID device_uuid;
|
GUID device_uuid;
|
||||||
LUID luid;
|
LUID luid;
|
||||||
|
|
||||||
WCHAR device_name[CCHDEVICENAME]; /* for use with e.g. ChangeDisplaySettings() */
|
|
||||||
|
|
||||||
void *formats;
|
void *formats;
|
||||||
size_t format_size;
|
size_t format_size;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue