wined3d: Don't clamp vertex depth values.
[wine] / dlls / d3d9 / tests / d3d9ex.c
1 /*
2  * Copyright (C) 2008 Stefan Dösinger(for CodeWeavers)
3  * Copyright (C) 2010 Louis Lenders
4  *
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.
9  *
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.
14  *
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
18  */
19
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
22  */
23
24 #define COBJMACROS
25 #include "wine/test.h"
26 #include "winuser.h"
27 #include "wingdi.h"
28 #include <initguid.h>
29 #include <d3d9.h>
30
31 static HMODULE d3d9_handle = 0;
32
33 static BOOL (WINAPI *pEnumDisplaySettingsExA)(LPCSTR, DWORD, DEVMODEA *, DWORD);
34 static LONG (WINAPI *pChangeDisplaySettingsExA)(LPCSTR, LPDEVMODE, HWND, DWORD, LPVOID);
35
36 static IDirect3D9 * (WINAPI *pDirect3DCreate9)(UINT SDKVersion);
37 static HRESULT (WINAPI *pDirect3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **d3d9ex);
38
39 static HWND create_window(void)
40 {
41     WNDCLASS wc = {0};
42     HWND ret;
43     wc.lpfnWndProc = DefWindowProc;
44     wc.lpszClassName = "d3d9_test_wc";
45     RegisterClass(&wc);
46
47     ret = CreateWindow("d3d9_test_wc", "d3d9_test",
48                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
49     return ret;
50 }
51
52 static ULONG getref(IUnknown *obj) {
53     IUnknown_AddRef(obj);
54     return IUnknown_Release(obj);
55 }
56
57 static void test_qi_base_to_ex(void)
58 {
59     IDirect3D9 *d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
60     IDirect3D9Ex *d3d9ex = (void *) 0xdeadbeef;
61     IDirect3DDevice9 *device;
62     IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef;
63     HRESULT hr;
64     HWND window = create_window();
65     D3DPRESENT_PARAMETERS present_parameters;
66
67     if (!d3d9)
68     {
69         skip("Direct3D9 is not available\n");
70         return;
71     }
72
73     hr = IDirect3D9_QueryInterface(d3d9, &IID_IDirect3D9Ex, (void **) &d3d9ex);
74     ok(hr == E_NOINTERFACE,
75        "IDirect3D9::QueryInterface for IID_IDirect3D9Ex returned %08x, expected E_NOINTERFACE\n",
76        hr);
77     ok(d3d9ex == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9ex);
78     if(d3d9ex) IDirect3D9Ex_Release(d3d9ex);
79
80     memset(&present_parameters, 0, sizeof(present_parameters));
81     present_parameters.Windowed = TRUE;
82     present_parameters.hDeviceWindow = window;
83     present_parameters.SwapEffect = D3DSWAPEFFECT_COPY;
84     present_parameters.BackBufferWidth = 640;
85     present_parameters.BackBufferHeight = 480;
86     present_parameters.EnableAutoDepthStencil = FALSE;
87     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
88     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
89     if(FAILED(hr)) {
90         skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
91         goto out;
92     }
93
94     hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
95     ok(hr == E_NOINTERFACE,
96        "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected E_NOINTERFACE\n",
97        hr);
98     ok(deviceEx == NULL, "QueryInterface returned interface %p, expected NULL\n", deviceEx);
99     if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
100
101     IDirect3DDevice9_Release(device);
102
103 out:
104     IDirect3D9_Release(d3d9);
105     DestroyWindow(window);
106 }
107
108 static void test_qi_ex_to_base(void)
109 {
110     IDirect3D9 *d3d9 = (void *) 0xdeadbeef;
111     IDirect3D9Ex *d3d9ex;
112     IDirect3DDevice9 *device;
113     IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef;
114     HRESULT hr;
115     HWND window = create_window();
116     D3DPRESENT_PARAMETERS present_parameters;
117     ULONG ref;
118
119     hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
120     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Direct3DCreate9Ex returned %08x\n", hr);
121     if(FAILED(hr)) {
122         skip("Direct3D9Ex is not available\n");
123         goto out;
124     }
125
126     hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9);
127     ok(hr == D3D_OK,
128        "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n",
129        hr);
130     ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
131        "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
132     ref = getref((IUnknown *) d3d9ex);
133     ok(ref == 2, "IDirect3D9Ex refcount is %d, expected 2\n", ref);
134     ref = getref((IUnknown *) d3d9);
135     ok(ref == 2, "IDirect3D9 refcount is %d, expected 2\n", ref);
136
137     memset(&present_parameters, 0, sizeof(present_parameters));
138     present_parameters.Windowed = TRUE;
139     present_parameters.hDeviceWindow = window;
140     present_parameters.SwapEffect = D3DSWAPEFFECT_COPY;
141     present_parameters.BackBufferWidth = 640;
142     present_parameters.BackBufferHeight = 480;
143     present_parameters.EnableAutoDepthStencil = FALSE;
144     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
145
146     /* First, try to create a normal device with IDirect3D9Ex::CreateDevice and QI it for IDirect3DDevice9Ex */
147     hr = IDirect3D9Ex_CreateDevice(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
148     if(FAILED(hr)) {
149         skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
150         goto out;
151     }
152
153     hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
154     ok(hr == D3D_OK,
155        "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n",
156        hr);
157     ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef,
158        "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx);
159     ref = getref((IUnknown *) device);
160     ok(ref == 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref);
161     ref = getref((IUnknown *) deviceEx);
162     ok(ref == 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref);
163     if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
164     IDirect3DDevice9_Release(device);
165
166     /* Next, try to create a normal device with IDirect3D9::CreateDevice(non-ex) and QI it */
167     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
168     if(FAILED(hr)) {
169         skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
170         goto out;
171     }
172
173     hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
174     ok(hr == D3D_OK,
175        "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n",
176        hr);
177     ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef,
178        "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx);
179     ref = getref((IUnknown *) device);
180     ok(ref == 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref);
181     ref = getref((IUnknown *) deviceEx);
182     ok(ref == 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref);
183     if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
184     IDirect3DDevice9_Release(device);
185
186     IDirect3D9_Release(d3d9);
187     IDirect3D9Ex_Release(d3d9ex);
188
189 out:
190     DestroyWindow(window);
191 }
192
193 static void test_get_adapter_luid(void)
194 {
195     HWND window = create_window();
196     IDirect3D9Ex *d3d9ex;
197     UINT count;
198     HRESULT hr;
199     LUID luid;
200
201     hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
202     if (FAILED(hr))
203     {
204         skip("Direct3D9Ex is not available.\n");
205         DestroyWindow(window);
206         return;
207     }
208
209     count = IDirect3D9Ex_GetAdapterCount(d3d9ex);
210     if (!count)
211     {
212         skip("No adapters available.\n");
213         IDirect3D9Ex_Release(d3d9ex);
214         DestroyWindow(window);
215         return;
216     }
217
218     hr = IDirect3D9Ex_GetAdapterLUID(d3d9ex, D3DADAPTER_DEFAULT, &luid);
219     ok(SUCCEEDED(hr), "GetAdapterLUID failed, hr %#x.\n", hr);
220     trace("adapter luid: %08x:%08x.\n", luid.HighPart, luid.LowPart);
221
222     IDirect3D9Ex_Release(d3d9ex);
223 }
224
225 static void test_get_adapter_displaymode_ex(void)
226 {
227     HWND window = create_window();
228     IDirect3D9 *d3d9 = (void *) 0xdeadbeef;
229     IDirect3D9Ex *d3d9ex;
230     UINT count;
231     HRESULT hr;
232     D3DDISPLAYMODE mode;
233     D3DDISPLAYMODEEX mode_ex;
234     D3DDISPLAYROTATION rotation;
235     HANDLE hdll;
236     DEVMODEA startmode;
237     LONG retval;
238
239     hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
240     if (FAILED(hr))
241     {
242         skip("Direct3D9Ex is not available (%#x)\n", hr);
243         DestroyWindow(window);
244         return;
245     }
246
247     count = IDirect3D9Ex_GetAdapterCount(d3d9ex);
248     if (!count)
249     {
250         skip("No adapters available.\n");
251         IDirect3D9Ex_Release(d3d9ex);
252         DestroyWindow(window);
253         return;
254     }
255
256     hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9);
257     ok(hr == D3D_OK,
258        "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n",
259        hr);
260     ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
261        "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
262     /* change displayorientation*/
263     hdll = GetModuleHandleA("user32.dll");
264     pEnumDisplaySettingsExA = (void*)GetProcAddress(hdll, "EnumDisplaySettingsExA");
265     pChangeDisplaySettingsExA = (void*)GetProcAddress(hdll, "ChangeDisplaySettingsExA");
266
267     if (!pEnumDisplaySettingsExA || !pChangeDisplaySettingsExA) goto out;
268
269     memset(&startmode, 0, sizeof(startmode));
270     startmode.dmSize = sizeof(startmode);
271     retval = pEnumDisplaySettingsExA(NULL, ENUM_CURRENT_SETTINGS, &startmode, 0);
272     ok(retval, "Failed to retrieve current display mode, retval %d.\n", retval);
273     if (!retval) goto out;
274
275     startmode.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT;
276     S2(U1(startmode)).dmDisplayOrientation = DMDO_180;
277     retval = pChangeDisplaySettingsExA(NULL, &startmode, NULL, 0, NULL);
278
279     if(retval == DISP_CHANGE_BADMODE)
280     {
281         trace(" Test skipped: graphics mode is not supported\n");
282         goto out;
283     }
284
285     ok(retval == DISP_CHANGE_SUCCESSFUL,"ChangeDisplaySettingsEx failed with %d\n", retval);
286     /* try retrieve orientation info with EnumDisplaySettingsEx*/
287     startmode.dmFields = 0;
288     S2(U1(startmode)).dmDisplayOrientation = 0;
289     ok(pEnumDisplaySettingsExA(NULL, ENUM_CURRENT_SETTINGS, &startmode, EDS_ROTATEDMODE), "EnumDisplaySettingsEx failed\n");
290
291     /*now that orientation has changed start tests for GetAdapterDisplayModeEx: invalid Size*/
292     memset(&mode_ex, 0, sizeof(mode_ex));
293     hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
294     todo_wine ok(hr == D3DERR_INVALIDCALL, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr);
295
296     mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
297     /* invalid count*/
298     hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, count + 1, &mode_ex, &rotation);
299     todo_wine ok(hr == D3DERR_INVALIDCALL, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr);
300     /*valid count and valid Size*/
301     hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
302     todo_wine ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr);
303
304     /* Compare what GetAdapterDisplayMode returns with what GetAdapterDisplayModeEx returns*/
305     hr = IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &mode);
306     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
307
308     ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
309     todo_wine ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
310     todo_wine ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
311     todo_wine ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n", mode_ex.RefreshRate, mode.RefreshRate);
312     todo_wine ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
313     /* don't know yet how to test for ScanLineOrdering, just testing that it is set to a value by GetAdapterDisplayModeEx*/
314     todo_wine ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
315     /* check that orientation is returned correctly by GetAdapterDisplayModeEx and EnumDisplaySettingsEx*/
316     todo_wine ok(S2(U1(startmode)).dmDisplayOrientation == DMDO_180 && rotation == D3DDISPLAYROTATION_180, "rotation is %d instead of %d\n", rotation, S2(U1(startmode)).dmDisplayOrientation);
317
318     trace("GetAdapterDisplayModeEx returned Width = %d,Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d\n",
319           mode_ex.Width, mode_ex.Height, mode_ex.RefreshRate, mode_ex.Format, mode_ex.ScanLineOrdering, rotation);
320
321     /* test GetAdapterDisplayModeEx with null pointer for D3DDISPLAYROTATION */
322     memset(&mode_ex, 0, sizeof(mode_ex));
323     mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
324
325     hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, NULL);
326     todo_wine ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr);
327
328     ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
329     todo_wine ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
330     todo_wine ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
331     todo_wine ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n", mode_ex.RefreshRate, mode.RefreshRate);
332     todo_wine ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
333     /* don't know yet how to test for ScanLineOrdering, just testing that it is set to a value by GetAdapterDisplayModeEx*/
334     todo_wine ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
335
336     /* return to the default mode */
337     pChangeDisplaySettingsExA(NULL, NULL, NULL, 0, NULL);
338 out:
339     IDirect3D9_Release(d3d9);
340     IDirect3D9Ex_Release(d3d9ex);
341 }
342
343 START_TEST(d3d9ex)
344 {
345     d3d9_handle = LoadLibraryA("d3d9.dll");
346     if (!d3d9_handle)
347     {
348         skip("Could not load d3d9.dll\n");
349         return;
350     }
351     pDirect3DCreate9 = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
352     ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
353     if(!pDirect3DCreate9) {
354         return;
355     }
356
357     pDirect3DCreate9Ex = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9Ex");
358     if (!pDirect3DCreate9Ex) {
359         win_skip("Failed to get address of Direct3DCreate9Ex\n");
360         return;
361     }
362
363     test_qi_base_to_ex();
364     test_qi_ex_to_base();
365     test_get_adapter_luid();
366     test_get_adapter_displaymode_ex();
367 }