d3d9/tests: Avoid leaking a device in the Reset test.
[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     D3DPRESENT_PARAMETERS        d3dpp;
852     D3DDISPLAYMODE               d3ddm, d3ddm2;
853     D3DVIEWPORT9                 vp;
854     DWORD                        width, orig_width = GetSystemMetrics(SM_CXSCREEN);
855     DWORD                        height, orig_height = GetSystemMetrics(SM_CYSCREEN);
856     IDirect3DSwapChain9          *pSwapchain;
857     IDirect3DSurface9            *surface;
858     IDirect3DTexture9            *texture;
859     IDirect3DVertexShader9       *shader;
860     UINT                         i, adapter_mode_count;
861     D3DLOCKED_RECT               lockrect;
862     IDirect3DDevice9 *device1 = NULL;
863     IDirect3DDevice9 *device2 = NULL;
864     struct
865     {
866         UINT w;
867         UINT h;
868     } *modes = NULL;
869     UINT mode_count = 0;
870
871     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
872     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
873     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
874     ok(hwnd != NULL, "Failed to create window\n");
875     if (!pD3d || !hwnd) goto cleanup;
876
877     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
878     adapter_mode_count = IDirect3D9_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format);
879     modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
880     for(i = 0; i < adapter_mode_count; ++i)
881     {
882         UINT j;
883         ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
884         hr = IDirect3D9_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
885         ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
886
887         for (j = 0; j < mode_count; ++j)
888         {
889             if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
890                 break;
891         }
892         if (j == mode_count)
893         {
894             modes[j].w = d3ddm2.Width;
895             modes[j].h = d3ddm2.Height;
896             ++mode_count;
897         }
898
899         /* We use them as invalid modes */
900         if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
901            (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
902             skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
903                  d3ddm2.Width, d3ddm2.Height);
904             goto cleanup;
905         }
906     }
907
908     if (mode_count < 2)
909     {
910         skip("Less than 2 modes supported, skipping mode tests\n");
911         goto cleanup;
912     }
913
914     i = 0;
915     if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
916
917     ZeroMemory( &d3dpp, sizeof(d3dpp) );
918     d3dpp.Windowed         = FALSE;
919     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
920     d3dpp.BackBufferWidth  = modes[i].w;
921     d3dpp.BackBufferHeight = modes[i].h;
922     d3dpp.BackBufferFormat = d3ddm.Format;
923     d3dpp.EnableAutoDepthStencil = TRUE;
924     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
925
926     hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
927             hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
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(device1);
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(device1, &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(device1, &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(device1, &d3dpp);
968     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
969     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
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(device1, &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(device1, 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(device1, &d3dpp);
1013     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1014     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
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(device1, &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(device1, 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(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1058     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1059     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1060     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1061     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
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(device1, &d3dpp);
1066     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1067     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
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(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1072     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1073     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1074     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1075     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1076     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1077     IDirect3DSurface9_Release(surface);
1078
1079     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1080             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1081     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1082     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1083     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1084     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1085     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1086     IDirect3DSurface9_Release(surface);
1087
1088     /* The depth stencil should get reset to the auto depth stencil when present. */
1089     hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
1090     ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
1091
1092     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1093     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1094     ok(surface == NULL, "Depth stencil should be NULL\n");
1095
1096     d3dpp.EnableAutoDepthStencil = TRUE;
1097     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1098     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1099     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1100
1101     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1102     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1103     ok(surface != NULL, "Depth stencil should not be NULL\n");
1104     if (surface) IDirect3DSurface9_Release(surface);
1105
1106     d3dpp.EnableAutoDepthStencil = FALSE;
1107     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1108     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1109
1110     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1111     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1112     ok(surface == NULL, "Depth stencil should be NULL\n");
1113
1114     /* Will a sysmem or scratch survive while locked */
1115     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1116             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1117     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1118     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1119     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1120     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1121     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1122     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1123     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1124     IDirect3DSurface9_UnlockRect(surface);
1125     IDirect3DSurface9_Release(surface);
1126
1127     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1128     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1129     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1130     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1131     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1132     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1133     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1134     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1135     IDirect3DSurface9_UnlockRect(surface);
1136     IDirect3DSurface9_Release(surface);
1137
1138     hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
1139     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
1140     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1141     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1142     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1143     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1144     IDirect3DTexture9_Release(texture);
1145
1146     /* A reference held to an implicit surface causes failures as well */
1147     hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1148     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
1149     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1150     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1151     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1152     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1153     IDirect3DSurface9_Release(surface);
1154     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1155     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1156     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1157     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1158
1159     /* Shaders are fine as well */
1160     hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
1161     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
1162     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1163     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1164     IDirect3DVertexShader9_Release(shader);
1165
1166     /* Try setting invalid modes */
1167     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1168     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1169     d3dpp.Windowed         = FALSE;
1170     d3dpp.BackBufferWidth  = 32;
1171     d3dpp.BackBufferHeight = 32;
1172     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1173     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
1174     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1175     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1176
1177     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1178     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1179     d3dpp.Windowed         = FALSE;
1180     d3dpp.BackBufferWidth  = 801;
1181     d3dpp.BackBufferHeight = 600;
1182     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1183     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
1184     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1185     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1186
1187     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1188
1189     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1190     d3dpp.Windowed         = TRUE;
1191     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1192     d3dpp.BackBufferFormat = d3ddm.Format;
1193     d3dpp.EnableAutoDepthStencil = FALSE;
1194     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1195
1196     hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1197             hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
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(device2);
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(device2, &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(device2, &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 (device2)
1227     {
1228         UINT refcount = IDirect3DDevice9_Release(device2);
1229         ok(!refcount, "Device has %u references left.\n", refcount);
1230     }
1231     if (device1)
1232     {
1233         UINT refcount = IDirect3DDevice9_Release(device1);
1234         ok(!refcount, "Device has %u references left.\n", refcount);
1235     }
1236     if (pD3d) IDirect3D9_Release(pD3d);
1237     if (hwnd) DestroyWindow(hwnd);
1238 }
1239
1240 /* Test adapter display modes */
1241 static void test_display_modes(void)
1242 {
1243     D3DDISPLAYMODE dmode;
1244     IDirect3D9 *pD3d;
1245
1246     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1247     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1248     if(!pD3d) return;
1249
1250 #define TEST_FMT(x,r) do { \
1251     HRESULT res = IDirect3D9_EnumAdapterModes(pD3d, 0, (x), 0, &dmode); \
1252     ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
1253 } while(0)
1254
1255     TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
1256     TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
1257     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1258     /* D3DFMT_R5G6B5 */
1259     TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
1260     TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
1261     TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
1262     TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
1263     TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
1264     TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
1265     TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
1266     TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
1267     TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
1268     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1269     TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
1270     TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
1271
1272     TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
1273     TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
1274
1275     TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
1276     TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
1277     TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
1278
1279     TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
1280     TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
1281     TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
1282     TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
1283     TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
1284     TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
1285
1286     TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
1287     TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
1288     TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
1289     TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
1290     TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
1291     TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
1292     TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
1293     TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
1294     TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
1295     TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
1296
1297     TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
1298     TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
1299     TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
1300     TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
1301     TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
1302     TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
1303     TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
1304     TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
1305     TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
1306     TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
1307
1308     TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
1309     TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
1310     TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
1311     TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
1312     /* Floating point formats */
1313     TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
1314     TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
1315     TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
1316
1317     /* IEEE formats */
1318     TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
1319     TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
1320     TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
1321
1322     TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
1323
1324     TEST_FMT(0, D3DERR_INVALIDCALL);
1325
1326     IDirect3D9_Release(pD3d);
1327 }
1328
1329 static void test_scene(void)
1330 {
1331     HRESULT                      hr;
1332     HWND                         hwnd               = NULL;
1333     IDirect3D9                  *pD3d               = NULL;
1334     IDirect3DDevice9            *pDevice            = NULL;
1335     D3DPRESENT_PARAMETERS        d3dpp;
1336     D3DDISPLAYMODE               d3ddm;
1337     IDirect3DSurface9            *pSurface1 = NULL, *pSurface2 = NULL, *pSurface3 = NULL, *pRenderTarget = NULL;
1338     IDirect3DSurface9            *pBackBuffer = NULL, *pDepthStencil = NULL;
1339     RECT rect = {0, 0, 128, 128};
1340     D3DCAPS9                     caps;
1341
1342     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1343     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1344     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1345     ok(hwnd != NULL, "Failed to create window\n");
1346     if (!pD3d || !hwnd) goto cleanup;
1347
1348     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1349     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1350     d3dpp.Windowed         = TRUE;
1351     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1352     d3dpp.BackBufferWidth  = 800;
1353     d3dpp.BackBufferHeight = 600;
1354     d3dpp.BackBufferFormat = d3ddm.Format;
1355     d3dpp.EnableAutoDepthStencil = TRUE;
1356     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1357
1358     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1359                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1360     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1361     if(!pDevice)
1362     {
1363         skip("Failed to create a d3d device\n");
1364         goto cleanup;
1365     }
1366
1367     /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
1368     memset(&caps, 0, sizeof(caps));
1369     hr = IDirect3DDevice9_GetDeviceCaps(pDevice, &caps);
1370     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
1371     if(FAILED(hr)) goto cleanup;
1372
1373     /* Test an EndScene without beginscene. Should return an error */
1374     hr = IDirect3DDevice9_EndScene(pDevice);
1375     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1376
1377     /* Test a normal BeginScene / EndScene pair, this should work */
1378     hr = IDirect3DDevice9_BeginScene(pDevice);
1379     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1380     if(SUCCEEDED(hr))
1381     {
1382         hr = IDirect3DDevice9_EndScene(pDevice);
1383         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1384     }
1385
1386     /* Test another EndScene without having begun a new scene. Should return an error */
1387     hr = IDirect3DDevice9_EndScene(pDevice);
1388     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1389
1390     /* Two nested BeginScene and EndScene calls */
1391     hr = IDirect3DDevice9_BeginScene(pDevice);
1392     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1393     hr = IDirect3DDevice9_BeginScene(pDevice);
1394     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
1395     hr = IDirect3DDevice9_EndScene(pDevice);
1396     ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1397     hr = IDirect3DDevice9_EndScene(pDevice);
1398     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1399
1400     /* Create some surfaces to test stretchrect between the scenes */
1401     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface1, NULL);
1402     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1403     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface2, NULL);
1404     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1405     hr = IDirect3DDevice9_CreateDepthStencilSurface(pDevice, 800, 600, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface3, NULL);
1406     ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
1407     hr = IDirect3DDevice9_CreateRenderTarget(pDevice, 128, 128, d3ddm.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pRenderTarget, NULL);
1408     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
1409
1410     hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
1411     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1412     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1413     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1414
1415     /* First make sure a simple StretchRect call works */
1416     if(pSurface1 && pSurface2) {
1417         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1418         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1419     }
1420     if(pBackBuffer && pRenderTarget) {
1421         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1422         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1423     }
1424     if(pDepthStencil && pSurface3) {
1425         HRESULT expected;
1426         if(0) /* Disabled for now because it crashes in wine */ {
1427             expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
1428             hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1429             ok( hr == expected, "IDirect3DDevice9_StretchRect returned %08x, expected %08x\n", hr, expected);
1430         }
1431     }
1432
1433     /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a beginScene - Endscene pair
1434      * width normal surfaces, render targets and depth stencil surfaces.
1435      */
1436     hr = IDirect3DDevice9_BeginScene(pDevice);
1437     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1438
1439     if(pSurface1 && pSurface2)
1440     {
1441         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1442         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1443     }
1444     if(pBackBuffer && pRenderTarget)
1445     {
1446         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1447         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1448     }
1449     if(pDepthStencil && pSurface3)
1450     {
1451         /* This is supposed to fail inside a BeginScene - EndScene pair. */
1452         hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1453         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
1454     }
1455
1456     hr = IDirect3DDevice9_EndScene(pDevice);
1457     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1458
1459     /* Does a SetRenderTarget influence BeginScene / EndScene ?
1460      * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
1461      * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
1462      */
1463     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pRenderTarget);
1464     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1465     hr = IDirect3DDevice9_BeginScene(pDevice);
1466     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1467     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pBackBuffer);
1468     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1469     hr = IDirect3DDevice9_EndScene(pDevice);
1470     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1471
1472 cleanup:
1473     if(pRenderTarget) IDirect3DSurface9_Release(pRenderTarget);
1474     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1475     if(pBackBuffer) IDirect3DSurface9_Release(pBackBuffer);
1476     if(pSurface1) IDirect3DSurface9_Release(pSurface1);
1477     if(pSurface2) IDirect3DSurface9_Release(pSurface2);
1478     if(pSurface3) IDirect3DSurface9_Release(pSurface3);
1479     if (pDevice)
1480     {
1481         UINT refcount = IDirect3DDevice9_Release(pDevice);
1482         ok(!refcount, "Device has %u references left.\n", refcount);
1483     }
1484     if (pD3d) IDirect3D9_Release(pD3d);
1485     if(hwnd) DestroyWindow(hwnd);
1486 }
1487
1488 static void test_limits(void)
1489 {
1490     HRESULT                      hr;
1491     HWND                         hwnd               = NULL;
1492     IDirect3D9                  *pD3d               = NULL;
1493     IDirect3DDevice9            *pDevice            = NULL;
1494     D3DPRESENT_PARAMETERS        d3dpp;
1495     D3DDISPLAYMODE               d3ddm;
1496     IDirect3DTexture9           *pTexture           = NULL;
1497     int i;
1498
1499     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1500     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1501     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1502     ok(hwnd != NULL, "Failed to create window\n");
1503     if (!pD3d || !hwnd) goto cleanup;
1504
1505     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1506     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1507     d3dpp.Windowed         = TRUE;
1508     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1509     d3dpp.BackBufferWidth  = 800;
1510     d3dpp.BackBufferHeight = 600;
1511     d3dpp.BackBufferFormat = d3ddm.Format;
1512     d3dpp.EnableAutoDepthStencil = TRUE;
1513     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1514
1515     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1516                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1517     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1518     if(!pDevice)
1519     {
1520         skip("Failed to create a d3d device\n");
1521         goto cleanup;
1522     }
1523
1524     hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL);
1525     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
1526     if(!pTexture) goto cleanup;
1527
1528     /* There are 16 pixel samplers. We should be able to access all of them */
1529     for(i = 0; i < 16; i++) {
1530         hr = IDirect3DDevice9_SetTexture(pDevice, i, (IDirect3DBaseTexture9 *) pTexture);
1531         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1532         hr = IDirect3DDevice9_SetTexture(pDevice, i, NULL);
1533         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1534         hr = IDirect3DDevice9_SetSamplerState(pDevice, i, D3DSAMP_SRGBTEXTURE, TRUE);
1535         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
1536     }
1537
1538     /* Now test all 8 textures stage states */
1539     for(i = 0; i < 8; i++) {
1540         hr = IDirect3DDevice9_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1541         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
1542     }
1543
1544     /* Investigations show that accessing higher samplers / textures stage states does not return an error either. Writing
1545      * to too high samplers(approximately sampler 40) causes memory corruption in windows, so there is no bounds checking
1546      * but how do I test that?
1547      */
1548 cleanup:
1549     if(pTexture) IDirect3DTexture9_Release(pTexture);
1550     if (pDevice)
1551     {
1552         UINT refcount = IDirect3D9_Release(pDevice);
1553         ok(!refcount, "Device has %u references left.\n", refcount);
1554     }
1555     if (pD3d) IDirect3D9_Release(pD3d);
1556     if(hwnd) DestroyWindow(hwnd);
1557 }
1558
1559 static void test_depthstenciltest(void)
1560 {
1561     HRESULT                      hr;
1562     HWND                         hwnd               = NULL;
1563     IDirect3D9                  *pD3d               = NULL;
1564     IDirect3DDevice9            *pDevice            = NULL;
1565     D3DPRESENT_PARAMETERS        d3dpp;
1566     D3DDISPLAYMODE               d3ddm;
1567     IDirect3DSurface9           *pDepthStencil           = NULL;
1568     IDirect3DSurface9           *pDepthStencil2          = NULL;
1569     D3DZBUFFERTYPE               state;
1570
1571     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1572     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1573     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1574     ok(hwnd != NULL, "Failed to create window\n");
1575     if (!pD3d || !hwnd) goto cleanup;
1576
1577     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1578     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1579     d3dpp.Windowed         = TRUE;
1580     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1581     d3dpp.BackBufferWidth  = 800;
1582     d3dpp.BackBufferHeight = 600;
1583     d3dpp.BackBufferFormat = d3ddm.Format;
1584     d3dpp.EnableAutoDepthStencil = TRUE;
1585     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1586
1587     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1588                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1589     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1590     if(!pDevice)
1591     {
1592         skip("Failed to create a d3d device\n");
1593         goto cleanup;
1594     }
1595
1596     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1597     ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1598
1599     /* Try to clear */
1600     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1601     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1602
1603     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
1604     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1605
1606     /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
1607     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
1608     ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1609     if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
1610
1611     /* This left the render states untouched! */
1612     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1613     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1614     ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1615     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
1616     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1617     ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
1618     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
1619     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1620     ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
1621     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
1622     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1623     ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
1624
1625     /* This is supposed to fail now */
1626     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1627     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1628
1629     hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
1630     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
1631
1632     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
1633     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1634
1635     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1636     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1637     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1638
1639     /* Now it works again */
1640     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1641     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1642
1643     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1644     if(pDevice) IDirect3D9_Release(pDevice);
1645
1646     /* Now see if autodepthstencil disable is honored. First, without a format set */
1647     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1648     d3dpp.Windowed         = TRUE;
1649     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1650     d3dpp.BackBufferWidth  = 800;
1651     d3dpp.BackBufferHeight = 600;
1652     d3dpp.BackBufferFormat = d3ddm.Format;
1653     d3dpp.EnableAutoDepthStencil = FALSE;
1654     d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1655
1656     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1657                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1658     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1659     if(!pDevice)
1660     {
1661         skip("Failed to create a d3d device\n");
1662         goto cleanup;
1663     }
1664
1665     pDepthStencil = NULL;
1666     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1667     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1668     if(pDepthStencil) {
1669         IDirect3DSurface9_Release(pDepthStencil);
1670         pDepthStencil = NULL;
1671     }
1672
1673     /* Check the depth test state */
1674     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1675     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1676     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1677
1678     if(pDevice) IDirect3D9_Release(pDevice);
1679
1680     /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
1681     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1682     d3dpp.Windowed         = TRUE;
1683     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1684     d3dpp.BackBufferWidth  = 800;
1685     d3dpp.BackBufferHeight = 600;
1686     d3dpp.BackBufferFormat = d3ddm.Format;
1687     d3dpp.EnableAutoDepthStencil = FALSE;
1688     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1689
1690     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1691                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1692     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1693     if(!pDevice)
1694     {
1695         skip("Failed to create a d3d device\n");
1696         goto cleanup;
1697     }
1698
1699     pDepthStencil = NULL;
1700     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1701     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1702     if(pDepthStencil) {
1703         IDirect3DSurface9_Release(pDepthStencil);
1704         pDepthStencil = NULL;
1705     }
1706
1707     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1708     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1709     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1710
1711 cleanup:
1712     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1713     if (pDevice)
1714     {
1715         UINT refcount = IDirect3D9_Release(pDevice);
1716         ok(!refcount, "Device has %u references left.\n", refcount);
1717     }
1718     if (pD3d) IDirect3D9_Release(pD3d);
1719     if(hwnd) DestroyWindow(hwnd);
1720 }
1721
1722 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
1723 static void test_draw_indexed(void)
1724 {
1725     static const struct {
1726         float position[3];
1727         DWORD color;
1728     } quad[] = {
1729         {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
1730         {{-1.0f,  1.0f, 0.0f}, 0xffff0000},
1731         {{ 1.0f,  1.0f, 0.0f}, 0xffff0000},
1732         {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
1733     };
1734     WORD indices[] = {0, 1, 2, 3, 0, 2};
1735
1736     static const D3DVERTEXELEMENT9 decl_elements[] = {
1737         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1738         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1739         D3DDECL_END()
1740     };
1741
1742     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1743     IDirect3DVertexBuffer9 *vertex_buffer = NULL;
1744     IDirect3DIndexBuffer9 *index_buffer = NULL;
1745     D3DPRESENT_PARAMETERS present_parameters;
1746     IDirect3DDevice9 *device = NULL;
1747     IDirect3D9 *d3d9;
1748     HRESULT hr;
1749     HWND hwnd;
1750     void *ptr;
1751
1752     hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
1753             0, 0, 0, 10, 10, 0, 0, 0, 0);
1754     if (!hwnd)
1755     {
1756         skip("Failed to create window\n");
1757         return;
1758     }
1759
1760     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
1761     if (!d3d9)
1762     {
1763         skip("Failed to create IDirect3D9 object\n");
1764         goto cleanup;
1765     }
1766
1767     ZeroMemory(&present_parameters, sizeof(present_parameters));
1768     present_parameters.Windowed = TRUE;
1769     present_parameters.hDeviceWindow = hwnd;
1770     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1771
1772     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1773             NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1774     if (FAILED(hr) || !device)
1775     {
1776         skip("Failed to create device\n");
1777         goto cleanup;
1778     }
1779
1780     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1781     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1782     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1783     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1784
1785     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
1786     ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
1787     hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1788     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1789     memcpy(ptr, quad, sizeof(quad));
1790     hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
1791     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1792     hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
1793     ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
1794
1795     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
1796     ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
1797     hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1798     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1799     memcpy(ptr, indices, sizeof(indices));
1800     hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
1801     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1802     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1803     ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
1804     hr = IDirect3DDevice9_BeginScene(device);
1805     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1806
1807     /* NULL index buffer. Should fail */
1808     hr = IDirect3DDevice9_SetIndices(device, NULL);
1809     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1810     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1811             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1812     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1813             hr, D3DERR_INVALIDCALL);
1814
1815     /* Valid index buffer, NULL vertex declaration. Should fail */
1816     hr = IDirect3DDevice9_SetIndices(device, index_buffer);
1817     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1818     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1819             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1820     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1821             hr, D3DERR_INVALIDCALL);
1822
1823     /* Valid index buffer and vertex declaration. Should succeed */
1824     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1825     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1826     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1827             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1828     ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
1829
1830     hr = IDirect3DDevice9_EndScene(device);
1831     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1832
1833     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1834     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1835
1836     IDirect3DVertexBuffer9_Release(vertex_buffer);
1837     IDirect3DIndexBuffer9_Release(index_buffer);
1838     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1839
1840 cleanup:
1841     if (device)
1842     {
1843         UINT refcount = IDirect3DDevice9_Release(device);
1844         ok(!refcount, "Device has %u references left.\n", refcount);
1845     }
1846     if (d3d9) IDirect3D9_Release(d3d9);
1847     if (hwnd) DestroyWindow(hwnd);
1848 }
1849
1850 static void test_null_stream(void)
1851 {
1852     IDirect3DVertexBuffer9 *buffer = NULL;
1853     D3DPRESENT_PARAMETERS present_parameters;
1854     IDirect3DDevice9 *device = NULL;
1855     IDirect3D9 *d3d9;
1856     HWND hwnd;
1857     HRESULT hr;
1858     IDirect3DVertexShader9 *shader = NULL;
1859     IDirect3DVertexDeclaration9 *decl = NULL;
1860     DWORD shader_code[] = {
1861         0xfffe0101,                             /* vs_1_1           */
1862         0x0000001f, 0x80000000, 0x900f0000,     /* dcl_position v0  */
1863         0x00000001, 0xc00f0000, 0x90e40000,     /* mov oPos, v0     */
1864         0x0000ffff                              /* end              */
1865     };
1866     static const D3DVERTEXELEMENT9 decl_elements[] = {
1867         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1868         {1, 0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1869         D3DDECL_END()
1870     };
1871
1872     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
1873     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
1874     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1875     ok(hwnd != NULL, "Failed to create window\n");
1876     if (!d3d9 || !hwnd) goto cleanup;
1877
1878     ZeroMemory(&present_parameters, sizeof(present_parameters));
1879     present_parameters.Windowed = TRUE;
1880     present_parameters.hDeviceWindow = hwnd;
1881     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1882
1883     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1884                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
1885     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1886     if(!device)
1887     {
1888         skip("Failed to create a d3d device\n");
1889         goto cleanup;
1890     }
1891
1892     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
1893     if(FAILED(hr)) {
1894         skip("No vertex shader support\n");
1895         goto cleanup;
1896     }
1897     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
1898     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
1899     if (FAILED(hr)) {
1900         skip("Vertex declaration handling not possible.\n");
1901         goto cleanup;
1902     }
1903     hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
1904     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
1905     if (FAILED(hr)) {
1906         skip("Vertex buffer handling not possible.\n");
1907         goto cleanup;
1908     }
1909
1910     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
1911     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
1912     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
1913     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
1914     hr = IDirect3DDevice9_SetVertexShader(device, shader);
1915     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
1916     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
1917     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
1918
1919     hr = IDirect3DDevice9_BeginScene(device);
1920     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (0x%08x)\n", hr);
1921     if(SUCCEEDED(hr)) {
1922         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
1923         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitive failed (0x%08x)\n", hr);
1924
1925         hr = IDirect3DDevice9_EndScene(device);
1926         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed (0x%08x)\n", hr);
1927     }
1928
1929     IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1930     IDirect3DDevice9_SetVertexShader(device, NULL);
1931     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1932
1933 cleanup:
1934     if (buffer) IDirect3DVertexBuffer9_Release(buffer);
1935     if(decl) IDirect3DVertexDeclaration9_Release(decl);
1936     if(shader) IDirect3DVertexShader9_Release(shader);
1937     if (device)
1938     {
1939         UINT refcount = IDirect3DDevice9_Release(device);
1940         ok(!refcount, "Device has %u references left.\n", refcount);
1941     }
1942     if(d3d9) IDirect3D9_Release(d3d9);
1943 }
1944
1945 static void test_lights(void)
1946 {
1947     D3DPRESENT_PARAMETERS present_parameters;
1948     IDirect3DDevice9 *device = NULL;
1949     IDirect3D9 *d3d9;
1950     HWND hwnd;
1951     HRESULT hr;
1952     unsigned int i;
1953     BOOL enabled;
1954     D3DCAPS9 caps;
1955
1956     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
1957     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
1958     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1959     ok(hwnd != NULL, "Failed to create window\n");
1960     if (!d3d9 || !hwnd) goto cleanup;
1961
1962     ZeroMemory(&present_parameters, sizeof(present_parameters));
1963     present_parameters.Windowed = TRUE;
1964     present_parameters.hDeviceWindow = hwnd;
1965     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1966
1967     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
1968                                   D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &present_parameters, &device );
1969     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1970        "IDirect3D9_CreateDevice failed with %08x\n", hr);
1971     if(!device)
1972     {
1973         skip("Failed to create a d3d device\n");
1974         goto cleanup;
1975     }
1976
1977     memset(&caps, 0, sizeof(caps));
1978     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1979     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
1980
1981     for(i = 1; i <= caps.MaxActiveLights; i++) {
1982         hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
1983         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1984         hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
1985         ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
1986         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1987     }
1988
1989     /* TODO: Test the rendering results in this situation */
1990     hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
1991     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
1992     hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
1993     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1994     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1995     hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
1996     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1997
1998     for(i = 1; i <= caps.MaxActiveLights; i++) {
1999         hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2000         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2001     }
2002
2003 cleanup:
2004     if (device)
2005     {
2006         UINT refcount = IDirect3DDevice9_Release(device);
2007         ok(!refcount, "Device has %u references left.\n", refcount);
2008     }
2009     if(d3d9) IDirect3D9_Release(d3d9);
2010 }
2011
2012 static void test_set_stream_source(void)
2013 {
2014     D3DPRESENT_PARAMETERS present_parameters;
2015     IDirect3DDevice9 *device = NULL;
2016     IDirect3D9 *d3d9;
2017     HWND hwnd;
2018     HRESULT hr;
2019     IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
2020
2021     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2022     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2023     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2024     ok(hwnd != NULL, "Failed to create window\n");
2025     if (!d3d9 || !hwnd) goto cleanup;
2026
2027     ZeroMemory(&present_parameters, sizeof(present_parameters));
2028     present_parameters.Windowed = TRUE;
2029     present_parameters.hDeviceWindow = hwnd;
2030     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2031
2032     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 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         hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd,
2039                                       D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2040         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2041            "IDirect3D9_CreateDevice failed with %08x\n", hr);
2042         if(!device)
2043         {
2044             skip("Failed to create a d3d device\n");
2045             goto cleanup;
2046         }
2047     }
2048
2049     hr = IDirect3DDevice9_CreateVertexBuffer( device, 512, 0, 0, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
2050     ok(hr == D3D_OK, "Failed to create a vertex buffer, hr = %08x\n", hr);
2051     if (SUCCEEDED(hr)) {
2052         /* Some cards(Geforce 7400 at least) accept non-aligned offsets, others(radeon 9000 verified) reject it,
2053          * so accept both results. Wine currently rejects this to be able to optimize the vbo conversion, but writes
2054          * a WARN
2055          */
2056         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32);
2057         ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2058         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32);
2059         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2060         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 2, 32);
2061         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2062         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 3, 32);
2063         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2064         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 4, 32);
2065         ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2066     }
2067     /* Try to set the NULL buffer with an offset and stride 0 */
2068     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2069     ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2070     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2071     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2072     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2073     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2074     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2075     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2076     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2077     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2078
2079     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2080     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2081
2082 cleanup:
2083     if (pVertexBuffer) IDirect3DVertexBuffer9_Release(pVertexBuffer);
2084     if (device)
2085     {
2086         UINT refcount = IDirect3DDevice9_Release(device);
2087         ok(!refcount, "Device has %u references left.\n", refcount);
2088     }
2089     if(d3d9) IDirect3D9_Release(d3d9);
2090 }
2091
2092 struct formats {
2093     D3DFORMAT DisplayFormat;
2094     D3DFORMAT BackBufferFormat;
2095     BOOL shouldPass;
2096 };
2097
2098 static const struct formats r5g6b5_format_list[] =
2099 {
2100     { D3DFMT_R5G6B5, D3DFMT_R5G6B5, TRUE },
2101     { D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, FALSE },
2102     { D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, FALSE },
2103     { D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, FALSE },
2104     { D3DFMT_R5G6B5, D3DFMT_A8R8G8B8, FALSE },
2105     { 0, 0, 0}
2106 };
2107
2108 static const struct formats x1r5g5b5_format_list[] =
2109 {
2110     { D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, FALSE },
2111     { D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, TRUE },
2112     { D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE },
2113     { D3DFMT_X1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2114     { D3DFMT_X1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2115
2116     /* A1R5G5B5 should not be usable as a display format, it is backbuffer-only */
2117     { D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, FALSE },
2118     { D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, FALSE },
2119     { D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE },
2120     { D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2121     { D3DFMT_A1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2122     { 0, 0, 0}
2123 };
2124
2125 static const struct formats x8r8g8b8_format_list[] =
2126 {
2127     { D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, FALSE },
2128     { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2129     { D3DFMT_X8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2130     { D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, TRUE },
2131     { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE },
2132
2133     /* A1R8G8B8 should not be usable as a display format, it is backbuffer-only */
2134     { D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, FALSE },
2135     { D3DFMT_A8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2136     { D3DFMT_A8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2137     { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, FALSE },
2138     { D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE },
2139     { 0, 0, 0}
2140 };
2141
2142 static void test_display_formats(void)
2143 {
2144     /* Direct3D9 offers 4 display formats R5G6B5, X1R5G5B5, X8R8G8B8 and A2R10G10B10.
2145      * Next to these there are 6 different backbuffer formats. Only a fixed number of
2146      * combinations are possible in FULLSCREEN mode. In windowed mode more combinations are
2147      * allowed due to depth conversion and this is likely driver dependent.
2148      * This test checks which combinations are possible in fullscreen mode and this should not be driver dependent.
2149      * TODO: handle A2R10G10B10 but what hardware supports it? Parhelia? It is very rare. */
2150
2151     UINT Adapter = D3DADAPTER_DEFAULT;
2152     D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
2153     int i, nmodes;
2154     HRESULT hr;
2155
2156     IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2157     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2158     if(!d3d9) return;
2159
2160     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_R5G6B5);
2161     if(!nmodes) {
2162         skip("Display format R5G6B5 not supported, skipping\n");
2163     } else {
2164         trace("Testing display format R5G6B5\n");
2165         for(i=0; r5g6b5_format_list[i].DisplayFormat != 0; i++)
2166         {
2167             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, FALSE);
2168
2169             if(r5g6b5_format_list[i].shouldPass)
2170                 ok(hr == D3D_OK ||
2171                    broken(hr == D3DERR_NOTAVAILABLE),
2172                    "format %d %d didn't pass with hr=%#08x\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, hr);
2173             else
2174                 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);
2175         }
2176     }
2177
2178     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X1R5G5B5);
2179     if(!nmodes) {
2180         skip("Display format X1R5G5B5 not supported, skipping\n");
2181     } else {
2182         trace("Testing display format X1R5G5B5\n");
2183         for(i=0; x1r5g5b5_format_list[i].DisplayFormat != 0; i++)
2184         {
2185             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, FALSE);
2186
2187             if(x1r5g5b5_format_list[i].shouldPass)
2188                 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);
2189             else
2190                 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);
2191         }
2192     }
2193
2194     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
2195     if(!nmodes) {
2196         skip("Display format X8R8G8B8 not supported, skipping\n");
2197     } else {
2198         trace("Testing display format X8R8G8B8\n");
2199         for(i=0; x8r8g8b8_format_list[i].DisplayFormat != 0; i++)
2200         {
2201             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, FALSE);
2202
2203             if(x8r8g8b8_format_list[i].shouldPass)
2204                 ok(hr == D3D_OK ||
2205                    broken(hr == D3DERR_NOTAVAILABLE),
2206                    "format %d %d didn't pass with hr=%#08x\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr);
2207             else
2208                 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);
2209         }
2210     }
2211
2212     if(d3d9) IDirect3D9_Release(d3d9);
2213 }
2214
2215 static void test_scissor_size(void)
2216 {
2217     IDirect3D9 *d3d9_ptr = 0;
2218     unsigned int i;
2219     static struct {
2220         int winx; int winy; int backx; int backy; BOOL window;
2221     } scts[] = { /* scissor tests */
2222         {800, 600, 640, 480, TRUE},
2223         {800, 600, 640, 480, FALSE},
2224         {640, 480, 800, 600, TRUE},
2225         {640, 480, 800, 600, FALSE},
2226     };
2227
2228     d3d9_ptr = pDirect3DCreate9(D3D_SDK_VERSION);
2229     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
2230     if (!d3d9_ptr){
2231         skip("Failed to create IDirect3D9 object\n");
2232         return;
2233     }
2234
2235     for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
2236         IDirect3DDevice9 *device_ptr = 0;
2237         D3DPRESENT_PARAMETERS present_parameters;
2238         HRESULT hr;
2239         HWND hwnd = 0;
2240         RECT scissorrect;
2241
2242         hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
2243                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
2244
2245         if (!scts[i].window)
2246         {
2247             scts[i].backx = screen_width;
2248             scts[i].backy = screen_height;
2249         }
2250
2251         ZeroMemory(&present_parameters, sizeof(present_parameters));
2252         present_parameters.Windowed = scts[i].window;
2253         present_parameters.hDeviceWindow = hwnd;
2254         present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2255         present_parameters.BackBufferWidth = scts[i].backx;
2256         present_parameters.BackBufferHeight = scts[i].backy;
2257         present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
2258         present_parameters.EnableAutoDepthStencil = TRUE;
2259         present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2260
2261         hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2262         if(FAILED(hr)) {
2263             present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
2264             hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2265             if(FAILED(hr)) {
2266                 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2267             }
2268         }
2269         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
2270
2271         if (!device_ptr)
2272         {
2273             DestroyWindow(hwnd);
2274             skip("Creating the device failed\n");
2275             goto err_out;
2276         }
2277
2278         /* Check for the default scissor rect size */
2279         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2280         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2281         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);
2282
2283         /* check the scissorrect values after a reset */
2284         present_parameters.BackBufferWidth = screen_width;
2285         present_parameters.BackBufferHeight = screen_height;
2286         hr = IDirect3DDevice9_Reset(device_ptr, &present_parameters);
2287         ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2288         hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
2289         ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2290
2291         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2292         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2293         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);
2294
2295         if(device_ptr) {
2296             ULONG ref;
2297
2298             ref = IDirect3DDevice9_Release(device_ptr);
2299             DestroyWindow(hwnd);
2300             ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
2301         }
2302     }
2303
2304 err_out:
2305     if(d3d9_ptr) IDirect3D9_Release(d3d9_ptr);
2306     return;
2307 }
2308
2309 static void test_multi_device(void)
2310 {
2311     IDirect3DDevice9 *device1 = NULL, *device2 = NULL;
2312     D3DPRESENT_PARAMETERS present_parameters;
2313     HWND hwnd1 = NULL, hwnd2 = NULL;
2314     IDirect3D9 *d3d9;
2315     ULONG refcount;
2316     HRESULT hr;
2317
2318     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2319     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2320     if (!d3d9) goto fail;
2321
2322     hwnd1 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2323     ok(hwnd1 != NULL, "Failed to create a window.\n");
2324     if (!hwnd1) goto fail;
2325
2326     memset(&present_parameters, 0, sizeof(present_parameters));
2327     present_parameters.Windowed = TRUE;
2328     present_parameters.hDeviceWindow = hwnd1;
2329     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2330
2331     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd1,
2332             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device1);
2333     IDirect3D9_Release(d3d9);
2334     d3d9 = NULL;
2335     if (FAILED(hr)) {
2336         skip("Failed to create a device\n");
2337         goto fail;
2338     }
2339
2340     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2341     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2342     if (!d3d9) goto fail;
2343
2344     hwnd2 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2345     ok(hwnd2 != NULL, "Failed to create a window.\n");
2346     if (!hwnd2) goto fail;
2347
2348     memset(&present_parameters, 0, sizeof(present_parameters));
2349     present_parameters.Windowed = TRUE;
2350     present_parameters.hDeviceWindow = hwnd2;
2351     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2352
2353     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd2,
2354             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device2);
2355     ok(SUCCEEDED(hr), "Failed to create a device, hr %#x\n", hr);
2356     IDirect3D9_Release(d3d9);
2357     d3d9 = NULL;
2358     if (FAILED(hr)) goto fail;
2359
2360 fail:
2361     if (d3d9) IDirect3D9_Release(d3d9);
2362     if (device1)
2363     {
2364         refcount = IDirect3DDevice9_Release(device1);
2365         ok(!refcount, "Device has %u references left.\n", refcount);
2366     }
2367     if (device2)
2368     {
2369         refcount = IDirect3DDevice9_Release(device2);
2370         ok(!refcount, "Device has %u references left.\n", refcount);
2371     }
2372     if (hwnd1) DestroyWindow(hwnd1);
2373     if (hwnd2) DestroyWindow(hwnd2);
2374 }
2375
2376 static HWND filter_messages;
2377
2378 enum message_window
2379 {
2380     DEVICE_WINDOW,
2381     FOCUS_WINDOW,
2382 };
2383
2384 struct message
2385 {
2386     UINT message;
2387     enum message_window window;
2388 };
2389
2390 static const struct message *expect_messages;
2391 static HWND device_window, focus_window;
2392
2393 struct wndproc_thread_param
2394 {
2395     HWND dummy_window;
2396     HANDLE window_created;
2397     HANDLE test_finished;
2398     BOOL running_in_foreground;
2399 };
2400
2401 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2402 {
2403     if (filter_messages && filter_messages == hwnd)
2404     {
2405         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2406             todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2407     }
2408
2409     if (expect_messages)
2410     {
2411         HWND w;
2412
2413         switch (expect_messages->window)
2414         {
2415             case DEVICE_WINDOW:
2416                 w = device_window;
2417                 break;
2418
2419             case FOCUS_WINDOW:
2420                 w = focus_window;
2421                 break;
2422
2423             default:
2424                 w = NULL;
2425                 break;
2426         };
2427
2428         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2429     }
2430
2431     return DefWindowProcA(hwnd, message, wparam, lparam);
2432 }
2433
2434 static DWORD WINAPI wndproc_thread(void *param)
2435 {
2436     struct wndproc_thread_param *p = param;
2437     DWORD res;
2438     BOOL ret;
2439
2440     p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2441             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2442     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2443
2444     ret = SetEvent(p->window_created);
2445     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2446
2447     for (;;)
2448     {
2449         MSG msg;
2450
2451         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2452         res = WaitForSingleObject(p->test_finished, 100);
2453         if (res == WAIT_OBJECT_0) break;
2454         if (res != WAIT_TIMEOUT)
2455         {
2456             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2457             break;
2458         }
2459     }
2460
2461     DestroyWindow(p->dummy_window);
2462
2463     return 0;
2464 }
2465
2466 static void test_wndproc(void)
2467 {
2468     struct wndproc_thread_param thread_params;
2469     IDirect3DDevice9 *device;
2470     WNDCLASSA wc = {0};
2471     IDirect3D9 *d3d9;
2472     HANDLE thread;
2473     LONG_PTR proc;
2474     ULONG ref;
2475     DWORD res, tid;
2476     HWND tmp;
2477
2478     static const struct message messages[] =
2479     {
2480         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2481         {WM_ACTIVATE,           FOCUS_WINDOW},
2482         {WM_SETFOCUS,           FOCUS_WINDOW},
2483         {0,                     0},
2484     };
2485
2486     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2487     {
2488         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2489         return;
2490     }
2491
2492     wc.lpfnWndProc = test_proc;
2493     wc.lpszClassName = "d3d9_test_wndproc_wc";
2494     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2495
2496     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2497     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2498     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2499     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2500
2501     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2502             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2503     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2504             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2505     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2506     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2507
2508     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2509     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2510
2511     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2512     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2513             (LONG_PTR)test_proc, proc);
2514     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2515     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2516             (LONG_PTR)test_proc, proc);
2517
2518     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2519             device_window, focus_window, thread_params.dummy_window);
2520
2521     tmp = GetFocus();
2522     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2523     if (thread_params.running_in_foreground)
2524     {
2525         tmp = GetForegroundWindow();
2526         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2527                 thread_params.dummy_window, tmp);
2528     }
2529     else
2530         skip("Not running in foreground, skip foreground window test\n");
2531
2532     flush_events();
2533
2534     expect_messages = messages;
2535
2536     device = create_device(d3d9, device_window, focus_window, FALSE);
2537     if (!device)
2538     {
2539         skip("Failed to create a D3D device, skipping tests.\n");
2540         goto done;
2541     }
2542
2543     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2544             expect_messages->message, expect_messages->window);
2545     expect_messages = NULL;
2546
2547     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2548     {
2549         tmp = GetFocus();
2550         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2551         tmp = GetForegroundWindow();
2552         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2553     }
2554     SetForegroundWindow(focus_window);
2555     flush_events();
2556
2557     filter_messages = focus_window;
2558
2559     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2560     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2561             (LONG_PTR)test_proc, proc);
2562
2563     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2564     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2565             (LONG_PTR)test_proc, proc);
2566
2567     ref = IDirect3DDevice9_Release(device);
2568     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2569
2570     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2571     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2572             (LONG_PTR)test_proc, proc);
2573
2574     device = create_device(d3d9, focus_window, focus_window, FALSE);
2575     if (!device)
2576     {
2577         skip("Failed to create a D3D device, skipping tests.\n");
2578         goto done;
2579     }
2580
2581     ref = IDirect3DDevice9_Release(device);
2582     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2583
2584     device = create_device(d3d9, device_window, focus_window, FALSE);
2585     if (!device)
2586     {
2587         skip("Failed to create a D3D device, skipping tests.\n");
2588         goto done;
2589     }
2590
2591     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2592     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2593             (LONG_PTR)test_proc, proc);
2594
2595     ref = IDirect3DDevice9_Release(device);
2596     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2597
2598     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2599     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2600             (LONG_PTR)DefWindowProcA, proc);
2601
2602 done:
2603     filter_messages = NULL;
2604     IDirect3D9_Release(d3d9);
2605
2606     SetEvent(thread_params.test_finished);
2607     WaitForSingleObject(thread, INFINITE);
2608     CloseHandle(thread_params.test_finished);
2609     CloseHandle(thread_params.window_created);
2610     CloseHandle(thread);
2611
2612     DestroyWindow(device_window);
2613     DestroyWindow(focus_window);
2614     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2615 }
2616
2617 static void test_wndproc_windowed(void)
2618 {
2619     struct wndproc_thread_param thread_params;
2620     IDirect3DDevice9 *device;
2621     WNDCLASSA wc = {0};
2622     IDirect3D9 *d3d9;
2623     HANDLE thread;
2624     LONG_PTR proc;
2625     HRESULT hr;
2626     ULONG ref;
2627     DWORD res, tid;
2628     HWND tmp;
2629
2630     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2631     {
2632         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2633         return;
2634     }
2635
2636     wc.lpfnWndProc = test_proc;
2637     wc.lpszClassName = "d3d9_test_wndproc_wc";
2638     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2639
2640     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2641     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2642     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2643     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2644
2645     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2646             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2647     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2648             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2649     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2650     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2651
2652     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2653     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2654
2655     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2656     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2657             (LONG_PTR)test_proc, proc);
2658     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2659     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2660             (LONG_PTR)test_proc, proc);
2661
2662     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2663             device_window, focus_window, thread_params.dummy_window);
2664
2665     tmp = GetFocus();
2666     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2667     if (thread_params.running_in_foreground)
2668     {
2669         tmp = GetForegroundWindow();
2670         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2671                 thread_params.dummy_window, tmp);
2672     }
2673     else
2674         skip("Not running in foreground, skip foreground window test\n");
2675
2676     filter_messages = focus_window;
2677
2678     device = create_device(d3d9, device_window, focus_window, TRUE);
2679     if (!device)
2680     {
2681         skip("Failed to create a D3D device, skipping tests.\n");
2682         goto done;
2683     }
2684
2685     tmp = GetFocus();
2686     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2687     tmp = GetForegroundWindow();
2688     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2689             thread_params.dummy_window, tmp);
2690
2691     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2692     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2693             (LONG_PTR)test_proc, proc);
2694
2695     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2696     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2697             (LONG_PTR)test_proc, proc);
2698
2699     filter_messages = NULL;
2700
2701     hr = reset_device(device, device_window, FALSE);
2702     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2703
2704     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2705     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2706             (LONG_PTR)test_proc, proc);
2707
2708     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2709     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2710             (LONG_PTR)test_proc, proc);
2711
2712     hr = reset_device(device, device_window, TRUE);
2713     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2714
2715     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2716     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2717             (LONG_PTR)test_proc, proc);
2718
2719     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2720     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2721             (LONG_PTR)test_proc, proc);
2722
2723     filter_messages = focus_window;
2724
2725     ref = IDirect3DDevice9_Release(device);
2726     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2727
2728     filter_messages = device_window;
2729
2730     device = create_device(d3d9, focus_window, focus_window, TRUE);
2731     if (!device)
2732     {
2733         skip("Failed to create a D3D device, skipping tests.\n");
2734         goto done;
2735     }
2736
2737     filter_messages = NULL;
2738
2739     hr = reset_device(device, focus_window, FALSE);
2740     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2741
2742     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2743     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2744             (LONG_PTR)test_proc, proc);
2745
2746     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2747     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2748             (LONG_PTR)test_proc, proc);
2749
2750     hr = reset_device(device, focus_window, TRUE);
2751     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2752
2753     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2754     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2755             (LONG_PTR)test_proc, proc);
2756
2757     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2758     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2759             (LONG_PTR)test_proc, proc);
2760
2761     filter_messages = device_window;
2762
2763     ref = IDirect3DDevice9_Release(device);
2764     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2765
2766     device = create_device(d3d9, device_window, focus_window, TRUE);
2767     if (!device)
2768     {
2769         skip("Failed to create a D3D device, skipping tests.\n");
2770         goto done;
2771     }
2772
2773     filter_messages = NULL;
2774
2775     hr = reset_device(device, device_window, FALSE);
2776     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2777
2778     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2779     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2780             (LONG_PTR)test_proc, proc);
2781
2782     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2783     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2784             (LONG_PTR)test_proc, proc);
2785
2786     hr = reset_device(device, device_window, TRUE);
2787     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2788
2789     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2790     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2791             (LONG_PTR)test_proc, proc);
2792
2793     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2794     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2795             (LONG_PTR)test_proc, proc);
2796
2797     filter_messages = device_window;
2798
2799     ref = IDirect3DDevice9_Release(device);
2800     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2801
2802 done:
2803     filter_messages = NULL;
2804     IDirect3D9_Release(d3d9);
2805
2806     SetEvent(thread_params.test_finished);
2807     WaitForSingleObject(thread, INFINITE);
2808     CloseHandle(thread_params.test_finished);
2809     CloseHandle(thread_params.window_created);
2810     CloseHandle(thread);
2811
2812     DestroyWindow(device_window);
2813     DestroyWindow(focus_window);
2814     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2815 }
2816
2817 static inline void set_fpu_cw(WORD cw)
2818 {
2819 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2820     __asm__ volatile ("fnclex");
2821     __asm__ volatile ("fldcw %0" : : "m" (cw));
2822 #endif
2823 }
2824
2825 static inline WORD get_fpu_cw(void)
2826 {
2827     WORD cw = 0;
2828 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2829     __asm__ volatile ("fnstcw %0" : "=m" (cw));
2830 #endif
2831     return cw;
2832 }
2833
2834 static void test_fpu_setup(void)
2835 {
2836 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2837     D3DPRESENT_PARAMETERS present_parameters;
2838     IDirect3DDevice9 *device;
2839     HWND window = NULL;
2840     IDirect3D9 *d3d9;
2841     HRESULT hr;
2842     WORD cw;
2843
2844     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2845     ok(!!d3d9, "Failed to create a d3d9 object.\n");
2846     if (!d3d9) return;
2847
2848     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2849     ok(!!window, "Failed to create a window.\n");
2850     if (!window) goto done;
2851
2852     memset(&present_parameters, 0, sizeof(present_parameters));
2853     present_parameters.Windowed = TRUE;
2854     present_parameters.hDeviceWindow = window;
2855     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2856
2857     set_fpu_cw(0xf60);
2858     cw = get_fpu_cw();
2859     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2860
2861     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2862             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
2863     if (FAILED(hr))
2864     {
2865         skip("Failed to create a device, hr %#x.\n", hr);
2866         set_fpu_cw(0x37f);
2867         goto done;
2868     }
2869
2870     cw = get_fpu_cw();
2871     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2872
2873     IDirect3DDevice9_Release(device);
2874
2875     cw = get_fpu_cw();
2876     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2877     set_fpu_cw(0xf60);
2878     cw = get_fpu_cw();
2879     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2880
2881     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2882             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
2883     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
2884
2885     cw = get_fpu_cw();
2886     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2887     set_fpu_cw(0x37f);
2888
2889     IDirect3DDevice9_Release(device);
2890
2891 done:
2892     if (window) DestroyWindow(window);
2893     if (d3d9) IDirect3D9_Release(d3d9);
2894 #endif
2895 }
2896
2897 static void test_window_style(void)
2898 {
2899     RECT focus_rect, fullscreen_rect, r;
2900     LONG device_style, device_exstyle;
2901     LONG focus_style, focus_exstyle;
2902     LONG style, expected_style;
2903     IDirect3DDevice9 *device;
2904     IDirect3D9 *d3d9;
2905     ULONG ref;
2906
2907
2908     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2909     {
2910         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2911         return;
2912     }
2913
2914     focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2915             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2916     device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2917             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2918
2919     device_style = GetWindowLongA(device_window, GWL_STYLE);
2920     device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
2921     focus_style = GetWindowLongA(focus_window, GWL_STYLE);
2922     focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
2923
2924     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
2925     GetWindowRect(focus_window, &focus_rect);
2926
2927     device = create_device(d3d9, device_window, focus_window, FALSE);
2928     if (!device)
2929     {
2930         skip("Failed to create a D3D device, skipping tests.\n");
2931         goto done;
2932     }
2933
2934     style = GetWindowLongA(device_window, GWL_STYLE);
2935     expected_style = device_style | WS_VISIBLE;
2936     todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
2937             expected_style, style);
2938     style = GetWindowLongA(device_window, GWL_EXSTYLE);
2939     expected_style = device_exstyle | WS_EX_TOPMOST;
2940     todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
2941             expected_style, style);
2942
2943     style = GetWindowLongA(focus_window, GWL_STYLE);
2944     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
2945             focus_style, style);
2946     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
2947     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
2948             focus_exstyle, style);
2949
2950     GetWindowRect(device_window, &r);
2951     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2952             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2953             r.left, r.top, r.right, r.bottom);
2954     GetClientRect(device_window, &r);
2955     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2956     GetWindowRect(focus_window, &r);
2957     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2958             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
2959             r.left, r.top, r.right, r.bottom);
2960
2961     ref = IDirect3DDevice9_Release(device);
2962     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2963
2964 done:
2965     IDirect3D9_Release(d3d9);
2966
2967     DestroyWindow(device_window);
2968     DestroyWindow(focus_window);
2969 }
2970
2971 START_TEST(device)
2972 {
2973     HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
2974     WNDCLASS wc = {0};
2975
2976     wc.lpfnWndProc = DefWindowProc;
2977     wc.lpszClassName = "d3d9_test_wc";
2978     RegisterClass(&wc);
2979
2980     if (!d3d9_handle)
2981     {
2982         skip("Could not load d3d9.dll\n");
2983         goto out;
2984     }
2985
2986     pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
2987     ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
2988     if (pDirect3DCreate9)
2989     {
2990         IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2991         if(!d3d9)
2992         {
2993             skip("could not create D3D9 object\n");
2994             goto out;
2995         }
2996         IDirect3D9_Release(d3d9);
2997
2998         screen_width = GetSystemMetrics(SM_CXSCREEN);
2999         screen_height = GetSystemMetrics(SM_CYSCREEN);
3000
3001         test_fpu_setup();
3002         test_multi_device();
3003         test_display_formats();
3004         test_display_modes();
3005         test_swapchain();
3006         test_refcount();
3007         test_mipmap_levels();
3008         test_checkdevicemultisampletype();
3009         test_cursor();
3010         test_reset();
3011         test_scene();
3012         test_limits();
3013         test_depthstenciltest();
3014         test_draw_indexed();
3015         test_null_stream();
3016         test_lights();
3017         test_set_stream_source();
3018         test_scissor_size();
3019         test_wndproc();
3020         test_wndproc_windowed();
3021         test_window_style();
3022     }
3023
3024 out:
3025     UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));
3026 }