d3d9/tests: Make sure to use return values (LLVM/Clang).
[wine] / dlls / d3d9 / tests / device.c
1 /*
2  * Copyright (C) 2006 Vitaliy Margolen
3  * Copyright (C) 2006 Chris Robinson
4  * Copyright (C) 2006-2007 Stefan Dösinger(For CodeWeavers)
5  * Copyright 2007 Henri Verbeet
6  * Copyright (C) 2008 Rico Schüller
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #define COBJMACROS
24 #include <d3d9.h>
25 #include "wine/test.h"
26
27 static INT screen_width;
28 static INT screen_height;
29
30 static IDirect3D9 *(WINAPI *pDirect3DCreate9)(UINT);
31
32 static int get_refcount(IUnknown *object)
33 {
34     IUnknown_AddRef( object );
35     return IUnknown_Release( object );
36 }
37
38 /* try to make sure pending X events have been processed before continuing */
39 static void flush_events(void)
40 {
41     MSG msg;
42     int diff = 200;
43     int min_timeout = 100;
44     DWORD time = GetTickCount() + diff;
45
46     while (diff > 0)
47     {
48         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
49         while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
50         diff = time - GetTickCount();
51     }
52 }
53
54 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND device_window, HWND focus_window, BOOL windowed)
55 {
56     D3DPRESENT_PARAMETERS present_parameters = {0};
57     IDirect3DDevice9 *device;
58
59     present_parameters.Windowed = windowed;
60     present_parameters.hDeviceWindow = device_window;
61     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
62     present_parameters.BackBufferWidth = screen_width;
63     present_parameters.BackBufferHeight = screen_height;
64     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
65     present_parameters.EnableAutoDepthStencil = TRUE;
66     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
67
68     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
69             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
70
71     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
72     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
73             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
74
75     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
76             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
77
78     return NULL;
79 }
80
81 static HRESULT reset_device(IDirect3DDevice9 *device, HWND device_window, BOOL windowed)
82 {
83     D3DPRESENT_PARAMETERS present_parameters = {0};
84
85     present_parameters.Windowed = windowed;
86     present_parameters.hDeviceWindow = device_window;
87     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
88     present_parameters.BackBufferWidth = screen_width;
89     present_parameters.BackBufferHeight = screen_height;
90     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
91     present_parameters.EnableAutoDepthStencil = TRUE;
92     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
93
94     return IDirect3DDevice9_Reset(device, &present_parameters);
95 }
96
97 #define CHECK_CALL(r,c,d,rc) \
98     if (SUCCEEDED(r)) {\
99         int tmp1 = get_refcount( (IUnknown *)d ); \
100         int rc_new = rc; \
101         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
102     } else {\
103         trace("%s failed: %08x\n", c, r); \
104     }
105
106 #define CHECK_RELEASE(obj,d,rc) \
107     if (obj) { \
108         int tmp1, rc_new = rc; \
109         IUnknown_Release( obj ); \
110         tmp1 = get_refcount( (IUnknown *)d ); \
111         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
112     }
113
114 #define CHECK_REFCOUNT(obj,rc) \
115     { \
116         int rc_new = rc; \
117         int count = get_refcount( (IUnknown *)obj ); \
118         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
119     }
120
121 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
122     { \
123         int rc_new = rc; \
124         int count = IUnknown_Release( (IUnknown *)obj ); \
125         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
126     }
127
128 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
129     { \
130         int rc_new = rc; \
131         int count = IUnknown_AddRef( (IUnknown *)obj ); \
132         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
133     }
134
135 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
136     { \
137         void *container_ptr = (void *)0x1337c0d3; \
138         hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
139         ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
140             "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
141         if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
142     }
143
144 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
145 {
146     IDirect3DBaseTexture9* texture = NULL;
147     HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
148             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
149
150     if (SUCCEEDED(hr)) {
151         DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
152         ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
153     } else
154         trace("CreateTexture failed: %08x\n", hr);
155
156     if (texture) IUnknown_Release( texture );
157 }
158
159 static void test_mipmap_levels(void)
160 {
161
162     HRESULT               hr;
163     HWND                  hwnd = NULL;
164
165     IDirect3D9            *pD3d = NULL;
166     IDirect3DDevice9      *pDevice = NULL;
167     D3DPRESENT_PARAMETERS d3dpp;
168     D3DDISPLAYMODE        d3ddm;
169
170     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
171     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
172     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
173     ok(hwnd != NULL, "Failed to create window\n");
174     if (!pD3d || !hwnd) goto cleanup;
175
176     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
177     ZeroMemory( &d3dpp, sizeof(d3dpp) );
178     d3dpp.Windowed         = TRUE;
179     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
180     d3dpp.BackBufferFormat = d3ddm.Format;
181
182     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
183                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
184     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
185     if (FAILED(hr)) {
186         skip("failed to create a d3d device\n");
187         goto cleanup;
188     }
189
190     check_mipmap_levels(pDevice, 32, 32, 6);
191     check_mipmap_levels(pDevice, 256, 1, 9);
192     check_mipmap_levels(pDevice, 1, 256, 9);
193     check_mipmap_levels(pDevice, 1, 1, 1);
194
195 cleanup:
196     if (pDevice)
197     {
198         UINT refcount = IUnknown_Release( pDevice );
199         ok(!refcount, "Device has %u references left.\n", refcount);
200     }
201     if (pD3d) IUnknown_Release( pD3d );
202     DestroyWindow( hwnd );
203 }
204
205 static void test_checkdevicemultisampletype(void)
206 {
207
208     HRESULT               hr;
209     HWND                  hwnd = NULL;
210
211     IDirect3D9            *pD3d = NULL;
212     IDirect3DDevice9      *pDevice = NULL;
213     D3DPRESENT_PARAMETERS d3dpp;
214     D3DDISPLAYMODE        d3ddm;
215     DWORD                 qualityLevels;
216
217     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
218     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
219     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
220     ok(hwnd != NULL, "Failed to create window\n");
221     if (!pD3d || !hwnd) goto cleanup;
222
223     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
224     ZeroMemory( &d3dpp, sizeof(d3dpp) );
225     d3dpp.Windowed         = TRUE;
226     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
227     d3dpp.BackBufferFormat = d3ddm.Format;
228
229     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
230                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
231     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
232     if (FAILED(hr)) {
233         skip("failed to create a d3d device\n");
234         goto cleanup;
235     }
236
237     qualityLevels = 0;
238
239     hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE,
240     D3DMULTISAMPLE_NONE, &qualityLevels);
241     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
242     if(hr == D3DERR_NOTAVAILABLE)
243     {
244         skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
245         goto cleanup;
246     }
247     ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
248
249     hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, FALSE,
250     D3DMULTISAMPLE_NONE, &qualityLevels);
251     ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
252     ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
253
254 cleanup:
255     if (pDevice)
256     {
257         UINT refcount = IUnknown_Release( pDevice );
258         ok(!refcount, "Device has %u references left.\n", refcount);
259     }
260     if (pD3d) IUnknown_Release( pD3d );
261     DestroyWindow( hwnd );
262 }
263
264 static void test_swapchain(void)
265 {
266     HRESULT                      hr;
267     HWND                         hwnd               = NULL;
268     IDirect3D9                  *pD3d               = NULL;
269     IDirect3DDevice9            *pDevice            = NULL;
270     IDirect3DSwapChain9         *swapchain0         = NULL;
271     IDirect3DSwapChain9         *swapchain1         = NULL;
272     IDirect3DSwapChain9         *swapchain2         = NULL;
273     IDirect3DSwapChain9         *swapchain3         = NULL;
274     IDirect3DSwapChain9         *swapchainX         = NULL;
275     IDirect3DSurface9           *backbuffer         = NULL;
276     D3DPRESENT_PARAMETERS        d3dpp;
277     D3DDISPLAYMODE               d3ddm;
278
279     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
280     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
281     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
282     ok(hwnd != NULL, "Failed to create window\n");
283     if (!pD3d || !hwnd) goto cleanup;
284
285     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
286     ZeroMemory( &d3dpp, sizeof(d3dpp) );
287     d3dpp.Windowed         = TRUE;
288     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
289     d3dpp.BackBufferFormat = d3ddm.Format;
290     d3dpp.BackBufferCount  = 0;
291
292     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
293                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
294     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
295        "Failed to create IDirect3D9Device (%08x)\n", hr);
296     if (FAILED(hr)) goto cleanup;
297
298     /* Check if the back buffer count was modified */
299     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
300
301     /* Get the implicit swapchain */
302     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &swapchain0);
303     ok(SUCCEEDED(hr), "Failed to get the impicit swapchain (%08x)\n", hr);
304     if(swapchain0) IDirect3DSwapChain9_Release(swapchain0);
305
306     /* Check if there is a back buffer */
307     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
308     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
309     ok(backbuffer != NULL, "The back buffer is NULL\n");
310     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
311
312     /* Try to get a nonexistent swapchain */
313     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
314     ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
315     ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
316     if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
317
318     /* Create a bunch of swapchains */
319     d3dpp.BackBufferCount = 0;
320     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
321     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
322     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
323
324     d3dpp.BackBufferCount  = 1;
325     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
326     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
327
328     d3dpp.BackBufferCount  = 2;
329     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
330     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
331     if(SUCCEEDED(hr)) {
332         /* Swapchain 3, created with backbuffercount 2 */
333         backbuffer = (void *) 0xdeadbeef;
334         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
335         ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
336         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
337         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
338
339         backbuffer = (void *) 0xdeadbeef;
340         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
341         ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
342         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
343         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
344
345         backbuffer = (void *) 0xdeadbeef;
346         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
347         ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
348         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
349         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
350
351         backbuffer = (void *) 0xdeadbeef;
352         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
353         ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
354         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
355         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
356     }
357
358     /* Check the back buffers of the swapchains */
359     /* Swapchain 1, created with backbuffercount 0 */
360     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
361     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
362     ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
363     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
364
365     backbuffer = (void *) 0xdeadbeef;
366     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
367     ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
368     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
369     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
370
371     /* Swapchain 2 - created with backbuffercount 1 */
372     backbuffer = (void *) 0xdeadbeef;
373     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
374     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
375     ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
376     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
377
378     backbuffer = (void *) 0xdeadbeef;
379     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
380     ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
381     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
382     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
383
384     backbuffer = (void *) 0xdeadbeef;
385     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
386     ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
387     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
388     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
389
390     /* Try getSwapChain on a manually created swapchain
391      * it should fail, apparently GetSwapChain only returns implicit swapchains
392      */
393     swapchainX = (void *) 0xdeadbeef;
394     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
395     ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
396     ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
397     if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
398
399 cleanup:
400     if(swapchain1) IDirect3DSwapChain9_Release(swapchain1);
401     if(swapchain2) IDirect3DSwapChain9_Release(swapchain2);
402     if(swapchain3) IDirect3DSwapChain9_Release(swapchain3);
403     if (pDevice)
404     {
405         UINT refcount = IDirect3DDevice9_Release(pDevice);
406         ok(!refcount, "Device has %u references left.\n", refcount);
407     }
408     if (pD3d) IDirect3D9_Release(pD3d);
409     DestroyWindow( hwnd );
410 }
411
412 /* Shared between two functions */
413 static const DWORD simple_vs[] = {0xFFFE0101,       /* vs_1_1               */
414     0x0000001F, 0x80000000, 0x900F0000,             /* dcl_position0 v0     */
415     0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0   */
416     0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1   */
417     0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2   */
418     0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3   */
419     0x0000FFFF};                                    /* END                  */
420
421 static void test_refcount(void)
422 {
423     HRESULT                      hr;
424     HWND                         hwnd               = NULL;
425     IDirect3D9                  *pD3d               = NULL;
426     IDirect3DDevice9            *pDevice            = NULL;
427     IDirect3DVertexBuffer9      *pVertexBuffer      = NULL;
428     IDirect3DIndexBuffer9       *pIndexBuffer       = NULL;
429     IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
430     IDirect3DVertexShader9      *pVertexShader      = NULL;
431     IDirect3DPixelShader9       *pPixelShader       = NULL;
432     IDirect3DCubeTexture9       *pCubeTexture       = NULL;
433     IDirect3DTexture9           *pTexture           = NULL;
434     IDirect3DVolumeTexture9     *pVolumeTexture     = NULL;
435     IDirect3DVolume9            *pVolumeLevel       = NULL;
436     IDirect3DSurface9           *pStencilSurface    = NULL;
437     IDirect3DSurface9           *pOffscreenSurface  = NULL;
438     IDirect3DSurface9           *pRenderTarget      = NULL;
439     IDirect3DSurface9           *pRenderTarget2     = NULL;
440     IDirect3DSurface9           *pRenderTarget3     = NULL;
441     IDirect3DSurface9           *pTextureLevel      = NULL;
442     IDirect3DSurface9           *pBackBuffer        = NULL;
443     IDirect3DStateBlock9        *pStateBlock        = NULL;
444     IDirect3DStateBlock9        *pStateBlock1       = NULL;
445     IDirect3DSwapChain9         *pSwapChain         = NULL;
446     IDirect3DQuery9             *pQuery             = NULL;
447     D3DPRESENT_PARAMETERS        d3dpp;
448     D3DDISPLAYMODE               d3ddm;
449     int                          refcount = 0, tmp;
450
451     D3DVERTEXELEMENT9 decl[] =
452     {
453         D3DDECL_END()
454     };
455     static DWORD simple_ps[] = {0xFFFF0101,                                     /* ps_1_1                       */
456         0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
457         0x00000042, 0xB00F0000,                                                 /* tex t0                       */
458         0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000,                         /* dp3 r0, c1, c0               */
459         0x00000005, 0x800F0000, 0x90E40000, 0x80E40000,                         /* mul r0, v0, r0               */
460         0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000,                         /* mul r0, t0, r0               */
461         0x0000FFFF};                                                            /* END                          */
462
463
464     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
465     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
466     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
467     ok(hwnd != NULL, "Failed to create window\n");
468     if (!pD3d || !hwnd) goto cleanup;
469
470     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
471     ZeroMemory( &d3dpp, sizeof(d3dpp) );
472     d3dpp.Windowed         = TRUE;
473     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
474     d3dpp.BackBufferFormat = d3ddm.Format;
475     d3dpp.EnableAutoDepthStencil = TRUE;
476     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
477
478     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
479                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
480     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
481        "Failed to create IDirect3D9Device (%08x)\n", hr);
482     if (FAILED(hr)) goto cleanup;
483
484     refcount = get_refcount( (IUnknown *)pDevice );
485     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
486
487     /**
488      * Check refcount of implicit surfaces and implicit swapchain. Findings:
489      *   - the container is the device OR swapchain
490      *   - they hold a reference to the device
491      *   - they are created with a refcount of 0 (Get/Release returns original refcount)
492      *   - they are not freed if refcount reaches 0.
493      *   - the refcount is not forwarded to the container.
494      */
495     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
496     CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
497     if (pSwapChain)
498     {
499         CHECK_REFCOUNT( pSwapChain, 1);
500
501         hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
502         CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
503         CHECK_REFCOUNT( pSwapChain, 1);
504         if(pRenderTarget)
505         {
506             CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
507             CHECK_REFCOUNT( pRenderTarget, 1);
508
509             CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
510             CHECK_REFCOUNT(pDevice, refcount);
511             CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
512             CHECK_REFCOUNT(pDevice, refcount);
513
514             hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
515             CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
516             CHECK_REFCOUNT( pRenderTarget, 2);
517             CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
518             CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
519             CHECK_REFCOUNT( pDevice, --refcount);
520
521             /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
522             CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
523             CHECK_REFCOUNT(pDevice, ++refcount);
524             CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
525             CHECK_REFCOUNT(pDevice, --refcount);
526         }
527
528         /* Render target and back buffer are identical. */
529         hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
530         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
531         if(pBackBuffer)
532         {
533             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
534             ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
535             pRenderTarget, pBackBuffer);
536             pBackBuffer = NULL;
537         }
538         CHECK_REFCOUNT( pDevice, --refcount);
539
540         hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
541         CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
542         CHECK_REFCOUNT( pSwapChain, 1);
543         if(pStencilSurface)
544         {
545             CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
546             CHECK_REFCOUNT( pStencilSurface, 1);
547
548             CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
549             CHECK_REFCOUNT(pDevice, refcount);
550             CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
551             CHECK_REFCOUNT(pDevice, refcount);
552
553             CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
554             CHECK_REFCOUNT( pDevice, --refcount);
555
556             /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
557             CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
558             CHECK_REFCOUNT(pDevice, ++refcount);
559             CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
560             CHECK_REFCOUNT(pDevice, --refcount);
561             pStencilSurface = NULL;
562         }
563
564         CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
565         CHECK_REFCOUNT( pDevice, --refcount);
566
567         /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
568         CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
569         CHECK_REFCOUNT(pDevice, ++refcount);
570         CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
571         CHECK_REFCOUNT(pDevice, --refcount);
572         pSwapChain = NULL;
573     }
574
575     /* Buffers */
576     hr = IDirect3DDevice9_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL );
577     CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
578     if(pIndexBuffer)
579     {
580         tmp = get_refcount( (IUnknown *)pIndexBuffer );
581
582         hr = IDirect3DDevice9_SetIndices(pDevice, pIndexBuffer);
583         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
584         hr = IDirect3DDevice9_SetIndices(pDevice, NULL);
585         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
586     }
587
588     hr = IDirect3DDevice9_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
589     CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
590     if(pVertexBuffer)
591     {
592         IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
593         UINT offset = ~0;
594         UINT stride = ~0;
595
596         tmp = get_refcount( (IUnknown *)pVertexBuffer );
597
598         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, pVertexBuffer, 0, 3 * sizeof(float));
599         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
600         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, NULL, 0, 0);
601         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
602
603         hr = IDirect3DDevice9_GetStreamSource(pDevice, 0, &pVBuf, &offset, &stride);
604         ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
605         ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
606         ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
607         ok(offset==0, "offset not 0 (got %u)!\n", offset);
608     }
609     /* Shaders */
610     hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, decl, &pVertexDeclaration );
611     CHECK_CALL( hr, "CreateVertexDeclaration", pDevice, ++refcount );
612     hr = IDirect3DDevice9_CreateVertexShader( pDevice, simple_vs, &pVertexShader );
613     CHECK_CALL( hr, "CreateVertexShader", pDevice, ++refcount );
614     hr = IDirect3DDevice9_CreatePixelShader( pDevice, simple_ps, &pPixelShader );
615     CHECK_CALL( hr, "CreatePixelShader", pDevice, ++refcount );
616     /* Textures */
617     hr = IDirect3DDevice9_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL );
618     CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
619     if (pTexture)
620     {
621         tmp = get_refcount( (IUnknown *)pTexture );
622
623         /* SetTexture should not increase refcounts */
624         hr = IDirect3DDevice9_SetTexture(pDevice, 0, (IDirect3DBaseTexture9 *) pTexture);
625         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
626         hr = IDirect3DDevice9_SetTexture(pDevice, 0, NULL);
627         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
628
629         /* This should not increment device refcount */
630         hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
631         CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
632         /* But should increment texture's refcount */
633         CHECK_REFCOUNT( pTexture, tmp+1 );
634         /* Because the texture and surface refcount are identical */
635         if (pTextureLevel)
636         {
637             CHECK_REFCOUNT        ( pTextureLevel, tmp+1 );
638             CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
639             CHECK_REFCOUNT        ( pTexture     , tmp+2 );
640             CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
641             CHECK_REFCOUNT        ( pTexture     , tmp+1 );
642             CHECK_RELEASE_REFCOUNT( pTexture     , tmp   );
643             CHECK_REFCOUNT        ( pTextureLevel, tmp   );
644         }
645     }
646     hr = IDirect3DDevice9_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL );
647     CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
648     hr = IDirect3DDevice9_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL );
649     CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
650     if (pVolumeTexture)
651     {
652         tmp = get_refcount( (IUnknown *)pVolumeTexture );
653
654         /* This should not increment device refcount */
655         hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
656         CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
657         /* But should increment volume texture's refcount */
658         CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
659         /* Because the volume texture and volume refcount are identical */
660         if (pVolumeLevel)
661         {
662             CHECK_REFCOUNT        ( pVolumeLevel  , tmp+1 );
663             CHECK_ADDREF_REFCOUNT ( pVolumeLevel  , tmp+2 );
664             CHECK_REFCOUNT        ( pVolumeTexture, tmp+2 );
665             CHECK_RELEASE_REFCOUNT( pVolumeLevel  , tmp+1 );
666             CHECK_REFCOUNT        ( pVolumeTexture, tmp+1 );
667             CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp   );
668             CHECK_REFCOUNT        ( pVolumeLevel  , tmp   );
669         }
670     }
671     /* Surfaces */
672     hr = IDirect3DDevice9_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL );
673     CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
674     CHECK_REFCOUNT( pStencilSurface, 1 );
675     hr = IDirect3DDevice9_CreateOffscreenPlainSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL );
676     CHECK_CALL( hr, "CreateOffscreenPlainSurface", pDevice, ++refcount );
677     CHECK_REFCOUNT( pOffscreenSurface, 1 );
678     hr = IDirect3DDevice9_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL );
679     CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
680     CHECK_REFCOUNT( pRenderTarget3, 1 );
681     /* Misc */
682     hr = IDirect3DDevice9_CreateStateBlock( pDevice, D3DSBT_ALL, &pStateBlock );
683     CHECK_CALL( hr, "CreateStateBlock", pDevice, ++refcount );
684     hr = IDirect3DDevice9_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
685     CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
686     if(pSwapChain)
687     {
688         /* check implicit back buffer */
689         hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
690         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
691         CHECK_REFCOUNT( pSwapChain, 1);
692         if(pBackBuffer)
693         {
694             CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
695             CHECK_REFCOUNT( pBackBuffer, 1);
696             CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
697             CHECK_REFCOUNT( pDevice, --refcount);
698
699             /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
700             CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
701             CHECK_REFCOUNT(pDevice, ++refcount);
702             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
703             CHECK_REFCOUNT(pDevice, --refcount);
704             pBackBuffer = NULL;
705         }
706         CHECK_REFCOUNT( pSwapChain, 1);
707     }
708     hr = IDirect3DDevice9_CreateQuery( pDevice, D3DQUERYTYPE_EVENT, &pQuery );
709     CHECK_CALL( hr, "CreateQuery", pDevice, ++refcount );
710
711     hr = IDirect3DDevice9_BeginStateBlock( pDevice );
712     CHECK_CALL( hr, "BeginStateBlock", pDevice, refcount );
713     hr = IDirect3DDevice9_EndStateBlock( pDevice, &pStateBlock1 );
714     CHECK_CALL( hr, "EndStateBlock", pDevice, ++refcount );
715
716     /* The implicit render target is not freed if refcount reaches 0.
717      * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
718     hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget2);
719     CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
720     if(pRenderTarget2)
721     {
722         CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
723         ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
724            pRenderTarget, pRenderTarget2);
725         CHECK_REFCOUNT( pDevice, --refcount);
726         pRenderTarget2 = NULL;
727     }
728     pRenderTarget = NULL;
729
730 cleanup:
731     CHECK_RELEASE(pDevice,              pDevice, --refcount);
732
733     /* Buffers */
734     CHECK_RELEASE(pVertexBuffer,        pDevice, --refcount);
735     CHECK_RELEASE(pIndexBuffer,         pDevice, --refcount);
736     /* Shaders */
737     CHECK_RELEASE(pVertexDeclaration,   pDevice, --refcount);
738     CHECK_RELEASE(pVertexShader,        pDevice, --refcount);
739     CHECK_RELEASE(pPixelShader,         pDevice, --refcount);
740     /* Textures */
741     CHECK_RELEASE(pTextureLevel,        pDevice, --refcount);
742     CHECK_RELEASE(pCubeTexture,         pDevice, --refcount);
743     CHECK_RELEASE(pVolumeTexture,       pDevice, --refcount);
744     /* Surfaces */
745     CHECK_RELEASE(pStencilSurface,      pDevice, --refcount);
746     CHECK_RELEASE(pOffscreenSurface,    pDevice, --refcount);
747     CHECK_RELEASE(pRenderTarget3,       pDevice, --refcount);
748     /* Misc */
749     CHECK_RELEASE(pStateBlock,          pDevice, --refcount);
750     CHECK_RELEASE(pSwapChain,           pDevice, --refcount);
751     CHECK_RELEASE(pQuery,               pDevice, --refcount);
752     /* This will destroy device - cannot check the refcount here */
753     if (pStateBlock1)         CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
754
755     if (pD3d)                 CHECK_RELEASE_REFCOUNT( pD3d, 0);
756
757     DestroyWindow( hwnd );
758 }
759
760 static void test_cursor(void)
761 {
762     HRESULT                      hr;
763     HWND                         hwnd               = NULL;
764     IDirect3D9                  *pD3d               = NULL;
765     IDirect3DDevice9            *pDevice            = NULL;
766     D3DPRESENT_PARAMETERS        d3dpp;
767     D3DDISPLAYMODE               d3ddm;
768     CURSORINFO                   info;
769     IDirect3DSurface9 *cursor = NULL;
770     HCURSOR cur;
771
772     memset(&info, 0, sizeof(info));
773     info.cbSize = sizeof(info);
774     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
775     cur = info.hCursor;
776
777     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
778     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
779     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
780     ok(hwnd != NULL, "Failed to create window\n");
781     if (!pD3d || !hwnd) goto cleanup;
782
783     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
784     ZeroMemory( &d3dpp, sizeof(d3dpp) );
785     d3dpp.Windowed         = TRUE;
786     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
787     d3dpp.BackBufferFormat = d3ddm.Format;
788
789     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
790                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
791     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
792        "Failed to create IDirect3D9Device (%08x)\n", hr);
793     if (FAILED(hr)) goto cleanup;
794
795     IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, 0);
796     ok(cursor != NULL, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
797
798     /* Initially hidden */
799     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
800     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
801
802     /* Not enabled without a surface*/
803     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
804     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
805
806     /* Fails */
807     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, NULL);
808     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
809
810     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, cursor);
811     ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
812
813     IDirect3DSurface9_Release(cursor);
814
815     memset(&info, 0, sizeof(info));
816     info.cbSize = sizeof(info);
817     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
818     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
819     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
820
821     /* Still hidden */
822     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
823     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
824
825     /* Enabled now*/
826     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
827     ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
828
829     /* GDI cursor unchanged */
830     memset(&info, 0, sizeof(info));
831     info.cbSize = sizeof(info);
832     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
833     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
834     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
835
836 cleanup:
837     if (pDevice)
838     {
839         UINT refcount = IDirect3DDevice9_Release(pDevice);
840         ok(!refcount, "Device has %u references left.\n", refcount);
841     }
842     if (pD3d) IDirect3D9_Release(pD3d);
843     DestroyWindow( hwnd );
844 }
845
846 static void test_reset(void)
847 {
848     HRESULT                      hr;
849     HWND                         hwnd               = NULL;
850     IDirect3D9                  *pD3d               = NULL;
851     IDirect3DDevice9            *pDevice            = NULL;
852     D3DPRESENT_PARAMETERS        d3dpp;
853     D3DDISPLAYMODE               d3ddm, d3ddm2;
854     D3DVIEWPORT9                 vp;
855     DWORD                        width, orig_width = GetSystemMetrics(SM_CXSCREEN);
856     DWORD                        height, orig_height = GetSystemMetrics(SM_CYSCREEN);
857     IDirect3DSwapChain9          *pSwapchain;
858     IDirect3DSurface9            *surface;
859     IDirect3DTexture9            *texture;
860     IDirect3DVertexShader9       *shader;
861     UINT                         i, adapter_mode_count;
862     D3DLOCKED_RECT               lockrect;
863     struct
864     {
865         UINT w;
866         UINT h;
867     } *modes = NULL;
868     UINT mode_count = 0;
869
870     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
871     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
872     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
873     ok(hwnd != NULL, "Failed to create window\n");
874     if (!pD3d || !hwnd) goto cleanup;
875
876     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
877     adapter_mode_count = IDirect3D9_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format);
878     modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
879     for(i = 0; i < adapter_mode_count; ++i)
880     {
881         UINT j;
882         ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
883         hr = IDirect3D9_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
884         ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
885
886         for (j = 0; j < mode_count; ++j)
887         {
888             if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
889                 break;
890         }
891         if (j == mode_count)
892         {
893             modes[j].w = d3ddm2.Width;
894             modes[j].h = d3ddm2.Height;
895             ++mode_count;
896         }
897
898         /* We use them as invalid modes */
899         if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
900            (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
901             skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
902                  d3ddm2.Width, d3ddm2.Height);
903             goto cleanup;
904         }
905     }
906
907     if (mode_count < 2)
908     {
909         skip("Less than 2 modes supported, skipping mode tests\n");
910         goto cleanup;
911     }
912
913     i = 0;
914     if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
915
916     ZeroMemory( &d3dpp, sizeof(d3dpp) );
917     d3dpp.Windowed         = FALSE;
918     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
919     d3dpp.BackBufferWidth  = modes[i].w;
920     d3dpp.BackBufferHeight = modes[i].h;
921     d3dpp.BackBufferFormat = d3ddm.Format;
922     d3dpp.EnableAutoDepthStencil = TRUE;
923     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
924
925     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
926                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
927
928     if(FAILED(hr))
929     {
930         skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
931         goto cleanup;
932     }
933     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
934     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
935
936     width = GetSystemMetrics(SM_CXSCREEN);
937     height = GetSystemMetrics(SM_CYSCREEN);
938     ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
939     ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
940
941     hr = IDirect3DDevice9_GetViewport(pDevice, &vp);
942     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
943     if(SUCCEEDED(hr))
944     {
945         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
946         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
947         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
948         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
949         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
950         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
951     }
952
953     i = 1;
954     vp.X = 10;
955     vp.Y = 20;
956     vp.MinZ = 2;
957     vp.MaxZ = 3;
958     hr = IDirect3DDevice9_SetViewport(pDevice, &vp);
959     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
960
961     ZeroMemory( &d3dpp, sizeof(d3dpp) );
962     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
963     d3dpp.Windowed         = FALSE;
964     d3dpp.BackBufferWidth  = modes[i].w;
965     d3dpp.BackBufferHeight = modes[i].h;
966     d3dpp.BackBufferFormat = d3ddm.Format;
967     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
968     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
969     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
970     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
971
972     ZeroMemory(&vp, sizeof(vp));
973     hr = IDirect3DDevice9_GetViewport(pDevice, &vp);
974     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
975     if(SUCCEEDED(hr))
976     {
977         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
978         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
979         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
980         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
981         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
982         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
983     }
984
985     width = GetSystemMetrics(SM_CXSCREEN);
986     height = GetSystemMetrics(SM_CYSCREEN);
987     ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
988     ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
989
990     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapchain);
991     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
992     if(SUCCEEDED(hr))
993     {
994         ZeroMemory(&d3dpp, sizeof(d3dpp));
995         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
996         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
997         if(SUCCEEDED(hr))
998         {
999             ok(d3dpp.BackBufferWidth == modes[i].w, "Back buffer width is %u, expected %u\n",
1000                     d3dpp.BackBufferWidth, modes[i].w);
1001             ok(d3dpp.BackBufferHeight == modes[i].h, "Back buffer height is %u, expected %u\n",
1002                     d3dpp.BackBufferHeight, modes[i].h);
1003         }
1004         IDirect3DSwapChain9_Release(pSwapchain);
1005     }
1006
1007     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1008     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1009     d3dpp.Windowed         = TRUE;
1010     d3dpp.BackBufferWidth  = 400;
1011     d3dpp.BackBufferHeight = 300;
1012     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1013     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1014     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1015     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1016
1017     width = GetSystemMetrics(SM_CXSCREEN);
1018     height = GetSystemMetrics(SM_CYSCREEN);
1019     ok(width == orig_width, "Screen width is %d\n", width);
1020     ok(height == orig_height, "Screen height is %d\n", height);
1021
1022     ZeroMemory(&vp, sizeof(vp));
1023     hr = IDirect3DDevice9_GetViewport(pDevice, &vp);
1024     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1025     if(SUCCEEDED(hr))
1026     {
1027         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1028         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1029         ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1030         ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1031         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1032         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1033     }
1034
1035     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapchain);
1036     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1037     if(SUCCEEDED(hr))
1038     {
1039         ZeroMemory(&d3dpp, sizeof(d3dpp));
1040         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1041         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1042         if(SUCCEEDED(hr))
1043         {
1044             ok(d3dpp.BackBufferWidth == 400, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1045             ok(d3dpp.BackBufferHeight == 300, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1046         }
1047         IDirect3DSwapChain9_Release(pSwapchain);
1048     }
1049
1050     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1051     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1052     d3dpp.Windowed         = TRUE;
1053     d3dpp.BackBufferWidth  = 400;
1054     d3dpp.BackBufferHeight = 300;
1055
1056     /* _Reset fails if there is a resource in the default pool */
1057     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1058     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1059     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1060     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1061     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1062     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1063     IDirect3DSurface9_Release(surface);
1064     /* Reset again to get the device out of the lost state */
1065     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1066     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1067     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1068     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1069
1070     /* Scratch, sysmem and managed pools are fine */
1071     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1072     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1073     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1074     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1075     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1076     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1077     IDirect3DSurface9_Release(surface);
1078
1079     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1080     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1081     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1082     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1083     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1084     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1085     IDirect3DSurface9_Release(surface);
1086
1087     /* The depth stencil should get reset to the auto depth stencil when present. */
1088     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
1089     ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
1090
1091     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &surface);
1092     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1093     ok(surface == NULL, "Depth stencil should be NULL\n");
1094
1095     d3dpp.EnableAutoDepthStencil = TRUE;
1096     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1097     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1098     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1099
1100     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &surface);
1101     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1102     ok(surface != NULL, "Depth stencil should not be NULL\n");
1103     if (surface) IDirect3DSurface9_Release(surface);
1104
1105     d3dpp.EnableAutoDepthStencil = FALSE;
1106     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1107     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1108
1109     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &surface);
1110     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1111     ok(surface == NULL, "Depth stencil should be NULL\n");
1112
1113     /* Will a sysmem or scratch survive while locked */
1114     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1115     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1116     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1117     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1118     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1119     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1120     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1121     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1122     IDirect3DSurface9_UnlockRect(surface);
1123     IDirect3DSurface9_Release(surface);
1124
1125     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1126     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1127     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1128     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1129     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1130     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1131     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1132     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1133     IDirect3DSurface9_UnlockRect(surface);
1134     IDirect3DSurface9_Release(surface);
1135
1136     hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
1137     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
1138     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1139     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1140     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1141     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1142     IDirect3DTexture9_Release(texture);
1143
1144     /* A reference held to an implicit surface causes failures as well */
1145     hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1146     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
1147     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1148     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1149     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1150     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1151     IDirect3DSurface9_Release(surface);
1152     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1153     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1154     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1155     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1156
1157     /* Shaders are fine as well */
1158     hr = IDirect3DDevice9_CreateVertexShader(pDevice, simple_vs, &shader);
1159     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
1160     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1161     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1162     IDirect3DVertexShader9_Release(shader);
1163
1164     /* Try setting invalid modes */
1165     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1166     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1167     d3dpp.Windowed         = FALSE;
1168     d3dpp.BackBufferWidth  = 32;
1169     d3dpp.BackBufferHeight = 32;
1170     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1171     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
1172     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1173     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1174
1175     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1176     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1177     d3dpp.Windowed         = FALSE;
1178     d3dpp.BackBufferWidth  = 801;
1179     d3dpp.BackBufferHeight = 600;
1180     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1181     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
1182     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1183     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1184
1185     pDevice = NULL;
1186     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1187
1188     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1189     d3dpp.Windowed         = TRUE;
1190     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1191     d3dpp.BackBufferFormat = d3ddm.Format;
1192     d3dpp.EnableAutoDepthStencil = FALSE;
1193     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1194
1195     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
1196                     D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1197
1198     if(FAILED(hr))
1199     {
1200         skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
1201         goto cleanup;
1202     }
1203
1204     hr = IDirect3DDevice9_TestCooperativeLevel(pDevice);
1205     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1206
1207     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1208     d3dpp.Windowed         = TRUE;
1209     d3dpp.BackBufferWidth  = 400;
1210     d3dpp.BackBufferHeight = 300;
1211     d3dpp.EnableAutoDepthStencil = TRUE;
1212     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1213
1214     hr = IDirect3DDevice9_Reset(pDevice, &d3dpp);
1215     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1216
1217     if (FAILED(hr)) goto cleanup;
1218
1219     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &surface);
1220     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1221     ok(surface != NULL, "Depth stencil should not be NULL\n");
1222     if (surface) IDirect3DSurface9_Release(surface);
1223
1224 cleanup:
1225     HeapFree(GetProcessHeap(), 0, modes);
1226     if (pDevice)
1227     {
1228         UINT refcount = IDirect3DDevice9_Release(pDevice);
1229         ok(!refcount, "Device has %u references left.\n", refcount);
1230     }
1231     if (pD3d) IDirect3D9_Release(pD3d);
1232 }
1233
1234 /* Test adapter display modes */
1235 static void test_display_modes(void)
1236 {
1237     D3DDISPLAYMODE dmode;
1238     IDirect3D9 *pD3d;
1239
1240     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1241     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1242     if(!pD3d) return;
1243
1244 #define TEST_FMT(x,r) do { \
1245     HRESULT res = IDirect3D9_EnumAdapterModes(pD3d, 0, (x), 0, &dmode); \
1246     ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
1247 } while(0)
1248
1249     TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
1250     TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
1251     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1252     /* D3DFMT_R5G6B5 */
1253     TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
1254     TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
1255     TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
1256     TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
1257     TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
1258     TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
1259     TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
1260     TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
1261     TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
1262     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1263     TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
1264     TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
1265
1266     TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
1267     TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
1268
1269     TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
1270     TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
1271     TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
1272
1273     TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
1274     TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
1275     TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
1276     TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
1277     TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
1278     TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
1279
1280     TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
1281     TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
1282     TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
1283     TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
1284     TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
1285     TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
1286     TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
1287     TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
1288     TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
1289     TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
1290
1291     TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
1292     TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
1293     TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
1294     TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
1295     TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
1296     TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
1297     TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
1298     TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
1299     TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
1300     TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
1301
1302     TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
1303     TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
1304     TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
1305     TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
1306     /* Floating point formats */
1307     TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
1308     TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
1309     TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
1310
1311     /* IEEE formats */
1312     TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
1313     TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
1314     TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
1315
1316     TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
1317
1318     TEST_FMT(0, D3DERR_INVALIDCALL);
1319
1320     IDirect3D9_Release(pD3d);
1321 }
1322
1323 static void test_scene(void)
1324 {
1325     HRESULT                      hr;
1326     HWND                         hwnd               = NULL;
1327     IDirect3D9                  *pD3d               = NULL;
1328     IDirect3DDevice9            *pDevice            = NULL;
1329     D3DPRESENT_PARAMETERS        d3dpp;
1330     D3DDISPLAYMODE               d3ddm;
1331     IDirect3DSurface9            *pSurface1 = NULL, *pSurface2 = NULL, *pSurface3 = NULL, *pRenderTarget = NULL;
1332     IDirect3DSurface9            *pBackBuffer = NULL, *pDepthStencil = NULL;
1333     RECT rect = {0, 0, 128, 128};
1334     D3DCAPS9                     caps;
1335
1336     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1337     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1338     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1339     ok(hwnd != NULL, "Failed to create window\n");
1340     if (!pD3d || !hwnd) goto cleanup;
1341
1342     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1343     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1344     d3dpp.Windowed         = TRUE;
1345     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1346     d3dpp.BackBufferWidth  = 800;
1347     d3dpp.BackBufferHeight = 600;
1348     d3dpp.BackBufferFormat = d3ddm.Format;
1349     d3dpp.EnableAutoDepthStencil = TRUE;
1350     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1351
1352     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1353                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1354     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1355     if(!pDevice)
1356     {
1357         skip("Failed to create a d3d device\n");
1358         goto cleanup;
1359     }
1360
1361     /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
1362     memset(&caps, 0, sizeof(caps));
1363     hr = IDirect3DDevice9_GetDeviceCaps(pDevice, &caps);
1364     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
1365     if(FAILED(hr)) goto cleanup;
1366
1367     /* Test an EndScene without beginscene. Should return an error */
1368     hr = IDirect3DDevice9_EndScene(pDevice);
1369     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1370
1371     /* Test a normal BeginScene / EndScene pair, this should work */
1372     hr = IDirect3DDevice9_BeginScene(pDevice);
1373     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1374     if(SUCCEEDED(hr))
1375     {
1376         hr = IDirect3DDevice9_EndScene(pDevice);
1377         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1378     }
1379
1380     /* Test another EndScene without having begun a new scene. Should return an error */
1381     hr = IDirect3DDevice9_EndScene(pDevice);
1382     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1383
1384     /* Two nested BeginScene and EndScene calls */
1385     hr = IDirect3DDevice9_BeginScene(pDevice);
1386     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1387     hr = IDirect3DDevice9_BeginScene(pDevice);
1388     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
1389     hr = IDirect3DDevice9_EndScene(pDevice);
1390     ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1391     hr = IDirect3DDevice9_EndScene(pDevice);
1392     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1393
1394     /* Create some surfaces to test stretchrect between the scenes */
1395     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface1, NULL);
1396     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1397     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface2, NULL);
1398     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1399     hr = IDirect3DDevice9_CreateDepthStencilSurface(pDevice, 800, 600, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface3, NULL);
1400     ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
1401     hr = IDirect3DDevice9_CreateRenderTarget(pDevice, 128, 128, d3ddm.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pRenderTarget, NULL);
1402     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
1403
1404     hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
1405     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1406     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1407     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1408
1409     /* First make sure a simple StretchRect call works */
1410     if(pSurface1 && pSurface2) {
1411         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1412         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1413     }
1414     if(pBackBuffer && pRenderTarget) {
1415         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1416         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1417     }
1418     if(pDepthStencil && pSurface3) {
1419         HRESULT expected;
1420         if(0) /* Disabled for now because it crashes in wine */ {
1421             expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
1422             hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1423             ok( hr == expected, "IDirect3DDevice9_StretchRect returned %08x, expected %08x\n", hr, expected);
1424         }
1425     }
1426
1427     /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a beginScene - Endscene pair
1428      * width normal surfaces, render targets and depth stencil surfaces.
1429      */
1430     hr = IDirect3DDevice9_BeginScene(pDevice);
1431     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1432
1433     if(pSurface1 && pSurface2)
1434     {
1435         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1436         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1437     }
1438     if(pBackBuffer && pRenderTarget)
1439     {
1440         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1441         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1442     }
1443     if(pDepthStencil && pSurface3)
1444     {
1445         /* This is supposed to fail inside a BeginScene - EndScene pair. */
1446         hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1447         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
1448     }
1449
1450     hr = IDirect3DDevice9_EndScene(pDevice);
1451     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1452
1453     /* Does a SetRenderTarget influence BeginScene / EndScene ?
1454      * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
1455      * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
1456      */
1457     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pRenderTarget);
1458     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1459     hr = IDirect3DDevice9_BeginScene(pDevice);
1460     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1461     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pBackBuffer);
1462     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1463     hr = IDirect3DDevice9_EndScene(pDevice);
1464     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1465
1466 cleanup:
1467     if(pRenderTarget) IDirect3DSurface9_Release(pRenderTarget);
1468     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1469     if(pBackBuffer) IDirect3DSurface9_Release(pBackBuffer);
1470     if(pSurface1) IDirect3DSurface9_Release(pSurface1);
1471     if(pSurface2) IDirect3DSurface9_Release(pSurface2);
1472     if(pSurface3) IDirect3DSurface9_Release(pSurface3);
1473     if (pDevice)
1474     {
1475         UINT refcount = IDirect3DDevice9_Release(pDevice);
1476         ok(!refcount, "Device has %u references left.\n", refcount);
1477     }
1478     if (pD3d) IDirect3D9_Release(pD3d);
1479     if(hwnd) DestroyWindow(hwnd);
1480 }
1481
1482 static void test_limits(void)
1483 {
1484     HRESULT                      hr;
1485     HWND                         hwnd               = NULL;
1486     IDirect3D9                  *pD3d               = NULL;
1487     IDirect3DDevice9            *pDevice            = NULL;
1488     D3DPRESENT_PARAMETERS        d3dpp;
1489     D3DDISPLAYMODE               d3ddm;
1490     IDirect3DTexture9           *pTexture           = NULL;
1491     int i;
1492
1493     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1494     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1495     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1496     ok(hwnd != NULL, "Failed to create window\n");
1497     if (!pD3d || !hwnd) goto cleanup;
1498
1499     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1500     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1501     d3dpp.Windowed         = TRUE;
1502     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1503     d3dpp.BackBufferWidth  = 800;
1504     d3dpp.BackBufferHeight = 600;
1505     d3dpp.BackBufferFormat = d3ddm.Format;
1506     d3dpp.EnableAutoDepthStencil = TRUE;
1507     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1508
1509     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1510                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1511     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1512     if(!pDevice)
1513     {
1514         skip("Failed to create a d3d device\n");
1515         goto cleanup;
1516     }
1517
1518     hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL);
1519     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
1520     if(!pTexture) goto cleanup;
1521
1522     /* There are 16 pixel samplers. We should be able to access all of them */
1523     for(i = 0; i < 16; i++) {
1524         hr = IDirect3DDevice9_SetTexture(pDevice, i, (IDirect3DBaseTexture9 *) pTexture);
1525         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1526         hr = IDirect3DDevice9_SetTexture(pDevice, i, NULL);
1527         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1528         hr = IDirect3DDevice9_SetSamplerState(pDevice, i, D3DSAMP_SRGBTEXTURE, TRUE);
1529         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
1530     }
1531
1532     /* Now test all 8 textures stage states */
1533     for(i = 0; i < 8; i++) {
1534         hr = IDirect3DDevice9_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1535         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
1536     }
1537
1538     /* Investigations show that accessing higher samplers / textures stage states does not return an error either. Writing
1539      * to too high samplers(approximately sampler 40) causes memory corruption in windows, so there is no bounds checking
1540      * but how do I test that?
1541      */
1542 cleanup:
1543     if(pTexture) IDirect3DTexture9_Release(pTexture);
1544     if (pDevice)
1545     {
1546         UINT refcount = IDirect3D9_Release(pDevice);
1547         ok(!refcount, "Device has %u references left.\n", refcount);
1548     }
1549     if (pD3d) IDirect3D9_Release(pD3d);
1550     if(hwnd) DestroyWindow(hwnd);
1551 }
1552
1553 static void test_depthstenciltest(void)
1554 {
1555     HRESULT                      hr;
1556     HWND                         hwnd               = NULL;
1557     IDirect3D9                  *pD3d               = NULL;
1558     IDirect3DDevice9            *pDevice            = NULL;
1559     D3DPRESENT_PARAMETERS        d3dpp;
1560     D3DDISPLAYMODE               d3ddm;
1561     IDirect3DSurface9           *pDepthStencil           = NULL;
1562     IDirect3DSurface9           *pDepthStencil2          = NULL;
1563     D3DZBUFFERTYPE               state;
1564
1565     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1566     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1567     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1568     ok(hwnd != NULL, "Failed to create window\n");
1569     if (!pD3d || !hwnd) goto cleanup;
1570
1571     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1572     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1573     d3dpp.Windowed         = TRUE;
1574     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1575     d3dpp.BackBufferWidth  = 800;
1576     d3dpp.BackBufferHeight = 600;
1577     d3dpp.BackBufferFormat = d3ddm.Format;
1578     d3dpp.EnableAutoDepthStencil = TRUE;
1579     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1580
1581     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1582                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1583     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1584     if(!pDevice)
1585     {
1586         skip("Failed to create a d3d device\n");
1587         goto cleanup;
1588     }
1589
1590     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1591     ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1592
1593     /* Try to clear */
1594     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1595     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1596
1597     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
1598     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1599
1600     /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
1601     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
1602     ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1603     if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
1604
1605     /* This left the render states untouched! */
1606     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1607     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1608     ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1609     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
1610     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1611     ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
1612     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
1613     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1614     ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
1615     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
1616     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1617     ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
1618
1619     /* This is supposed to fail now */
1620     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1621     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1622
1623     hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
1624     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
1625
1626     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
1627     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1628
1629     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1630     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1631     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1632
1633     /* Now it works again */
1634     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1635     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1636
1637     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1638     if(pDevice) IDirect3D9_Release(pDevice);
1639
1640     /* Now see if autodepthstencil disable is honored. First, without a format set */
1641     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1642     d3dpp.Windowed         = TRUE;
1643     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1644     d3dpp.BackBufferWidth  = 800;
1645     d3dpp.BackBufferHeight = 600;
1646     d3dpp.BackBufferFormat = d3ddm.Format;
1647     d3dpp.EnableAutoDepthStencil = FALSE;
1648     d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1649
1650     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1651                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1652     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1653     if(!pDevice)
1654     {
1655         skip("Failed to create a d3d device\n");
1656         goto cleanup;
1657     }
1658
1659     pDepthStencil = NULL;
1660     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1661     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1662     if(pDepthStencil) {
1663         IDirect3DSurface9_Release(pDepthStencil);
1664         pDepthStencil = NULL;
1665     }
1666
1667     /* Check the depth test state */
1668     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1669     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1670     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1671
1672     if(pDevice) IDirect3D9_Release(pDevice);
1673
1674     /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
1675     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1676     d3dpp.Windowed         = TRUE;
1677     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1678     d3dpp.BackBufferWidth  = 800;
1679     d3dpp.BackBufferHeight = 600;
1680     d3dpp.BackBufferFormat = d3ddm.Format;
1681     d3dpp.EnableAutoDepthStencil = FALSE;
1682     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1683
1684     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1685                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1686     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1687     if(!pDevice)
1688     {
1689         skip("Failed to create a d3d device\n");
1690         goto cleanup;
1691     }
1692
1693     pDepthStencil = NULL;
1694     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1695     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1696     if(pDepthStencil) {
1697         IDirect3DSurface9_Release(pDepthStencil);
1698         pDepthStencil = NULL;
1699     }
1700
1701     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1702     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1703     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1704
1705 cleanup:
1706     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1707     if (pDevice)
1708     {
1709         UINT refcount = IDirect3D9_Release(pDevice);
1710         ok(!refcount, "Device has %u references left.\n", refcount);
1711     }
1712     if (pD3d) IDirect3D9_Release(pD3d);
1713     if(hwnd) DestroyWindow(hwnd);
1714 }
1715
1716 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
1717 static void test_draw_indexed(void)
1718 {
1719     static const struct {
1720         float position[3];
1721         DWORD color;
1722     } quad[] = {
1723         {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
1724         {{-1.0f,  1.0f, 0.0f}, 0xffff0000},
1725         {{ 1.0f,  1.0f, 0.0f}, 0xffff0000},
1726         {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
1727     };
1728     WORD indices[] = {0, 1, 2, 3, 0, 2};
1729
1730     static const D3DVERTEXELEMENT9 decl_elements[] = {
1731         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1732         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1733         D3DDECL_END()
1734     };
1735
1736     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1737     IDirect3DVertexBuffer9 *vertex_buffer = NULL;
1738     IDirect3DIndexBuffer9 *index_buffer = NULL;
1739     D3DPRESENT_PARAMETERS present_parameters;
1740     IDirect3DDevice9 *device = NULL;
1741     IDirect3D9 *d3d9;
1742     HRESULT hr;
1743     HWND hwnd;
1744     void *ptr;
1745
1746     hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
1747             0, 0, 0, 10, 10, 0, 0, 0, 0);
1748     if (!hwnd)
1749     {
1750         skip("Failed to create window\n");
1751         return;
1752     }
1753
1754     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
1755     if (!d3d9)
1756     {
1757         skip("Failed to create IDirect3D9 object\n");
1758         goto cleanup;
1759     }
1760
1761     ZeroMemory(&present_parameters, sizeof(present_parameters));
1762     present_parameters.Windowed = TRUE;
1763     present_parameters.hDeviceWindow = hwnd;
1764     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1765
1766     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1767             NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1768     if (FAILED(hr) || !device)
1769     {
1770         skip("Failed to create device\n");
1771         goto cleanup;
1772     }
1773
1774     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1775     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1776     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1777     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1778
1779     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
1780     ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
1781     hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1782     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1783     memcpy(ptr, quad, sizeof(quad));
1784     hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
1785     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1786     hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
1787     ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
1788
1789     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
1790     ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
1791     hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1792     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1793     memcpy(ptr, indices, sizeof(indices));
1794     hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
1795     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1796     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1797     ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
1798     hr = IDirect3DDevice9_BeginScene(device);
1799     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1800
1801     /* NULL index buffer. Should fail */
1802     hr = IDirect3DDevice9_SetIndices(device, NULL);
1803     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1804     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1805             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1806     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1807             hr, D3DERR_INVALIDCALL);
1808
1809     /* Valid index buffer, NULL vertex declaration. Should fail */
1810     hr = IDirect3DDevice9_SetIndices(device, index_buffer);
1811     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1812     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1813             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1814     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1815             hr, D3DERR_INVALIDCALL);
1816
1817     /* Valid index buffer and vertex declaration. Should succeed */
1818     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1819     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1820     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1821             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1822     ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
1823
1824     hr = IDirect3DDevice9_EndScene(device);
1825     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1826
1827     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1828     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1829
1830     IDirect3DVertexBuffer9_Release(vertex_buffer);
1831     IDirect3DIndexBuffer9_Release(index_buffer);
1832     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1833
1834 cleanup:
1835     if (device)
1836     {
1837         UINT refcount = IDirect3DDevice9_Release(device);
1838         ok(!refcount, "Device has %u references left.\n", refcount);
1839     }
1840     if (d3d9) IDirect3D9_Release(d3d9);
1841     if (hwnd) DestroyWindow(hwnd);
1842 }
1843
1844 static void test_null_stream(void)
1845 {
1846     IDirect3DVertexBuffer9 *buffer = NULL;
1847     D3DPRESENT_PARAMETERS present_parameters;
1848     IDirect3DDevice9 *device = NULL;
1849     IDirect3D9 *d3d9;
1850     HWND hwnd;
1851     HRESULT hr;
1852     IDirect3DVertexShader9 *shader = NULL;
1853     IDirect3DVertexDeclaration9 *decl = NULL;
1854     DWORD shader_code[] = {
1855         0xfffe0101,                             /* vs_1_1           */
1856         0x0000001f, 0x80000000, 0x900f0000,     /* dcl_position v0  */
1857         0x00000001, 0xc00f0000, 0x90e40000,     /* mov oPos, v0     */
1858         0x0000ffff                              /* end              */
1859     };
1860     static const D3DVERTEXELEMENT9 decl_elements[] = {
1861         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1862         {1, 0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1863         D3DDECL_END()
1864     };
1865
1866     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
1867     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
1868     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1869     ok(hwnd != NULL, "Failed to create window\n");
1870     if (!d3d9 || !hwnd) goto cleanup;
1871
1872     ZeroMemory(&present_parameters, sizeof(present_parameters));
1873     present_parameters.Windowed = TRUE;
1874     present_parameters.hDeviceWindow = hwnd;
1875     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1876
1877     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1878                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
1879     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1880     if(!device)
1881     {
1882         skip("Failed to create a d3d device\n");
1883         goto cleanup;
1884     }
1885
1886     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
1887     if(FAILED(hr)) {
1888         skip("No vertex shader support\n");
1889         goto cleanup;
1890     }
1891     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
1892     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
1893     if (FAILED(hr)) {
1894         skip("Vertex declaration handling not possible.\n");
1895         goto cleanup;
1896     }
1897     hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
1898     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
1899     if (FAILED(hr)) {
1900         skip("Vertex buffer handling not possible.\n");
1901         goto cleanup;
1902     }
1903
1904     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
1905     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
1906     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
1907     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
1908     hr = IDirect3DDevice9_SetVertexShader(device, shader);
1909     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
1910     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
1911     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
1912
1913     hr = IDirect3DDevice9_BeginScene(device);
1914     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (0x%08x)\n", hr);
1915     if(SUCCEEDED(hr)) {
1916         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
1917         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitive failed (0x%08x)\n", hr);
1918
1919         hr = IDirect3DDevice9_EndScene(device);
1920         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed (0x%08x)\n", hr);
1921     }
1922
1923     IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1924     IDirect3DDevice9_SetVertexShader(device, NULL);
1925     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1926
1927 cleanup:
1928     if (buffer) IDirect3DVertexBuffer9_Release(buffer);
1929     if(decl) IDirect3DVertexDeclaration9_Release(decl);
1930     if(shader) IDirect3DVertexShader9_Release(shader);
1931     if (device)
1932     {
1933         UINT refcount = IDirect3DDevice9_Release(device);
1934         ok(!refcount, "Device has %u references left.\n", refcount);
1935     }
1936     if(d3d9) IDirect3D9_Release(d3d9);
1937 }
1938
1939 static void test_lights(void)
1940 {
1941     D3DPRESENT_PARAMETERS present_parameters;
1942     IDirect3DDevice9 *device = NULL;
1943     IDirect3D9 *d3d9;
1944     HWND hwnd;
1945     HRESULT hr;
1946     unsigned int i;
1947     BOOL enabled;
1948     D3DCAPS9 caps;
1949
1950     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
1951     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
1952     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1953     ok(hwnd != NULL, "Failed to create window\n");
1954     if (!d3d9 || !hwnd) goto cleanup;
1955
1956     ZeroMemory(&present_parameters, sizeof(present_parameters));
1957     present_parameters.Windowed = TRUE;
1958     present_parameters.hDeviceWindow = hwnd;
1959     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1960
1961     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
1962                                   D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &present_parameters, &device );
1963     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1964        "IDirect3D9_CreateDevice failed with %08x\n", hr);
1965     if(!device)
1966     {
1967         skip("Failed to create a d3d device\n");
1968         goto cleanup;
1969     }
1970
1971     memset(&caps, 0, sizeof(caps));
1972     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1973     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
1974
1975     for(i = 1; i <= caps.MaxActiveLights; i++) {
1976         hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
1977         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1978         hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
1979         ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
1980         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1981     }
1982
1983     /* TODO: Test the rendering results in this situation */
1984     hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
1985     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
1986     hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
1987     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1988     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1989     hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
1990     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1991
1992     for(i = 1; i <= caps.MaxActiveLights; i++) {
1993         hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
1994         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
1995     }
1996
1997 cleanup:
1998     if (device)
1999     {
2000         UINT refcount = IDirect3DDevice9_Release(device);
2001         ok(!refcount, "Device has %u references left.\n", refcount);
2002     }
2003     if(d3d9) IDirect3D9_Release(d3d9);
2004 }
2005
2006 static void test_set_stream_source(void)
2007 {
2008     D3DPRESENT_PARAMETERS present_parameters;
2009     IDirect3DDevice9 *device = NULL;
2010     IDirect3D9 *d3d9;
2011     HWND hwnd;
2012     HRESULT hr;
2013     IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
2014
2015     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2016     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2017     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2018     ok(hwnd != NULL, "Failed to create window\n");
2019     if (!d3d9 || !hwnd) goto cleanup;
2020
2021     ZeroMemory(&present_parameters, sizeof(present_parameters));
2022     present_parameters.Windowed = TRUE;
2023     present_parameters.hDeviceWindow = hwnd;
2024     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2025
2026     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2027                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2028     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2029        "IDirect3D9_CreateDevice failed with %08x\n", hr);
2030     if(!device)
2031     {
2032         hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd,
2033                                       D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2034         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2035            "IDirect3D9_CreateDevice failed with %08x\n", hr);
2036         if(!device)
2037         {
2038             skip("Failed to create a d3d device\n");
2039             goto cleanup;
2040         }
2041     }
2042
2043     hr = IDirect3DDevice9_CreateVertexBuffer( device, 512, 0, 0, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
2044     ok(hr == D3D_OK, "Failed to create a vertex buffer, hr = %08x\n", hr);
2045     if (SUCCEEDED(hr)) {
2046         /* Some cards(Geforce 7400 at least) accept non-aligned offsets, others(radeon 9000 verified) reject it,
2047          * so accept both results. Wine currently rejects this to be able to optimize the vbo conversion, but writes
2048          * a WARN
2049          */
2050         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32);
2051         ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2052         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32);
2053         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2054         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 2, 32);
2055         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2056         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 3, 32);
2057         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2058         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 4, 32);
2059         ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2060     }
2061     /* Try to set the NULL buffer with an offset and stride 0 */
2062     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2063     ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2064     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2065     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2066     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2067     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2068     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2069     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2070     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2071     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2072
2073     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2074     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2075
2076 cleanup:
2077     if (pVertexBuffer) IDirect3DVertexBuffer9_Release(pVertexBuffer);
2078     if (device)
2079     {
2080         UINT refcount = IDirect3DDevice9_Release(device);
2081         ok(!refcount, "Device has %u references left.\n", refcount);
2082     }
2083     if(d3d9) IDirect3D9_Release(d3d9);
2084 }
2085
2086 struct formats {
2087     D3DFORMAT DisplayFormat;
2088     D3DFORMAT BackBufferFormat;
2089     BOOL shouldPass;
2090 };
2091
2092 static const struct formats r5g6b5_format_list[] =
2093 {
2094     { D3DFMT_R5G6B5, D3DFMT_R5G6B5, TRUE },
2095     { D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, FALSE },
2096     { D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, FALSE },
2097     { D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, FALSE },
2098     { D3DFMT_R5G6B5, D3DFMT_A8R8G8B8, FALSE },
2099     { 0, 0, 0}
2100 };
2101
2102 static const struct formats x1r5g5b5_format_list[] =
2103 {
2104     { D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, FALSE },
2105     { D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, TRUE },
2106     { D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE },
2107     { D3DFMT_X1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2108     { D3DFMT_X1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2109
2110     /* A1R5G5B5 should not be usable as a display format, it is backbuffer-only */
2111     { D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, FALSE },
2112     { D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, FALSE },
2113     { D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE },
2114     { D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2115     { D3DFMT_A1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2116     { 0, 0, 0}
2117 };
2118
2119 static const struct formats x8r8g8b8_format_list[] =
2120 {
2121     { D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, FALSE },
2122     { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2123     { D3DFMT_X8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2124     { D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, TRUE },
2125     { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE },
2126
2127     /* A1R8G8B8 should not be usable as a display format, it is backbuffer-only */
2128     { D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, FALSE },
2129     { D3DFMT_A8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2130     { D3DFMT_A8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2131     { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, FALSE },
2132     { D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE },
2133     { 0, 0, 0}
2134 };
2135
2136 static void test_display_formats(void)
2137 {
2138     /* Direct3D9 offers 4 display formats R5G6B5, X1R5G5B5, X8R8G8B8 and A2R10G10B10.
2139      * Next to these there are 6 different backbuffer formats. Only a fixed number of
2140      * combinations are possible in FULLSCREEN mode. In windowed mode more combinations are
2141      * allowed due to depth conversion and this is likely driver dependent.
2142      * This test checks which combinations are possible in fullscreen mode and this should not be driver dependent.
2143      * TODO: handle A2R10G10B10 but what hardware supports it? Parhelia? It is very rare. */
2144
2145     UINT Adapter = D3DADAPTER_DEFAULT;
2146     D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
2147     int i, nmodes;
2148     HRESULT hr;
2149
2150     IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2151     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2152     if(!d3d9) return;
2153
2154     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_R5G6B5);
2155     if(!nmodes) {
2156         skip("Display format R5G6B5 not supported, skipping\n");
2157     } else {
2158         trace("Testing display format R5G6B5\n");
2159         for(i=0; r5g6b5_format_list[i].DisplayFormat != 0; i++)
2160         {
2161             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, FALSE);
2162
2163             if(r5g6b5_format_list[i].shouldPass)
2164                 ok(hr == D3D_OK ||
2165                    broken(hr == D3DERR_NOTAVAILABLE),
2166                    "format %d %d didn't pass with hr=%#08x\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, hr);
2167             else
2168                 ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat);
2169         }
2170     }
2171
2172     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X1R5G5B5);
2173     if(!nmodes) {
2174         skip("Display format X1R5G5B5 not supported, skipping\n");
2175     } else {
2176         trace("Testing display format X1R5G5B5\n");
2177         for(i=0; x1r5g5b5_format_list[i].DisplayFormat != 0; i++)
2178         {
2179             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, FALSE);
2180
2181             if(x1r5g5b5_format_list[i].shouldPass)
2182                 ok(hr == D3D_OK, "format %d %d didn't pass with hr=%#08x\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, hr);
2183             else
2184                 ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat);
2185         }
2186     }
2187
2188     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
2189     if(!nmodes) {
2190         skip("Display format X8R8G8B8 not supported, skipping\n");
2191     } else {
2192         trace("Testing display format X8R8G8B8\n");
2193         for(i=0; x8r8g8b8_format_list[i].DisplayFormat != 0; i++)
2194         {
2195             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, FALSE);
2196
2197             if(x8r8g8b8_format_list[i].shouldPass)
2198                 ok(hr == D3D_OK ||
2199                    broken(hr == D3DERR_NOTAVAILABLE),
2200                    "format %d %d didn't pass with hr=%#08x\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr);
2201             else
2202                 ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat);
2203         }
2204     }
2205
2206     if(d3d9) IDirect3D9_Release(d3d9);
2207 }
2208
2209 static void test_scissor_size(void)
2210 {
2211     IDirect3D9 *d3d9_ptr = 0;
2212     unsigned int i;
2213     static struct {
2214         int winx; int winy; int backx; int backy; BOOL window;
2215     } scts[] = { /* scissor tests */
2216         {800, 600, 640, 480, TRUE},
2217         {800, 600, 640, 480, FALSE},
2218         {640, 480, 800, 600, TRUE},
2219         {640, 480, 800, 600, FALSE},
2220     };
2221
2222     d3d9_ptr = pDirect3DCreate9(D3D_SDK_VERSION);
2223     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
2224     if (!d3d9_ptr){
2225         skip("Failed to create IDirect3D9 object\n");
2226         return;
2227     }
2228
2229     for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
2230         IDirect3DDevice9 *device_ptr = 0;
2231         D3DPRESENT_PARAMETERS present_parameters;
2232         HRESULT hr;
2233         HWND hwnd = 0;
2234         RECT scissorrect;
2235
2236         hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
2237                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
2238
2239         if (!scts[i].window)
2240         {
2241             scts[i].backx = screen_width;
2242             scts[i].backy = screen_height;
2243         }
2244
2245         ZeroMemory(&present_parameters, sizeof(present_parameters));
2246         present_parameters.Windowed = scts[i].window;
2247         present_parameters.hDeviceWindow = hwnd;
2248         present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2249         present_parameters.BackBufferWidth = scts[i].backx;
2250         present_parameters.BackBufferHeight = scts[i].backy;
2251         present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
2252         present_parameters.EnableAutoDepthStencil = TRUE;
2253         present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2254
2255         hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2256         if(FAILED(hr)) {
2257             present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
2258             hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2259             if(FAILED(hr)) {
2260                 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2261             }
2262         }
2263         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
2264
2265         if (!device_ptr)
2266         {
2267             DestroyWindow(hwnd);
2268             skip("Creating the device failed\n");
2269             goto err_out;
2270         }
2271
2272         /* Check for the default scissor rect size */
2273         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2274         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2275         ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy && scissorrect.top == 0 && scissorrect.left == 0, "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom, scts[i].backx, scts[i].backy);
2276
2277         /* check the scissorrect values after a reset */
2278         present_parameters.BackBufferWidth = screen_width;
2279         present_parameters.BackBufferHeight = screen_height;
2280         hr = IDirect3DDevice9_Reset(device_ptr, &present_parameters);
2281         ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2282         hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
2283         ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2284
2285         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2286         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2287         ok(scissorrect.right == screen_width && scissorrect.bottom == screen_height && scissorrect.top == 0 && scissorrect.left == 0, "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom, screen_width, screen_height);
2288
2289         if(device_ptr) {
2290             ULONG ref;
2291
2292             ref = IDirect3DDevice9_Release(device_ptr);
2293             DestroyWindow(hwnd);
2294             ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
2295         }
2296     }
2297
2298 err_out:
2299     if(d3d9_ptr) IDirect3D9_Release(d3d9_ptr);
2300     return;
2301 }
2302
2303 static void test_multi_device(void)
2304 {
2305     IDirect3DDevice9 *device1 = NULL, *device2 = NULL;
2306     D3DPRESENT_PARAMETERS present_parameters;
2307     HWND hwnd1 = NULL, hwnd2 = NULL;
2308     IDirect3D9 *d3d9;
2309     ULONG refcount;
2310     HRESULT hr;
2311
2312     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2313     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2314     if (!d3d9) goto fail;
2315
2316     hwnd1 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2317     ok(hwnd1 != NULL, "Failed to create a window.\n");
2318     if (!hwnd1) goto fail;
2319
2320     memset(&present_parameters, 0, sizeof(present_parameters));
2321     present_parameters.Windowed = TRUE;
2322     present_parameters.hDeviceWindow = hwnd1;
2323     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2324
2325     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd1,
2326             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device1);
2327     IDirect3D9_Release(d3d9);
2328     d3d9 = NULL;
2329     if (FAILED(hr)) {
2330         skip("Failed to create a device\n");
2331         goto fail;
2332     }
2333
2334     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2335     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2336     if (!d3d9) goto fail;
2337
2338     hwnd2 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2339     ok(hwnd2 != NULL, "Failed to create a window.\n");
2340     if (!hwnd2) goto fail;
2341
2342     memset(&present_parameters, 0, sizeof(present_parameters));
2343     present_parameters.Windowed = TRUE;
2344     present_parameters.hDeviceWindow = hwnd2;
2345     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2346
2347     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd2,
2348             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device2);
2349     ok(SUCCEEDED(hr), "Failed to create a device, hr %#x\n", hr);
2350     IDirect3D9_Release(d3d9);
2351     d3d9 = NULL;
2352     if (FAILED(hr)) goto fail;
2353
2354 fail:
2355     if (d3d9) IDirect3D9_Release(d3d9);
2356     if (device1)
2357     {
2358         refcount = IDirect3DDevice9_Release(device1);
2359         ok(!refcount, "Device has %u references left.\n", refcount);
2360     }
2361     if (device2)
2362     {
2363         refcount = IDirect3DDevice9_Release(device2);
2364         ok(!refcount, "Device has %u references left.\n", refcount);
2365     }
2366     if (hwnd1) DestroyWindow(hwnd1);
2367     if (hwnd2) DestroyWindow(hwnd2);
2368 }
2369
2370 static HWND filter_messages;
2371
2372 enum message_window
2373 {
2374     DEVICE_WINDOW,
2375     FOCUS_WINDOW,
2376 };
2377
2378 struct message
2379 {
2380     UINT message;
2381     enum message_window window;
2382 };
2383
2384 static const struct message *expect_messages;
2385 static HWND device_window, focus_window;
2386
2387 struct wndproc_thread_param
2388 {
2389     HWND dummy_window;
2390     HANDLE window_created;
2391     HANDLE test_finished;
2392     BOOL running_in_foreground;
2393 };
2394
2395 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2396 {
2397     if (filter_messages && filter_messages == hwnd)
2398     {
2399         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2400             todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2401     }
2402
2403     if (expect_messages)
2404     {
2405         HWND w;
2406
2407         switch (expect_messages->window)
2408         {
2409             case DEVICE_WINDOW:
2410                 w = device_window;
2411                 break;
2412
2413             case FOCUS_WINDOW:
2414                 w = focus_window;
2415                 break;
2416
2417             default:
2418                 w = NULL;
2419                 break;
2420         };
2421
2422         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2423     }
2424
2425     return DefWindowProcA(hwnd, message, wparam, lparam);
2426 }
2427
2428 static DWORD WINAPI wndproc_thread(void *param)
2429 {
2430     struct wndproc_thread_param *p = param;
2431     DWORD res;
2432     BOOL ret;
2433
2434     p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2435             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2436     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2437
2438     ret = SetEvent(p->window_created);
2439     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2440
2441     for (;;)
2442     {
2443         MSG msg;
2444
2445         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2446         res = WaitForSingleObject(p->test_finished, 100);
2447         if (res == WAIT_OBJECT_0) break;
2448         if (res != WAIT_TIMEOUT)
2449         {
2450             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2451             break;
2452         }
2453     }
2454
2455     DestroyWindow(p->dummy_window);
2456
2457     return 0;
2458 }
2459
2460 static void test_wndproc(void)
2461 {
2462     struct wndproc_thread_param thread_params;
2463     IDirect3DDevice9 *device;
2464     WNDCLASSA wc = {0};
2465     IDirect3D9 *d3d9;
2466     HANDLE thread;
2467     LONG_PTR proc;
2468     ULONG ref;
2469     DWORD res, tid;
2470     HWND tmp;
2471
2472     static const struct message messages[] =
2473     {
2474         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2475         {WM_ACTIVATE,           FOCUS_WINDOW},
2476         {WM_SETFOCUS,           FOCUS_WINDOW},
2477         {0,                     0},
2478     };
2479
2480     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2481     {
2482         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2483         return;
2484     }
2485
2486     wc.lpfnWndProc = test_proc;
2487     wc.lpszClassName = "d3d9_test_wndproc_wc";
2488     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2489
2490     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2491     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2492     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2493     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2494
2495     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2496             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2497     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2498             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2499     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2500     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2501
2502     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2503     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2504
2505     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2506     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2507             (LONG_PTR)test_proc, proc);
2508     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2509     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2510             (LONG_PTR)test_proc, proc);
2511
2512     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2513             device_window, focus_window, thread_params.dummy_window);
2514
2515     tmp = GetFocus();
2516     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2517     if (thread_params.running_in_foreground)
2518     {
2519         tmp = GetForegroundWindow();
2520         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2521                 thread_params.dummy_window, tmp);
2522     }
2523     else
2524         skip("Not running in foreground, skip foreground window test\n");
2525
2526     flush_events();
2527
2528     expect_messages = messages;
2529
2530     device = create_device(d3d9, device_window, focus_window, FALSE);
2531     if (!device)
2532     {
2533         skip("Failed to create a D3D device, skipping tests.\n");
2534         goto done;
2535     }
2536
2537     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2538             expect_messages->message, expect_messages->window);
2539     expect_messages = NULL;
2540
2541     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2542     {
2543         tmp = GetFocus();
2544         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2545         tmp = GetForegroundWindow();
2546         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2547     }
2548     SetForegroundWindow(focus_window);
2549     flush_events();
2550
2551     filter_messages = focus_window;
2552
2553     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2554     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2555             (LONG_PTR)test_proc, proc);
2556
2557     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2558     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2559             (LONG_PTR)test_proc, proc);
2560
2561     ref = IDirect3DDevice9_Release(device);
2562     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2563
2564     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2565     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2566             (LONG_PTR)test_proc, proc);
2567
2568     device = create_device(d3d9, focus_window, focus_window, FALSE);
2569     if (!device)
2570     {
2571         skip("Failed to create a D3D device, skipping tests.\n");
2572         goto done;
2573     }
2574
2575     ref = IDirect3DDevice9_Release(device);
2576     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2577
2578     device = create_device(d3d9, device_window, focus_window, FALSE);
2579     if (!device)
2580     {
2581         skip("Failed to create a D3D device, skipping tests.\n");
2582         goto done;
2583     }
2584
2585     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2586     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2587             (LONG_PTR)test_proc, proc);
2588
2589     ref = IDirect3DDevice9_Release(device);
2590     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2591
2592     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2593     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2594             (LONG_PTR)DefWindowProcA, proc);
2595
2596 done:
2597     filter_messages = NULL;
2598     IDirect3D9_Release(d3d9);
2599
2600     SetEvent(thread_params.test_finished);
2601     WaitForSingleObject(thread, INFINITE);
2602     CloseHandle(thread_params.test_finished);
2603     CloseHandle(thread_params.window_created);
2604     CloseHandle(thread);
2605
2606     DestroyWindow(device_window);
2607     DestroyWindow(focus_window);
2608     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2609 }
2610
2611 static void test_wndproc_windowed(void)
2612 {
2613     struct wndproc_thread_param thread_params;
2614     IDirect3DDevice9 *device;
2615     WNDCLASSA wc = {0};
2616     IDirect3D9 *d3d9;
2617     HANDLE thread;
2618     LONG_PTR proc;
2619     HRESULT hr;
2620     ULONG ref;
2621     DWORD res, tid;
2622     HWND tmp;
2623
2624     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2625     {
2626         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2627         return;
2628     }
2629
2630     wc.lpfnWndProc = test_proc;
2631     wc.lpszClassName = "d3d9_test_wndproc_wc";
2632     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2633
2634     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2635     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2636     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2637     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2638
2639     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2640             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2641     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2642             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2643     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2644     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2645
2646     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2647     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2648
2649     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2650     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2651             (LONG_PTR)test_proc, proc);
2652     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2653     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2654             (LONG_PTR)test_proc, proc);
2655
2656     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2657             device_window, focus_window, thread_params.dummy_window);
2658
2659     tmp = GetFocus();
2660     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2661     if (thread_params.running_in_foreground)
2662     {
2663         tmp = GetForegroundWindow();
2664         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2665                 thread_params.dummy_window, tmp);
2666     }
2667     else
2668         skip("Not running in foreground, skip foreground window test\n");
2669
2670     filter_messages = focus_window;
2671
2672     device = create_device(d3d9, device_window, focus_window, TRUE);
2673     if (!device)
2674     {
2675         skip("Failed to create a D3D device, skipping tests.\n");
2676         goto done;
2677     }
2678
2679     tmp = GetFocus();
2680     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2681     tmp = GetForegroundWindow();
2682     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2683             thread_params.dummy_window, tmp);
2684
2685     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2686     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2687             (LONG_PTR)test_proc, proc);
2688
2689     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2690     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2691             (LONG_PTR)test_proc, proc);
2692
2693     filter_messages = NULL;
2694
2695     hr = reset_device(device, device_window, FALSE);
2696     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2697
2698     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2699     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2700             (LONG_PTR)test_proc, proc);
2701
2702     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2703     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2704             (LONG_PTR)test_proc, proc);
2705
2706     hr = reset_device(device, device_window, TRUE);
2707     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2708
2709     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2710     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2711             (LONG_PTR)test_proc, proc);
2712
2713     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2714     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2715             (LONG_PTR)test_proc, proc);
2716
2717     filter_messages = focus_window;
2718
2719     ref = IDirect3DDevice9_Release(device);
2720     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2721
2722     filter_messages = device_window;
2723
2724     device = create_device(d3d9, focus_window, focus_window, TRUE);
2725     if (!device)
2726     {
2727         skip("Failed to create a D3D device, skipping tests.\n");
2728         goto done;
2729     }
2730
2731     filter_messages = NULL;
2732
2733     hr = reset_device(device, focus_window, FALSE);
2734     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2735
2736     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2737     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2738             (LONG_PTR)test_proc, proc);
2739
2740     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2741     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2742             (LONG_PTR)test_proc, proc);
2743
2744     hr = reset_device(device, focus_window, TRUE);
2745     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2746
2747     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2748     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2749             (LONG_PTR)test_proc, proc);
2750
2751     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2752     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2753             (LONG_PTR)test_proc, proc);
2754
2755     filter_messages = device_window;
2756
2757     ref = IDirect3DDevice9_Release(device);
2758     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2759
2760     device = create_device(d3d9, device_window, focus_window, TRUE);
2761     if (!device)
2762     {
2763         skip("Failed to create a D3D device, skipping tests.\n");
2764         goto done;
2765     }
2766
2767     filter_messages = NULL;
2768
2769     hr = reset_device(device, device_window, FALSE);
2770     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2771
2772     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2773     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2774             (LONG_PTR)test_proc, proc);
2775
2776     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2777     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2778             (LONG_PTR)test_proc, proc);
2779
2780     hr = reset_device(device, device_window, TRUE);
2781     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2782
2783     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2784     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2785             (LONG_PTR)test_proc, proc);
2786
2787     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2788     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2789             (LONG_PTR)test_proc, proc);
2790
2791     filter_messages = device_window;
2792
2793     ref = IDirect3DDevice9_Release(device);
2794     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2795
2796 done:
2797     filter_messages = NULL;
2798     IDirect3D9_Release(d3d9);
2799
2800     SetEvent(thread_params.test_finished);
2801     WaitForSingleObject(thread, INFINITE);
2802     CloseHandle(thread_params.test_finished);
2803     CloseHandle(thread_params.window_created);
2804     CloseHandle(thread);
2805
2806     DestroyWindow(device_window);
2807     DestroyWindow(focus_window);
2808     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2809 }
2810
2811 static inline void set_fpu_cw(WORD cw)
2812 {
2813 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2814     __asm__ volatile ("fnclex");
2815     __asm__ volatile ("fldcw %0" : : "m" (cw));
2816 #endif
2817 }
2818
2819 static inline WORD get_fpu_cw(void)
2820 {
2821     WORD cw = 0;
2822 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2823     __asm__ volatile ("fnstcw %0" : "=m" (cw));
2824 #endif
2825     return cw;
2826 }
2827
2828 static void test_fpu_setup(void)
2829 {
2830 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2831     D3DPRESENT_PARAMETERS present_parameters;
2832     IDirect3DDevice9 *device;
2833     HWND window = NULL;
2834     IDirect3D9 *d3d9;
2835     HRESULT hr;
2836     WORD cw;
2837
2838     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2839     ok(!!d3d9, "Failed to create a d3d9 object.\n");
2840     if (!d3d9) return;
2841
2842     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2843     ok(!!window, "Failed to create a window.\n");
2844     if (!window) goto done;
2845
2846     memset(&present_parameters, 0, sizeof(present_parameters));
2847     present_parameters.Windowed = TRUE;
2848     present_parameters.hDeviceWindow = window;
2849     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2850
2851     set_fpu_cw(0xf60);
2852     cw = get_fpu_cw();
2853     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2854
2855     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2856             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
2857     if (FAILED(hr))
2858     {
2859         skip("Failed to create a device, hr %#x.\n", hr);
2860         set_fpu_cw(0x37f);
2861         goto done;
2862     }
2863
2864     cw = get_fpu_cw();
2865     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2866
2867     IDirect3DDevice9_Release(device);
2868
2869     cw = get_fpu_cw();
2870     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2871     set_fpu_cw(0xf60);
2872     cw = get_fpu_cw();
2873     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2874
2875     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2876             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
2877     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
2878
2879     cw = get_fpu_cw();
2880     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2881     set_fpu_cw(0x37f);
2882
2883     IDirect3DDevice9_Release(device);
2884
2885 done:
2886     if (window) DestroyWindow(window);
2887     if (d3d9) IDirect3D9_Release(d3d9);
2888 #endif
2889 }
2890
2891 START_TEST(device)
2892 {
2893     HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
2894     WNDCLASS wc = {0};
2895
2896     wc.lpfnWndProc = DefWindowProc;
2897     wc.lpszClassName = "d3d9_test_wc";
2898     RegisterClass(&wc);
2899
2900     if (!d3d9_handle)
2901     {
2902         skip("Could not load d3d9.dll\n");
2903         goto out;
2904     }
2905
2906     pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
2907     ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
2908     if (pDirect3DCreate9)
2909     {
2910         IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2911         if(!d3d9)
2912         {
2913             skip("could not create D3D9 object\n");
2914             goto out;
2915         }
2916         IDirect3D9_Release(d3d9);
2917
2918         screen_width = GetSystemMetrics(SM_CXSCREEN);
2919         screen_height = GetSystemMetrics(SM_CYSCREEN);
2920
2921         test_fpu_setup();
2922         test_multi_device();
2923         test_display_formats();
2924         test_display_modes();
2925         test_swapchain();
2926         test_refcount();
2927         test_mipmap_levels();
2928         test_checkdevicemultisampletype();
2929         test_cursor();
2930         test_reset();
2931         test_scene();
2932         test_limits();
2933         test_depthstenciltest();
2934         test_draw_indexed();
2935         test_null_stream();
2936         test_lights();
2937         test_set_stream_source();
2938         test_scissor_size();
2939         test_wndproc();
2940         test_wndproc_windowed();
2941     }
2942
2943 out:
2944     UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));
2945 }