2 * Copyright (C) 2008 Stefan Dösinger(for CodeWeavers)
3 * Copyright (C) 2010 Louis Lenders
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 /* This file contains tests specific to IDirect3D9Ex and IDirect3DDevice9Ex, like
21 * how to obtain them. For testing rendering with extended functions use visual.c
25 #include "wine/test.h"
31 static HMODULE d3d9_handle
= 0;
33 static BOOL (WINAPI
*pEnumDisplaySettingsExA
)(LPCSTR
, DWORD
, DEVMODEA
*, DWORD
);
34 static LONG (WINAPI
*pChangeDisplaySettingsExA
)(LPCSTR
, LPDEVMODE
, HWND
, DWORD
, LPVOID
);
36 static IDirect3D9
* (WINAPI
*pDirect3DCreate9
)(UINT SDKVersion
);
37 static HRESULT (WINAPI
*pDirect3DCreate9Ex
)(UINT SDKVersion
, IDirect3D9Ex
**d3d9ex
);
39 static HWND
create_window(void)
43 wc
.lpfnWndProc
= DefWindowProc
;
44 wc
.lpszClassName
= "d3d9_test_wc";
47 ret
= CreateWindow("d3d9_test_wc", "d3d9_test",
48 WS_MAXIMIZE
| WS_VISIBLE
| WS_CAPTION
, 0, 0, 640, 480, 0, 0, 0, 0);
52 static IDirect3DDevice9Ex
*create_device(IDirect3D9Ex
*d3d9
, HWND device_window
, HWND focus_window
, BOOL windowed
)
54 D3DPRESENT_PARAMETERS present_parameters
= {0};
55 IDirect3DDevice9Ex
*device
;
56 D3DDISPLAYMODEEX mode
, *m
;
58 present_parameters
.Windowed
= windowed
;
59 present_parameters
.hDeviceWindow
= device_window
;
60 present_parameters
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
61 present_parameters
.BackBufferWidth
= 640;
62 present_parameters
.BackBufferHeight
= 480;
63 present_parameters
.BackBufferFormat
= D3DFMT_A8R8G8B8
;
64 present_parameters
.EnableAutoDepthStencil
= TRUE
;
65 present_parameters
.AutoDepthStencilFormat
= D3DFMT_D24S8
;
67 mode
.Size
= sizeof(mode
);
71 mode
.Format
= D3DFMT_A8R8G8B8
;
72 mode
.ScanLineOrdering
= 0;
74 m
= windowed
? NULL
: &mode
;
75 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, focus_window
,
76 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_parameters
, m
, &device
))) return device
;
78 present_parameters
.AutoDepthStencilFormat
= D3DFMT_D16
;
79 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, focus_window
,
80 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_parameters
, m
, &device
))) return device
;
82 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, focus_window
,
83 D3DCREATE_SOFTWARE_VERTEXPROCESSING
, &present_parameters
, m
, &device
))) return device
;
88 static ULONG
getref(IUnknown
*obj
) {
90 return IUnknown_Release(obj
);
93 static void test_qi_base_to_ex(void)
95 IDirect3D9
*d3d9
= pDirect3DCreate9(D3D_SDK_VERSION
);
96 IDirect3D9Ex
*d3d9ex
= (void *) 0xdeadbeef;
97 IDirect3DDevice9
*device
;
98 IDirect3DDevice9Ex
*deviceEx
= (void *) 0xdeadbeef;
100 HWND window
= create_window();
101 D3DPRESENT_PARAMETERS present_parameters
;
105 skip("Direct3D9 is not available\n");
109 hr
= IDirect3D9_QueryInterface(d3d9
, &IID_IDirect3D9Ex
, (void **) &d3d9ex
);
110 ok(hr
== E_NOINTERFACE
,
111 "IDirect3D9::QueryInterface for IID_IDirect3D9Ex returned %08x, expected E_NOINTERFACE\n",
113 ok(d3d9ex
== NULL
, "QueryInterface returned interface %p, expected NULL\n", d3d9ex
);
114 if(d3d9ex
) IDirect3D9Ex_Release(d3d9ex
);
116 memset(&present_parameters
, 0, sizeof(present_parameters
));
117 present_parameters
.Windowed
= TRUE
;
118 present_parameters
.hDeviceWindow
= window
;
119 present_parameters
.SwapEffect
= D3DSWAPEFFECT_COPY
;
120 present_parameters
.BackBufferWidth
= 640;
121 present_parameters
.BackBufferHeight
= 480;
122 present_parameters
.EnableAutoDepthStencil
= FALSE
;
123 present_parameters
.AutoDepthStencilFormat
= D3DFMT_D16
;
124 hr
= IDirect3D9_CreateDevice(d3d9
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, present_parameters
.hDeviceWindow
, D3DCREATE_SOFTWARE_VERTEXPROCESSING
, &present_parameters
, &device
);
126 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
130 hr
= IDirect3DDevice9_QueryInterface(device
, &IID_IDirect3DDevice9Ex
, (void **) &deviceEx
);
131 ok(hr
== E_NOINTERFACE
,
132 "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected E_NOINTERFACE\n",
134 ok(deviceEx
== NULL
, "QueryInterface returned interface %p, expected NULL\n", deviceEx
);
135 if(deviceEx
) IDirect3DDevice9Ex_Release(deviceEx
);
137 IDirect3DDevice9_Release(device
);
140 IDirect3D9_Release(d3d9
);
141 DestroyWindow(window
);
144 static void test_qi_ex_to_base(void)
146 IDirect3D9
*d3d9
= (void *) 0xdeadbeef;
147 IDirect3D9Ex
*d3d9ex
;
148 IDirect3DDevice9
*device
;
149 IDirect3DDevice9Ex
*deviceEx
= (void *) 0xdeadbeef;
151 HWND window
= create_window();
152 D3DPRESENT_PARAMETERS present_parameters
;
155 hr
= pDirect3DCreate9Ex(D3D_SDK_VERSION
, &d3d9ex
);
156 ok(hr
== D3D_OK
|| hr
== D3DERR_NOTAVAILABLE
, "Direct3DCreate9Ex returned %08x\n", hr
);
158 skip("Direct3D9Ex is not available\n");
162 hr
= IDirect3D9Ex_QueryInterface(d3d9ex
, &IID_IDirect3D9
, (void **) &d3d9
);
164 "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n",
166 ok(d3d9
!= NULL
&& d3d9
!= (void *) 0xdeadbeef,
167 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9
);
168 ref
= getref((IUnknown
*) d3d9ex
);
169 ok(ref
== 2, "IDirect3D9Ex refcount is %d, expected 2\n", ref
);
170 ref
= getref((IUnknown
*) d3d9
);
171 ok(ref
== 2, "IDirect3D9 refcount is %d, expected 2\n", ref
);
173 memset(&present_parameters
, 0, sizeof(present_parameters
));
174 present_parameters
.Windowed
= TRUE
;
175 present_parameters
.hDeviceWindow
= window
;
176 present_parameters
.SwapEffect
= D3DSWAPEFFECT_COPY
;
177 present_parameters
.BackBufferWidth
= 640;
178 present_parameters
.BackBufferHeight
= 480;
179 present_parameters
.EnableAutoDepthStencil
= FALSE
;
180 present_parameters
.AutoDepthStencilFormat
= D3DFMT_D16
;
182 /* First, try to create a normal device with IDirect3D9Ex::CreateDevice and QI it for IDirect3DDevice9Ex */
183 hr
= IDirect3D9Ex_CreateDevice(d3d9ex
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, present_parameters
.hDeviceWindow
, D3DCREATE_SOFTWARE_VERTEXPROCESSING
, &present_parameters
, &device
);
185 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
189 hr
= IDirect3DDevice9_QueryInterface(device
, &IID_IDirect3DDevice9Ex
, (void **) &deviceEx
);
191 "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n",
193 ok(deviceEx
!= NULL
&& deviceEx
!= (void *) 0xdeadbeef,
194 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx
);
195 ref
= getref((IUnknown
*) device
);
196 ok(ref
== 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref
);
197 ref
= getref((IUnknown
*) deviceEx
);
198 ok(ref
== 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref
);
199 if(deviceEx
) IDirect3DDevice9Ex_Release(deviceEx
);
200 IDirect3DDevice9_Release(device
);
202 /* Next, try to create a normal device with IDirect3D9::CreateDevice(non-ex) and QI it */
203 hr
= IDirect3D9_CreateDevice(d3d9
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, present_parameters
.hDeviceWindow
, D3DCREATE_SOFTWARE_VERTEXPROCESSING
, &present_parameters
, &device
);
205 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
209 hr
= IDirect3DDevice9_QueryInterface(device
, &IID_IDirect3DDevice9Ex
, (void **) &deviceEx
);
211 "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n",
213 ok(deviceEx
!= NULL
&& deviceEx
!= (void *) 0xdeadbeef,
214 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx
);
215 ref
= getref((IUnknown
*) device
);
216 ok(ref
== 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref
);
217 ref
= getref((IUnknown
*) deviceEx
);
218 ok(ref
== 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref
);
219 if(deviceEx
) IDirect3DDevice9Ex_Release(deviceEx
);
220 IDirect3DDevice9_Release(device
);
222 IDirect3D9_Release(d3d9
);
223 IDirect3D9Ex_Release(d3d9ex
);
226 DestroyWindow(window
);
229 static void test_get_adapter_luid(void)
231 HWND window
= create_window();
232 IDirect3D9Ex
*d3d9ex
;
237 hr
= pDirect3DCreate9Ex(D3D_SDK_VERSION
, &d3d9ex
);
240 skip("Direct3D9Ex is not available.\n");
241 DestroyWindow(window
);
245 count
= IDirect3D9Ex_GetAdapterCount(d3d9ex
);
248 skip("No adapters available.\n");
249 IDirect3D9Ex_Release(d3d9ex
);
250 DestroyWindow(window
);
254 hr
= IDirect3D9Ex_GetAdapterLUID(d3d9ex
, D3DADAPTER_DEFAULT
, &luid
);
255 ok(SUCCEEDED(hr
), "GetAdapterLUID failed, hr %#x.\n", hr
);
256 trace("adapter luid: %08x:%08x.\n", luid
.HighPart
, luid
.LowPart
);
258 IDirect3D9Ex_Release(d3d9ex
);
261 static void test_get_adapter_displaymode_ex(void)
263 HWND window
= create_window();
264 IDirect3D9
*d3d9
= (void *) 0xdeadbeef;
265 IDirect3D9Ex
*d3d9ex
;
269 D3DDISPLAYMODEEX mode_ex
;
270 D3DDISPLAYROTATION rotation
;
275 hr
= pDirect3DCreate9Ex(D3D_SDK_VERSION
, &d3d9ex
);
278 skip("Direct3D9Ex is not available (%#x)\n", hr
);
279 DestroyWindow(window
);
283 count
= IDirect3D9Ex_GetAdapterCount(d3d9ex
);
286 skip("No adapters available.\n");
287 IDirect3D9Ex_Release(d3d9ex
);
288 DestroyWindow(window
);
292 hr
= IDirect3D9Ex_QueryInterface(d3d9ex
, &IID_IDirect3D9
, (void **) &d3d9
);
294 "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n",
296 ok(d3d9
!= NULL
&& d3d9
!= (void *) 0xdeadbeef,
297 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9
);
298 /* change displayorientation*/
299 hdll
= GetModuleHandleA("user32.dll");
300 pEnumDisplaySettingsExA
= (void*)GetProcAddress(hdll
, "EnumDisplaySettingsExA");
301 pChangeDisplaySettingsExA
= (void*)GetProcAddress(hdll
, "ChangeDisplaySettingsExA");
303 if (!pEnumDisplaySettingsExA
|| !pChangeDisplaySettingsExA
) goto out
;
305 memset(&startmode
, 0, sizeof(startmode
));
306 startmode
.dmSize
= sizeof(startmode
);
307 retval
= pEnumDisplaySettingsExA(NULL
, ENUM_CURRENT_SETTINGS
, &startmode
, 0);
308 ok(retval
, "Failed to retrieve current display mode, retval %d.\n", retval
);
309 if (!retval
) goto out
;
311 startmode
.dmFields
= DM_DISPLAYORIENTATION
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
312 S2(U1(startmode
)).dmDisplayOrientation
= DMDO_180
;
313 retval
= pChangeDisplaySettingsExA(NULL
, &startmode
, NULL
, 0, NULL
);
315 if(retval
== DISP_CHANGE_BADMODE
)
317 trace(" Test skipped: graphics mode is not supported\n");
321 ok(retval
== DISP_CHANGE_SUCCESSFUL
,"ChangeDisplaySettingsEx failed with %d\n", retval
);
322 /* try retrieve orientation info with EnumDisplaySettingsEx*/
323 startmode
.dmFields
= 0;
324 S2(U1(startmode
)).dmDisplayOrientation
= 0;
325 ok(pEnumDisplaySettingsExA(NULL
, ENUM_CURRENT_SETTINGS
, &startmode
, EDS_ROTATEDMODE
), "EnumDisplaySettingsEx failed\n");
327 /*now that orientation has changed start tests for GetAdapterDisplayModeEx: invalid Size*/
328 memset(&mode_ex
, 0, sizeof(mode_ex
));
329 hr
= IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex
, D3DADAPTER_DEFAULT
, &mode_ex
, &rotation
);
330 ok(hr
== D3DERR_INVALIDCALL
, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr
);
332 mode_ex
.Size
= sizeof(D3DDISPLAYMODEEX
);
334 hr
= IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex
, count
+ 1, &mode_ex
, &rotation
);
335 ok(hr
== D3DERR_INVALIDCALL
, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr
);
336 /*valid count and valid Size*/
337 hr
= IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex
, D3DADAPTER_DEFAULT
, &mode_ex
, &rotation
);
338 ok(SUCCEEDED(hr
), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr
);
340 /* Compare what GetAdapterDisplayMode returns with what GetAdapterDisplayModeEx returns*/
341 hr
= IDirect3D9_GetAdapterDisplayMode(d3d9
, D3DADAPTER_DEFAULT
, &mode
);
342 ok(SUCCEEDED(hr
), "GetAdapterDisplayMode failed, hr %#x.\n", hr
);
344 ok(mode_ex
.Size
== sizeof(D3DDISPLAYMODEEX
), "size is %d\n", mode_ex
.Size
);
345 ok(mode_ex
.Width
== mode
.Width
, "width is %d instead of %d\n", mode_ex
.Width
, mode
.Width
);
346 ok(mode_ex
.Height
== mode
.Height
, "height is %d instead of %d\n", mode_ex
.Height
, mode
.Height
);
347 ok(mode_ex
.RefreshRate
== mode
.RefreshRate
, "RefreshRate is %d instead of %d\n",
348 mode_ex
.RefreshRate
, mode
.RefreshRate
);
349 ok(mode_ex
.Format
== mode
.Format
, "format is %x instead of %x\n", mode_ex
.Format
, mode
.Format
);
350 /* Don't know yet how to test for ScanLineOrdering, just testing that it
351 * is set to a value by GetAdapterDisplayModeEx(). */
352 ok(mode_ex
.ScanLineOrdering
!= 0, "ScanLineOrdering returned 0\n");
353 /* Check that orientation is returned correctly by GetAdapterDisplayModeEx
354 * and EnumDisplaySettingsEx(). */
355 todo_wine
ok(S2(U1(startmode
)).dmDisplayOrientation
== DMDO_180
&& rotation
== D3DDISPLAYROTATION_180
,
356 "rotation is %d instead of %d\n", rotation
, S2(U1(startmode
)).dmDisplayOrientation
);
358 trace("GetAdapterDisplayModeEx returned Width = %d,Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d\n",
359 mode_ex
.Width
, mode_ex
.Height
, mode_ex
.RefreshRate
, mode_ex
.Format
, mode_ex
.ScanLineOrdering
, rotation
);
361 /* test GetAdapterDisplayModeEx with null pointer for D3DDISPLAYROTATION */
362 memset(&mode_ex
, 0, sizeof(mode_ex
));
363 mode_ex
.Size
= sizeof(D3DDISPLAYMODEEX
);
365 hr
= IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex
, D3DADAPTER_DEFAULT
, &mode_ex
, NULL
);
366 ok(SUCCEEDED(hr
), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr
);
368 ok(mode_ex
.Size
== sizeof(D3DDISPLAYMODEEX
), "size is %d\n", mode_ex
.Size
);
369 ok(mode_ex
.Width
== mode
.Width
, "width is %d instead of %d\n", mode_ex
.Width
, mode
.Width
);
370 ok(mode_ex
.Height
== mode
.Height
, "height is %d instead of %d\n", mode_ex
.Height
, mode
.Height
);
371 ok(mode_ex
.RefreshRate
== mode
.RefreshRate
, "RefreshRate is %d instead of %d\n",
372 mode_ex
.RefreshRate
, mode
.RefreshRate
);
373 ok(mode_ex
.Format
== mode
.Format
, "format is %x instead of %x\n", mode_ex
.Format
, mode
.Format
);
374 /* Don't know yet how to test for ScanLineOrdering, just testing that it
375 * is set to a value by GetAdapterDisplayModeEx(). */
376 ok(mode_ex
.ScanLineOrdering
!= 0, "ScanLineOrdering returned 0\n");
378 /* return to the default mode */
379 pChangeDisplaySettingsExA(NULL
, NULL
, NULL
, 0, NULL
);
381 IDirect3D9_Release(d3d9
);
382 IDirect3D9Ex_Release(d3d9ex
);
385 static void test_texture_sysmem_create(void)
387 IDirect3DDevice9Ex
*device
;
388 IDirect3DTexture9
*texture
;
389 D3DLOCKED_RECT locked_rect
;
396 if (FAILED(hr
= pDirect3DCreate9Ex(D3D_SDK_VERSION
, &d3d9
)))
398 skip("Failed to create IDirect3D9Ex object (hr %#x), skipping tests.\n", hr
);
402 window
= create_window();
403 device
= create_device(d3d9
, window
, window
, TRUE
);
406 skip("Failed to create a D3D device, skipping tests.\n");
410 mem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 128 * 128 * 4);
411 hr
= IDirect3DDevice9Ex_CreateTexture(device
, 128, 128, 0, 0, D3DFMT_A8R8G8B8
,
412 D3DPOOL_SYSTEMMEM
, &texture
, &mem
);
413 ok(hr
== D3DERR_INVALIDCALL
, "Got unexpected hr %#x.\n", hr
);
414 hr
= IDirect3DDevice9Ex_CreateTexture(device
, 128, 128, 1, 0, D3DFMT_A8R8G8B8
,
415 D3DPOOL_SYSTEMMEM
, &texture
, &mem
);
416 ok(SUCCEEDED(hr
), "Failed to create texture, hr %#x.\n", hr
);
417 hr
= IDirect3DTexture9_LockRect(texture
, 0, &locked_rect
, NULL
, 0);
418 ok(SUCCEEDED(hr
), "Failed to lock texture, hr %#x.\n", hr
);
419 ok(locked_rect
.Pitch
== 128 * 4, "Got unexpected pitch %d.\n", locked_rect
.Pitch
);
420 ok(locked_rect
.pBits
== mem
, "Got unexpected pBits %p, expected %p.\n", locked_rect
.pBits
, mem
);
421 hr
= IDirect3DTexture9_UnlockRect(texture
, 0);
422 ok(SUCCEEDED(hr
), "Failed to unlock texture, hr %#x.\n", hr
);
423 IDirect3DTexture9_Release(texture
);
424 HeapFree(GetProcessHeap(), 0, mem
);
426 refcount
= IDirect3DDevice9Ex_Release(device
);
427 ok(!refcount
, "Device has %u references left.\n", refcount
);
430 DestroyWindow(window
);
432 IDirect3D9Ex_Release(d3d9
);
437 d3d9_handle
= LoadLibraryA("d3d9.dll");
440 skip("Could not load d3d9.dll\n");
443 pDirect3DCreate9
= (void *)GetProcAddress(d3d9_handle
, "Direct3DCreate9");
444 ok(pDirect3DCreate9
!= NULL
, "Failed to get address of Direct3DCreate9\n");
445 if(!pDirect3DCreate9
) {
449 pDirect3DCreate9Ex
= (void *)GetProcAddress(d3d9_handle
, "Direct3DCreate9Ex");
450 if (!pDirect3DCreate9Ex
) {
451 win_skip("Failed to get address of Direct3DCreate9Ex\n");
455 test_qi_base_to_ex();
456 test_qi_ex_to_base();
457 test_get_adapter_luid();
458 test_get_adapter_displaymode_ex();
459 test_texture_sysmem_create();