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