CreateDevice() and CreateDeviceEx() expect the focus window to be non-NULL. If windowed mode is used, the focus window can be NULL as long as the device window is non-NULL instead.
Signed-off-by: Jeff Smith whydoubt@gmail.com --- dlls/d3d9/device.c | 3 ++ dlls/d3d9/tests/device.c | 87 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+)
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index b92193d46f..3f9004c4c0 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -4711,6 +4711,9 @@ HRESULT device_init(struct d3d9_device *device, struct d3d9 *parent, struct wine if (output_idx >= parent->wined3d_output_count) return D3DERR_INVALIDCALL;
+ if (focus_window == 0 && (parameters->hDeviceWindow == 0 || !parameters->Windowed)) + return D3DERR_INVALIDCALL; + if (mode) FIXME("Ignoring display mode.\n");
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 53a83ad887..0fb439bbe3 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -289,6 +289,92 @@ static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc * if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \ }
+static void test_create_device(void) +{ + IDirect3D9 *d3d9; + IDirect3DDevice9 *device; + HWND window; + HRESULT hr; + D3DPRESENT_PARAMETERS present_parameters = {0}; + DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING; + + window = create_window(); + d3d9 = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d9, "Failed to create a D3D object.\n"); + + if (!(device = create_device(d3d9, window, NULL))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + goto done; + } + IDirect3DDevice9_Release(device); + + /* Presentation parameters = NULL causes a crash in Windows. */ + + /* In windowed mode, focus window or device window must be set. */ + + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + present_parameters.Windowed = TRUE; + hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + behavior_flags, &present_parameters, &device); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(present_parameters.BackBufferWidth == 640, + "Got unexpected BackBufferWidth %u.\n", present_parameters.BackBufferWidth); + ok(present_parameters.BackBufferHeight == 480, + "Got unexpected BackBufferHeight %u.\n", present_parameters.BackBufferHeight); + ok(present_parameters.BackBufferFormat == D3DFMT_X8R8G8B8, + "Got unexpected BackBufferFormat %u.\n", present_parameters.BackBufferFormat); + IDirect3DDevice9_Release(device); + + memset(&present_parameters, 0, sizeof(D3DPRESENT_PARAMETERS)); + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + present_parameters.Windowed = TRUE; + present_parameters.hDeviceWindow = window; + hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, + behavior_flags, &present_parameters, &device); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(present_parameters.BackBufferWidth == 640, + "Got unexpected BackBufferWidth %u.\n", present_parameters.BackBufferWidth); + ok(present_parameters.BackBufferHeight == 480, + "Got unexpected BackBufferHeight %u.\n", present_parameters.BackBufferHeight); + ok(present_parameters.BackBufferFormat == D3DFMT_X8R8G8B8, + "Got unexpected BackBufferFormat %u.\n", present_parameters.BackBufferFormat); + IDirect3DDevice9_Release(device); + + memset(&present_parameters, 0, sizeof(D3DPRESENT_PARAMETERS)); + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + present_parameters.Windowed = TRUE; + hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, + behavior_flags, &present_parameters, &device); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + + /* In fullscreen mode, focus window must be set. */ + + memset(&present_parameters, 0, sizeof(D3DPRESENT_PARAMETERS)); + present_parameters.BackBufferWidth = 640; + present_parameters.BackBufferHeight = 480; + present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window, + behavior_flags, &present_parameters, &device); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + IDirect3DDevice9_Release(device); + + memset(&present_parameters, 0, sizeof(D3DPRESENT_PARAMETERS)); + present_parameters.BackBufferWidth = 640; + present_parameters.BackBufferHeight = 480; + present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8; + present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + present_parameters.hDeviceWindow = window; + hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, + behavior_flags, &present_parameters, &device); + ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr); + +done: + IDirect3D9_Release(d3d9); + DestroyWindow(window); +} + static void test_get_set_vertex_declaration(void) { IDirect3DVertexDeclaration9 *declaration, *tmp; @@ -14136,6 +14222,7 @@ START_TEST(device)
Direct3DShaderValidatorCreate9 = (void *)GetProcAddress(d3d9_handle, "Direct3DShaderValidatorCreate9");
+ test_create_device(); test_get_set_vertex_declaration(); test_get_declaration(); test_fvf_decl_conversion();
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=78271
Your paranoid android.
=== w10pro64_zh_CN (32 bit report) ===
d3d9: device.c:5272: Test failed: Didn't receive MOUSEMOVE 0 (50, 50).
=== debiant (32 bit Chinese:China report) ===
d3d9: device.c:14152: Test failed: Adapter 0: Expect window rect (0,0)-(1024,768), got (0,-9)-(1024,759).
Am 08.09.20 um 09:02 schrieb Jeff Smith:
- hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL,
behavior_flags, &present_parameters, &device);
Is this true of all device types? In particular, also NULLREF? I think WPF creates NULLREF devices with NULL windows, although I am not sure what for...
On Tue, Sep 8, 2020 at 5:50 AM Stefan Dösinger stefandoesinger@gmail.com wrote:
Am 08.09.20 um 09:02 schrieb Jeff Smith:
- hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL,
behavior_flags, &present_parameters, &device);
Is this true of all device types? In particular, also NULLREF? I think WPF creates NULLREF devices with NULL windows, although I am not sure what for...
Yes, it does appear that CreateDevice with other D3DDEVTYPEs does behave differently, particularly NULLREF. I am trying to improve the tests and solution, but am running into a bug with NULLREF that is causing it to fail on some platforms but not others.
Thanks, Jeff
[RFC]
I am working on expanding the tests, but am wondering which device types I really need to target. In rough order of which ones I would consider important:
D3DDEVTYPE_HAL - obviously D3DDEVTYPE_NULLREF - as Stefan mentioned, seems important not to break this - allows creating a window-less device D3DDEVTYPE_SW - CreateDevice always returns D3DERR_INVALIDCALL - not that interesting, but would be simple to implement. - If we wanted to support registering software devices it would be more important. D3DDEVTYPE_REF - CreateDevice generally returns D3DERR_NOTAVAILABLE - Has some quirks that make it harder to implement. - As I understand, this would behave differently on Windows systems with d3dref9.dll installed.
I'm thinking of testing and correcting the first three, but if someone has a strong sense that it should be otherwise, it would be great to know sooner rather than later.
Thanks, Jeff
On Wed, Sep 9, 2020 at 12:54 PM Jeff Smith whydoubt@gmail.com wrote:
On Tue, Sep 8, 2020 at 5:50 AM Stefan Dösinger stefandoesinger@gmail.com wrote:
Am 08.09.20 um 09:02 schrieb Jeff Smith:
- hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL,
behavior_flags, &present_parameters, &device);
Is this true of all device types? In particular, also NULLREF? I think WPF creates NULLREF devices with NULL windows, although I am not sure what for...
Yes, it does appear that CreateDevice with other D3DDEVTYPEs does behave differently, particularly NULLREF. I am trying to improve the tests and solution, but am running into a bug with NULLREF that is causing it to fail on some platforms but not others.
Thanks, Jeff
On Fri, 11 Sep 2020 at 04:29, Jeff Smith whydoubt@gmail.com wrote:
I'm thinking of testing and correcting the first three, but if someone has a strong sense that it should be otherwise, it would be great to know sooner rather than later.
Well, the first question I'd have would be why we care about fixing this issue in particular.
On Fri, Sep 11, 2020 at 4:56 AM Henri Verbeet hverbeet@gmail.com wrote:
On Fri, 11 Sep 2020 at 04:29, Jeff Smith whydoubt@gmail.com wrote:
I'm thinking of testing and correcting the first three, but if someone has a strong sense that it should be otherwise, it would be great to know sooner rather than later.
Well, the first question I'd have would be why we care about fixing this issue in particular.
What led me to this in the first place is an application that tries to call CreateDevice with the focus window and device window both set to zero. This returns an (invalid call) error in Windows. With Wine, it usual fails (with a memory error) from attempting a huge memory allocation, though it could also return success (which is clearly not right)
My original patch did not consider D3DDEVTYPE_NULLREF, which apparently ignores the windows, and so CreateDevice should succeed for that device type. Since I had missed that, I am trying to generalize the tests for device types besides HAL.