crypt32: Free the encoded msg (Coverity).
[wine] / dlls / d3d9 / tests / device.c
1 /*
2  * Copyright (C) 2006 Vitaliy Margolen
3  * Copyright (C) 2006 Chris Robinson
4  * Copyright 2006-2007, 2010 Stefan Dösinger for CodeWeavers
5  * Copyright 2006, 2007 Henri Verbeet
6  * Copyright 2013 Henri Verbeet for CodeWeavers
7  * Copyright (C) 2008 Rico Schüller
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #define COBJMACROS
25 #include <windowsx.h>
26 #include <d3d9.h>
27 #include "wine/test.h"
28
29 static INT screen_width;
30 static INT screen_height;
31
32 static IDirect3D9 *(WINAPI *pDirect3DCreate9)(UINT);
33
34 static int get_refcount(IUnknown *object)
35 {
36     IUnknown_AddRef( object );
37     return IUnknown_Release( object );
38 }
39
40 /* try to make sure pending X events have been processed before continuing */
41 static void flush_events(void)
42 {
43     MSG msg;
44     int diff = 200;
45     int min_timeout = 100;
46     DWORD time = GetTickCount() + diff;
47
48     while (diff > 0)
49     {
50         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
51         while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
52         diff = time - GetTickCount();
53     }
54 }
55
56 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND device_window, HWND focus_window, BOOL windowed)
57 {
58     D3DPRESENT_PARAMETERS present_parameters = {0};
59     IDirect3DDevice9 *device;
60
61     present_parameters.Windowed = windowed;
62     present_parameters.hDeviceWindow = device_window;
63     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
64     present_parameters.BackBufferWidth = screen_width;
65     present_parameters.BackBufferHeight = screen_height;
66     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
67     present_parameters.EnableAutoDepthStencil = TRUE;
68     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
69
70     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
71             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
72
73     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
74     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
75             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
76
77     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
78             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
79
80     return NULL;
81 }
82
83 static HRESULT reset_device(IDirect3DDevice9 *device, HWND device_window, BOOL windowed)
84 {
85     D3DPRESENT_PARAMETERS present_parameters = {0};
86
87     present_parameters.Windowed = windowed;
88     present_parameters.hDeviceWindow = device_window;
89     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
90     present_parameters.BackBufferWidth = screen_width;
91     present_parameters.BackBufferHeight = screen_height;
92     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
93     present_parameters.EnableAutoDepthStencil = TRUE;
94     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
95
96     return IDirect3DDevice9_Reset(device, &present_parameters);
97 }
98
99 #define CHECK_CALL(r,c,d,rc) \
100     if (SUCCEEDED(r)) {\
101         int tmp1 = get_refcount( (IUnknown *)d ); \
102         int rc_new = rc; \
103         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
104     } else {\
105         trace("%s failed: %08x\n", c, r); \
106     }
107
108 #define CHECK_RELEASE(obj,d,rc) \
109     if (obj) { \
110         int tmp1, rc_new = rc; \
111         IUnknown_Release( (IUnknown*)obj ); \
112         tmp1 = get_refcount( (IUnknown *)d ); \
113         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
114     }
115
116 #define CHECK_REFCOUNT(obj,rc) \
117     { \
118         int rc_new = rc; \
119         int count = get_refcount( (IUnknown *)obj ); \
120         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
121     }
122
123 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
124     { \
125         int rc_new = rc; \
126         int count = IUnknown_Release( (IUnknown *)obj ); \
127         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
128     }
129
130 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
131     { \
132         int rc_new = rc; \
133         int count = IUnknown_AddRef( (IUnknown *)obj ); \
134         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
135     }
136
137 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
138     { \
139         void *container_ptr = (void *)0x1337c0d3; \
140         hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
141         ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
142             "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
143         if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
144     }
145
146 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
147 {
148     IDirect3DBaseTexture9* texture = NULL;
149     HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
150             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
151
152     if (SUCCEEDED(hr)) {
153         DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
154         ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
155     } else
156         trace("CreateTexture failed: %08x\n", hr);
157
158     if (texture) IDirect3DBaseTexture9_Release( texture );
159 }
160
161 static void test_mipmap_levels(void)
162 {
163
164     HRESULT               hr;
165     HWND                  hwnd = NULL;
166
167     IDirect3D9            *pD3d = NULL;
168     IDirect3DDevice9      *pDevice = NULL;
169     D3DPRESENT_PARAMETERS d3dpp;
170     D3DDISPLAYMODE        d3ddm;
171
172     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
173     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
174     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
175     ok(hwnd != NULL, "Failed to create window\n");
176     if (!pD3d || !hwnd) goto cleanup;
177
178     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
179     ZeroMemory( &d3dpp, sizeof(d3dpp) );
180     d3dpp.Windowed         = TRUE;
181     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
182     d3dpp.BackBufferFormat = d3ddm.Format;
183
184     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
185                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
186     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
187     if (FAILED(hr)) {
188         skip("failed to create a d3d device\n");
189         goto cleanup;
190     }
191
192     check_mipmap_levels(pDevice, 32, 32, 6);
193     check_mipmap_levels(pDevice, 256, 1, 9);
194     check_mipmap_levels(pDevice, 1, 256, 9);
195     check_mipmap_levels(pDevice, 1, 1, 1);
196
197 cleanup:
198     if (pDevice)
199     {
200         UINT refcount = IDirect3DDevice9_Release( pDevice );
201         ok(!refcount, "Device has %u references left.\n", refcount);
202     }
203     if (pD3d) IDirect3D9_Release( pD3d );
204     DestroyWindow( hwnd );
205 }
206
207 static void test_checkdevicemultisampletype(void)
208 {
209
210     HRESULT               hr;
211     HWND                  hwnd = NULL;
212
213     IDirect3D9            *pD3d = NULL;
214     IDirect3DDevice9      *pDevice = NULL;
215     D3DPRESENT_PARAMETERS d3dpp;
216     D3DDISPLAYMODE        d3ddm;
217     DWORD                 qualityLevels;
218
219     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
220     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
221     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
222     ok(hwnd != NULL, "Failed to create window\n");
223     if (!pD3d || !hwnd) goto cleanup;
224
225     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
226     ZeroMemory( &d3dpp, sizeof(d3dpp) );
227     d3dpp.Windowed         = TRUE;
228     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
229     d3dpp.BackBufferFormat = d3ddm.Format;
230
231     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
232                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
233     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
234     if (FAILED(hr)) {
235         skip("failed to create a d3d device\n");
236         goto cleanup;
237     }
238
239     qualityLevels = 0;
240
241     hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE,
242     D3DMULTISAMPLE_NONE, &qualityLevels);
243     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
244     if(hr == D3DERR_NOTAVAILABLE)
245     {
246         skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
247         goto cleanup;
248     }
249     ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
250
251     hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, FALSE,
252     D3DMULTISAMPLE_NONE, &qualityLevels);
253     ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
254     ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
255
256 cleanup:
257     if (pDevice)
258     {
259         UINT refcount = IDirect3DDevice9_Release( pDevice );
260         ok(!refcount, "Device has %u references left.\n", refcount);
261     }
262     if (pD3d) IDirect3D9_Release( pD3d );
263     DestroyWindow( hwnd );
264 }
265
266 static void test_swapchain(void)
267 {
268     HRESULT                      hr;
269     HWND                         hwnd               = NULL;
270     IDirect3D9                  *pD3d               = NULL;
271     IDirect3DDevice9            *pDevice            = NULL;
272     IDirect3DSwapChain9         *swapchain0         = NULL;
273     IDirect3DSwapChain9         *swapchain1         = NULL;
274     IDirect3DSwapChain9         *swapchain2         = NULL;
275     IDirect3DSwapChain9         *swapchain3         = NULL;
276     IDirect3DSwapChain9         *swapchainX         = NULL;
277     IDirect3DSurface9           *backbuffer         = NULL;
278     D3DPRESENT_PARAMETERS        d3dpp;
279     D3DDISPLAYMODE               d3ddm;
280
281     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
282     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
283     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
284     ok(hwnd != NULL, "Failed to create window\n");
285     if (!pD3d || !hwnd) goto cleanup;
286
287     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
288     ZeroMemory( &d3dpp, sizeof(d3dpp) );
289     d3dpp.Windowed         = TRUE;
290     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
291     d3dpp.BackBufferFormat = d3ddm.Format;
292     d3dpp.BackBufferCount  = 0;
293
294     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
295                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
296     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
297        "Failed to create IDirect3D9Device (%08x)\n", hr);
298     if (FAILED(hr)) goto cleanup;
299
300     /* Check if the back buffer count was modified */
301     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
302
303     /* Get the implicit swapchain */
304     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &swapchain0);
305     ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
306     if(swapchain0) IDirect3DSwapChain9_Release(swapchain0);
307
308     /* Check if there is a back buffer */
309     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
310     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
311     ok(backbuffer != NULL, "The back buffer is NULL\n");
312     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
313
314     /* Try to get a nonexistent swapchain */
315     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
316     ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
317     ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
318     if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
319
320     /* Create a bunch of swapchains */
321     d3dpp.BackBufferCount = 0;
322     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
323     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
324     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
325
326     d3dpp.BackBufferCount  = 1;
327     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
328     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
329
330     d3dpp.BackBufferCount  = 2;
331     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
332     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
333     if(SUCCEEDED(hr)) {
334         /* Swapchain 3, created with backbuffercount 2 */
335         backbuffer = (void *) 0xdeadbeef;
336         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
337         ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
338         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
339         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
340
341         backbuffer = (void *) 0xdeadbeef;
342         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
343         ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
344         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
345         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
346
347         backbuffer = (void *) 0xdeadbeef;
348         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
349         ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
350         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
351         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
352
353         backbuffer = (void *) 0xdeadbeef;
354         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
355         ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
356         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
357         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
358     }
359
360     /* Check the back buffers of the swapchains */
361     /* Swapchain 1, created with backbuffercount 0 */
362     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
363     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
364     ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
365     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
366
367     backbuffer = (void *) 0xdeadbeef;
368     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
369     ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
370     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
371     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
372
373     /* Swapchain 2 - created with backbuffercount 1 */
374     backbuffer = (void *) 0xdeadbeef;
375     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
376     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
377     ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
378     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
379
380     backbuffer = (void *) 0xdeadbeef;
381     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
382     ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
383     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
384     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
385
386     backbuffer = (void *) 0xdeadbeef;
387     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
388     ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
389     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
390     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
391
392     /* Try getSwapChain on a manually created swapchain
393      * it should fail, apparently GetSwapChain only returns implicit swapchains
394      */
395     swapchainX = (void *) 0xdeadbeef;
396     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
397     ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
398     ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
399     if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
400
401 cleanup:
402     if(swapchain1) IDirect3DSwapChain9_Release(swapchain1);
403     if(swapchain2) IDirect3DSwapChain9_Release(swapchain2);
404     if(swapchain3) IDirect3DSwapChain9_Release(swapchain3);
405     if (pDevice)
406     {
407         UINT refcount = IDirect3DDevice9_Release(pDevice);
408         ok(!refcount, "Device has %u references left.\n", refcount);
409     }
410     if (pD3d) IDirect3D9_Release(pD3d);
411     DestroyWindow( hwnd );
412 }
413
414 /* Shared between two functions */
415 static const DWORD simple_vs[] = {0xFFFE0101,       /* vs_1_1               */
416     0x0000001F, 0x80000000, 0x900F0000,             /* dcl_position0 v0     */
417     0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0   */
418     0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1   */
419     0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2   */
420     0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3   */
421     0x0000FFFF};                                    /* END                  */
422
423 static void test_refcount(void)
424 {
425     HRESULT                      hr;
426     HWND                         hwnd               = NULL;
427     IDirect3D9                  *pD3d               = NULL;
428     IDirect3D9                  *pD3d2              = NULL;
429     IDirect3DDevice9            *pDevice            = NULL;
430     IDirect3DVertexBuffer9      *pVertexBuffer      = NULL;
431     IDirect3DIndexBuffer9       *pIndexBuffer       = NULL;
432     IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
433     IDirect3DVertexShader9      *pVertexShader      = NULL;
434     IDirect3DPixelShader9       *pPixelShader       = NULL;
435     IDirect3DCubeTexture9       *pCubeTexture       = NULL;
436     IDirect3DTexture9           *pTexture           = NULL;
437     IDirect3DVolumeTexture9     *pVolumeTexture     = NULL;
438     IDirect3DVolume9            *pVolumeLevel       = NULL;
439     IDirect3DSurface9           *pStencilSurface    = NULL;
440     IDirect3DSurface9           *pOffscreenSurface  = NULL;
441     IDirect3DSurface9           *pRenderTarget      = NULL;
442     IDirect3DSurface9           *pRenderTarget2     = NULL;
443     IDirect3DSurface9           *pRenderTarget3     = NULL;
444     IDirect3DSurface9           *pTextureLevel      = NULL;
445     IDirect3DSurface9           *pBackBuffer        = NULL;
446     IDirect3DStateBlock9        *pStateBlock        = NULL;
447     IDirect3DStateBlock9        *pStateBlock1       = NULL;
448     IDirect3DSwapChain9         *pSwapChain         = NULL;
449     IDirect3DQuery9             *pQuery             = NULL;
450     D3DPRESENT_PARAMETERS        d3dpp;
451     D3DDISPLAYMODE               d3ddm;
452     int                          refcount = 0, tmp;
453
454     D3DVERTEXELEMENT9 decl[] =
455     {
456         D3DDECL_END()
457     };
458     static DWORD simple_ps[] = {0xFFFF0101,                                     /* ps_1_1                       */
459         0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
460         0x00000042, 0xB00F0000,                                                 /* tex t0                       */
461         0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000,                         /* dp3 r0, c1, c0               */
462         0x00000005, 0x800F0000, 0x90E40000, 0x80E40000,                         /* mul r0, v0, r0               */
463         0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000,                         /* mul r0, t0, r0               */
464         0x0000FFFF};                                                            /* END                          */
465
466
467     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
468     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
469     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
470     ok(hwnd != NULL, "Failed to create window\n");
471     if (!pD3d || !hwnd) goto cleanup;
472
473     CHECK_REFCOUNT( pD3d, 1 );
474
475     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
476     ZeroMemory( &d3dpp, sizeof(d3dpp) );
477     d3dpp.Windowed         = TRUE;
478     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
479     d3dpp.BackBufferFormat = d3ddm.Format;
480     d3dpp.EnableAutoDepthStencil = TRUE;
481     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
482
483     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
484                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
485     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
486        "Failed to create IDirect3D9Device (%08x)\n", hr);
487     if (FAILED(hr)) goto cleanup;
488
489     refcount = get_refcount( (IUnknown *)pDevice );
490     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
491
492     CHECK_REFCOUNT( pD3d, 2 );
493
494     hr = IDirect3DDevice9_GetDirect3D(pDevice, &pD3d2);
495     CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
496
497     ok(pD3d2 == pD3d, "Expected IDirect3D9 pointers to be equal\n");
498     CHECK_REFCOUNT( pD3d, 3 );
499     CHECK_RELEASE_REFCOUNT( pD3d, 2 );
500
501     /**
502      * Check refcount of implicit surfaces and implicit swapchain. Findings:
503      *   - the container is the device OR swapchain
504      *   - they hold a reference to the device
505      *   - they are created with a refcount of 0 (Get/Release returns original refcount)
506      *   - they are not freed if refcount reaches 0.
507      *   - the refcount is not forwarded to the container.
508      */
509     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
510     CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
511     if (pSwapChain)
512     {
513         CHECK_REFCOUNT( pSwapChain, 1);
514
515         hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
516         CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
517         CHECK_REFCOUNT( pSwapChain, 1);
518         if(pRenderTarget)
519         {
520             CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
521             CHECK_REFCOUNT( pRenderTarget, 1);
522
523             CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
524             CHECK_REFCOUNT(pDevice, refcount);
525             CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
526             CHECK_REFCOUNT(pDevice, refcount);
527
528             hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
529             CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
530             CHECK_REFCOUNT( pRenderTarget, 2);
531             CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
532             CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
533             CHECK_REFCOUNT( pDevice, --refcount);
534
535             /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
536             CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
537             CHECK_REFCOUNT(pDevice, ++refcount);
538             CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
539             CHECK_REFCOUNT(pDevice, --refcount);
540         }
541
542         /* Render target and back buffer are identical. */
543         hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
544         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
545         if(pBackBuffer)
546         {
547             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
548             ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
549             pRenderTarget, pBackBuffer);
550             pBackBuffer = NULL;
551         }
552         CHECK_REFCOUNT( pDevice, --refcount);
553
554         hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
555         CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
556         CHECK_REFCOUNT( pSwapChain, 1);
557         if(pStencilSurface)
558         {
559             CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
560             CHECK_REFCOUNT( pStencilSurface, 1);
561
562             CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
563             CHECK_REFCOUNT(pDevice, refcount);
564             CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
565             CHECK_REFCOUNT(pDevice, refcount);
566
567             CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
568             CHECK_REFCOUNT( pDevice, --refcount);
569
570             /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
571             CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
572             CHECK_REFCOUNT(pDevice, ++refcount);
573             CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
574             CHECK_REFCOUNT(pDevice, --refcount);
575             pStencilSurface = NULL;
576         }
577
578         CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
579         CHECK_REFCOUNT( pDevice, --refcount);
580
581         /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
582         CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
583         CHECK_REFCOUNT(pDevice, ++refcount);
584         CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
585         CHECK_REFCOUNT(pDevice, --refcount);
586         pSwapChain = NULL;
587     }
588
589     /* Buffers */
590     hr = IDirect3DDevice9_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL );
591     CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
592     if(pIndexBuffer)
593     {
594         tmp = get_refcount( (IUnknown *)pIndexBuffer );
595
596         hr = IDirect3DDevice9_SetIndices(pDevice, pIndexBuffer);
597         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
598         hr = IDirect3DDevice9_SetIndices(pDevice, NULL);
599         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
600     }
601
602     hr = IDirect3DDevice9_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
603     CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
604     if(pVertexBuffer)
605     {
606         IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
607         UINT offset = ~0;
608         UINT stride = ~0;
609
610         tmp = get_refcount( (IUnknown *)pVertexBuffer );
611
612         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, pVertexBuffer, 0, 3 * sizeof(float));
613         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
614         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, NULL, 0, 0);
615         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
616
617         hr = IDirect3DDevice9_GetStreamSource(pDevice, 0, &pVBuf, &offset, &stride);
618         ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
619         ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
620         ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
621         ok(offset==0, "offset not 0 (got %u)!\n", offset);
622     }
623     /* Shaders */
624     hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, decl, &pVertexDeclaration );
625     CHECK_CALL( hr, "CreateVertexDeclaration", pDevice, ++refcount );
626     hr = IDirect3DDevice9_CreateVertexShader( pDevice, simple_vs, &pVertexShader );
627     CHECK_CALL( hr, "CreateVertexShader", pDevice, ++refcount );
628     hr = IDirect3DDevice9_CreatePixelShader( pDevice, simple_ps, &pPixelShader );
629     CHECK_CALL( hr, "CreatePixelShader", pDevice, ++refcount );
630     /* Textures */
631     hr = IDirect3DDevice9_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL );
632     CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
633     if (pTexture)
634     {
635         tmp = get_refcount( (IUnknown *)pTexture );
636
637         /* SetTexture should not increase refcounts */
638         hr = IDirect3DDevice9_SetTexture(pDevice, 0, (IDirect3DBaseTexture9 *) pTexture);
639         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
640         hr = IDirect3DDevice9_SetTexture(pDevice, 0, NULL);
641         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
642
643         /* This should not increment device refcount */
644         hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
645         CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
646         /* But should increment texture's refcount */
647         CHECK_REFCOUNT( pTexture, tmp+1 );
648         /* Because the texture and surface refcount are identical */
649         if (pTextureLevel)
650         {
651             CHECK_REFCOUNT        ( pTextureLevel, tmp+1 );
652             CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
653             CHECK_REFCOUNT        ( pTexture     , tmp+2 );
654             CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
655             CHECK_REFCOUNT        ( pTexture     , tmp+1 );
656             CHECK_RELEASE_REFCOUNT( pTexture     , tmp   );
657             CHECK_REFCOUNT        ( pTextureLevel, tmp   );
658         }
659     }
660     hr = IDirect3DDevice9_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL );
661     CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
662     hr = IDirect3DDevice9_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL );
663     CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
664     if (pVolumeTexture)
665     {
666         tmp = get_refcount( (IUnknown *)pVolumeTexture );
667
668         /* This should not increment device refcount */
669         hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
670         CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
671         /* But should increment volume texture's refcount */
672         CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
673         /* Because the volume texture and volume refcount are identical */
674         if (pVolumeLevel)
675         {
676             CHECK_REFCOUNT        ( pVolumeLevel  , tmp+1 );
677             CHECK_ADDREF_REFCOUNT ( pVolumeLevel  , tmp+2 );
678             CHECK_REFCOUNT        ( pVolumeTexture, tmp+2 );
679             CHECK_RELEASE_REFCOUNT( pVolumeLevel  , tmp+1 );
680             CHECK_REFCOUNT        ( pVolumeTexture, tmp+1 );
681             CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp   );
682             CHECK_REFCOUNT        ( pVolumeLevel  , tmp   );
683         }
684     }
685     /* Surfaces */
686     hr = IDirect3DDevice9_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL );
687     CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
688     CHECK_REFCOUNT( pStencilSurface, 1 );
689     hr = IDirect3DDevice9_CreateOffscreenPlainSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL );
690     CHECK_CALL( hr, "CreateOffscreenPlainSurface", pDevice, ++refcount );
691     CHECK_REFCOUNT( pOffscreenSurface, 1 );
692     hr = IDirect3DDevice9_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL );
693     CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
694     CHECK_REFCOUNT( pRenderTarget3, 1 );
695     /* Misc */
696     hr = IDirect3DDevice9_CreateStateBlock( pDevice, D3DSBT_ALL, &pStateBlock );
697     CHECK_CALL( hr, "CreateStateBlock", pDevice, ++refcount );
698     hr = IDirect3DDevice9_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
699     CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
700     if(pSwapChain)
701     {
702         /* check implicit back buffer */
703         hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
704         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
705         CHECK_REFCOUNT( pSwapChain, 1);
706         if(pBackBuffer)
707         {
708             CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
709             CHECK_REFCOUNT( pBackBuffer, 1);
710             CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
711             CHECK_REFCOUNT( pDevice, --refcount);
712
713             /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
714             CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
715             CHECK_REFCOUNT(pDevice, ++refcount);
716             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
717             CHECK_REFCOUNT(pDevice, --refcount);
718             pBackBuffer = NULL;
719         }
720         CHECK_REFCOUNT( pSwapChain, 1);
721     }
722     hr = IDirect3DDevice9_CreateQuery( pDevice, D3DQUERYTYPE_EVENT, &pQuery );
723     CHECK_CALL( hr, "CreateQuery", pDevice, ++refcount );
724
725     hr = IDirect3DDevice9_BeginStateBlock( pDevice );
726     CHECK_CALL( hr, "BeginStateBlock", pDevice, refcount );
727     hr = IDirect3DDevice9_EndStateBlock( pDevice, &pStateBlock1 );
728     CHECK_CALL( hr, "EndStateBlock", pDevice, ++refcount );
729
730     /* The implicit render target is not freed if refcount reaches 0.
731      * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
732     hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget2);
733     CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
734     if(pRenderTarget2)
735     {
736         CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
737         ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
738            pRenderTarget, pRenderTarget2);
739         CHECK_REFCOUNT( pDevice, --refcount);
740         pRenderTarget2 = NULL;
741     }
742     pRenderTarget = NULL;
743
744 cleanup:
745     CHECK_RELEASE(pDevice,              pDevice, --refcount);
746
747     /* Buffers */
748     CHECK_RELEASE(pVertexBuffer,        pDevice, --refcount);
749     CHECK_RELEASE(pIndexBuffer,         pDevice, --refcount);
750     /* Shaders */
751     CHECK_RELEASE(pVertexDeclaration,   pDevice, --refcount);
752     CHECK_RELEASE(pVertexShader,        pDevice, --refcount);
753     CHECK_RELEASE(pPixelShader,         pDevice, --refcount);
754     /* Textures */
755     CHECK_RELEASE(pTextureLevel,        pDevice, --refcount);
756     CHECK_RELEASE(pCubeTexture,         pDevice, --refcount);
757     CHECK_RELEASE(pVolumeTexture,       pDevice, --refcount);
758     /* Surfaces */
759     CHECK_RELEASE(pStencilSurface,      pDevice, --refcount);
760     CHECK_RELEASE(pOffscreenSurface,    pDevice, --refcount);
761     CHECK_RELEASE(pRenderTarget3,       pDevice, --refcount);
762     /* Misc */
763     CHECK_RELEASE(pStateBlock,          pDevice, --refcount);
764     CHECK_RELEASE(pSwapChain,           pDevice, --refcount);
765     CHECK_RELEASE(pQuery,               pDevice, --refcount);
766     /* This will destroy device - cannot check the refcount here */
767     if (pStateBlock1)         CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
768
769     if (pD3d)                 CHECK_RELEASE_REFCOUNT( pD3d, 0);
770
771     DestroyWindow( hwnd );
772 }
773
774 static void test_cursor(void)
775 {
776     HRESULT                      hr;
777     HWND                         hwnd               = NULL;
778     IDirect3D9                  *pD3d               = NULL;
779     IDirect3DDevice9            *pDevice            = NULL;
780     D3DPRESENT_PARAMETERS        d3dpp;
781     D3DDISPLAYMODE               d3ddm;
782     CURSORINFO                   info;
783     IDirect3DSurface9 *cursor = NULL;
784     HCURSOR cur;
785
786     memset(&info, 0, sizeof(info));
787     info.cbSize = sizeof(info);
788     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
789     cur = info.hCursor;
790
791     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
792     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
793     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
794     ok(hwnd != NULL, "Failed to create window\n");
795     if (!pD3d || !hwnd) goto cleanup;
796
797     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
798     ZeroMemory( &d3dpp, sizeof(d3dpp) );
799     d3dpp.Windowed         = TRUE;
800     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
801     d3dpp.BackBufferFormat = d3ddm.Format;
802
803     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
804                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
805     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
806        "Failed to create IDirect3D9Device (%08x)\n", hr);
807     if (FAILED(hr)) goto cleanup;
808
809     IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, 0);
810     ok(cursor != NULL, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
811
812     /* Initially hidden */
813     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
814     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
815
816     /* Not enabled without a surface*/
817     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
818     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
819
820     /* Fails */
821     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, NULL);
822     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
823
824     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, cursor);
825     ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
826
827     IDirect3DSurface9_Release(cursor);
828
829     memset(&info, 0, sizeof(info));
830     info.cbSize = sizeof(info);
831     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
832     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
833     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
834
835     /* Still hidden */
836     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
837     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
838
839     /* Enabled now*/
840     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
841     ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
842
843     /* GDI cursor unchanged */
844     memset(&info, 0, sizeof(info));
845     info.cbSize = sizeof(info);
846     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
847     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
848     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
849
850 cleanup:
851     if (pDevice)
852     {
853         UINT refcount = IDirect3DDevice9_Release(pDevice);
854         ok(!refcount, "Device has %u references left.\n", refcount);
855     }
856     if (pD3d) IDirect3D9_Release(pD3d);
857     DestroyWindow( hwnd );
858 }
859
860 static void test_reset(void)
861 {
862     HRESULT                      hr;
863     HWND                         hwnd               = NULL;
864     RECT                         winrect;
865     IDirect3D9                  *pD3d               = NULL;
866     D3DPRESENT_PARAMETERS        d3dpp;
867     D3DDISPLAYMODE               d3ddm, d3ddm2;
868     D3DVIEWPORT9                 vp;
869     DWORD                        width, orig_width = GetSystemMetrics(SM_CXSCREEN);
870     DWORD                        height, orig_height = GetSystemMetrics(SM_CYSCREEN);
871     IDirect3DSwapChain9          *pSwapchain;
872     IDirect3DSurface9            *surface;
873     IDirect3DTexture9            *texture;
874     IDirect3DVertexShader9       *shader;
875     UINT                         i, adapter_mode_count;
876     D3DLOCKED_RECT               lockrect;
877     IDirect3DDevice9 *device1 = NULL;
878     IDirect3DDevice9 *device2 = NULL;
879     D3DCAPS9 caps;
880     DWORD value;
881     struct
882     {
883         UINT w;
884         UINT h;
885     } *modes = NULL;
886     UINT mode_count = 0;
887
888     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
889     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
890     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
891     ok(hwnd != NULL, "Failed to create window\n");
892     if (!pD3d || !hwnd) goto cleanup;
893
894     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
895     adapter_mode_count = IDirect3D9_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format);
896     modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
897     for(i = 0; i < adapter_mode_count; ++i)
898     {
899         UINT j;
900         ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
901         hr = IDirect3D9_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
902         ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
903
904         for (j = 0; j < mode_count; ++j)
905         {
906             if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
907                 break;
908         }
909         if (j == mode_count)
910         {
911             modes[j].w = d3ddm2.Width;
912             modes[j].h = d3ddm2.Height;
913             ++mode_count;
914         }
915
916         /* We use them as invalid modes */
917         if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
918            (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
919             skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
920                  d3ddm2.Width, d3ddm2.Height);
921             goto cleanup;
922         }
923     }
924
925     if (mode_count < 2)
926     {
927         skip("Less than 2 modes supported, skipping mode tests\n");
928         goto cleanup;
929     }
930
931     i = 0;
932     if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
933
934     ZeroMemory( &d3dpp, sizeof(d3dpp) );
935     d3dpp.Windowed         = FALSE;
936     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
937     d3dpp.BackBufferWidth  = modes[i].w;
938     d3dpp.BackBufferHeight = modes[i].h;
939     d3dpp.BackBufferFormat = d3ddm.Format;
940     d3dpp.EnableAutoDepthStencil = TRUE;
941     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
942
943     hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
944             hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
945     if (FAILED(hr))
946     {
947         skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
948         goto cleanup;
949     }
950     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
951     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
952
953     hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
954     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
955
956     width = GetSystemMetrics(SM_CXSCREEN);
957     height = GetSystemMetrics(SM_CYSCREEN);
958     ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
959     ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
960
961     hr = IDirect3DDevice9_GetViewport(device1, &vp);
962     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
963     if(SUCCEEDED(hr))
964     {
965         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
966         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
967         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
968         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
969         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
970         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
971     }
972
973     i = 1;
974     vp.X = 10;
975     vp.Y = 20;
976     vp.MinZ = 2;
977     vp.MaxZ = 3;
978     hr = IDirect3DDevice9_SetViewport(device1, &vp);
979     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
980
981     hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
982     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
983     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
984     hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
985     ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
986
987     ZeroMemory( &d3dpp, sizeof(d3dpp) );
988     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
989     d3dpp.Windowed         = FALSE;
990     d3dpp.BackBufferWidth  = modes[i].w;
991     d3dpp.BackBufferHeight = modes[i].h;
992     d3dpp.BackBufferFormat = d3ddm.Format;
993     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
994     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
995     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
996     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
997
998     hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
999     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1000     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1001
1002     ZeroMemory(&vp, sizeof(vp));
1003     hr = IDirect3DDevice9_GetViewport(device1, &vp);
1004     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1005     if(SUCCEEDED(hr))
1006     {
1007         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1008         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1009         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1010         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1011         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1012         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1013     }
1014
1015     width = GetSystemMetrics(SM_CXSCREEN);
1016     height = GetSystemMetrics(SM_CYSCREEN);
1017     ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1018     ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1019
1020     hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1021     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1022     if(SUCCEEDED(hr))
1023     {
1024         ZeroMemory(&d3dpp, sizeof(d3dpp));
1025         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1026         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1027         if(SUCCEEDED(hr))
1028         {
1029             ok(d3dpp.BackBufferWidth == modes[i].w, "Back buffer width is %u, expected %u\n",
1030                     d3dpp.BackBufferWidth, modes[i].w);
1031             ok(d3dpp.BackBufferHeight == modes[i].h, "Back buffer height is %u, expected %u\n",
1032                     d3dpp.BackBufferHeight, modes[i].h);
1033         }
1034         IDirect3DSwapChain9_Release(pSwapchain);
1035     }
1036
1037     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1038     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1039     d3dpp.Windowed         = TRUE;
1040     d3dpp.BackBufferWidth  = 400;
1041     d3dpp.BackBufferHeight = 300;
1042     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1043     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1044     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1045     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1046
1047     width = GetSystemMetrics(SM_CXSCREEN);
1048     height = GetSystemMetrics(SM_CYSCREEN);
1049     ok(width == orig_width, "Screen width is %d\n", width);
1050     ok(height == orig_height, "Screen height is %d\n", height);
1051
1052     ZeroMemory(&vp, sizeof(vp));
1053     hr = IDirect3DDevice9_GetViewport(device1, &vp);
1054     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1055     if(SUCCEEDED(hr))
1056     {
1057         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1058         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1059         ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1060         ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1061         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1062         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1063     }
1064
1065     hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1066     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1067     if(SUCCEEDED(hr))
1068     {
1069         ZeroMemory(&d3dpp, sizeof(d3dpp));
1070         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1071         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1072         if(SUCCEEDED(hr))
1073         {
1074             ok(d3dpp.BackBufferWidth == 400, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1075             ok(d3dpp.BackBufferHeight == 300, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1076         }
1077         IDirect3DSwapChain9_Release(pSwapchain);
1078     }
1079
1080     winrect.left = 0;
1081     winrect.top = 0;
1082     winrect.right = 200;
1083     winrect.bottom = 150;
1084     ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1085     ok(SetWindowPos(hwnd, NULL, 0, 0,
1086                     winrect.right-winrect.left,
1087                     winrect.bottom-winrect.top,
1088                     SWP_NOMOVE|SWP_NOZORDER),
1089        "SetWindowPos failed\n");
1090
1091     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1092     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1093     d3dpp.Windowed         = TRUE;
1094     d3dpp.BackBufferWidth  = 0;
1095     d3dpp.BackBufferHeight = 0;
1096     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1097     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1098     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1099     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1100
1101     ZeroMemory(&vp, sizeof(vp));
1102     hr = IDirect3DDevice9_GetViewport(device1, &vp);
1103     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1104     if(SUCCEEDED(hr))
1105     {
1106         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1107         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1108         todo_wine ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
1109         todo_wine ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
1110         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1111         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1112     }
1113
1114     hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1115     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1116     if(SUCCEEDED(hr))
1117     {
1118         ZeroMemory(&d3dpp, sizeof(d3dpp));
1119         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1120         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1121         if(SUCCEEDED(hr))
1122         {
1123             todo_wine ok(d3dpp.BackBufferWidth == 200, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1124             todo_wine ok(d3dpp.BackBufferHeight == 150, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1125         }
1126         IDirect3DSwapChain9_Release(pSwapchain);
1127     }
1128
1129     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1130     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1131     d3dpp.Windowed         = TRUE;
1132     d3dpp.BackBufferWidth  = 400;
1133     d3dpp.BackBufferHeight = 300;
1134
1135     /* _Reset fails if there is a resource in the default pool */
1136     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1137     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1138     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1139     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1140     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1141     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1142     IDirect3DSurface9_Release(surface);
1143     /* Reset again to get the device out of the lost state */
1144     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1145     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1146     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1147     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1148
1149     if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1150     {
1151         IDirect3DVolumeTexture9 *volume_texture;
1152
1153         hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1154                 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1155         ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1156         hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1157         ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1158         hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1159         ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1160                 hr, D3DERR_DEVICENOTRESET);
1161         IDirect3DVolumeTexture9_Release(volume_texture);
1162         hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1163         ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1164         hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1165         ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1166     }
1167     else
1168     {
1169         skip("Volume textures not supported.\n");
1170     }
1171
1172     /* Scratch, sysmem and managed pools are fine */
1173     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1174     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1175     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1176     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1177     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1178     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1179     IDirect3DSurface9_Release(surface);
1180
1181     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1182             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1183     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1184     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1185     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1186     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1187     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1188     IDirect3DSurface9_Release(surface);
1189
1190     /* The depth stencil should get reset to the auto depth stencil when present. */
1191     hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
1192     ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
1193
1194     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1195     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1196     ok(surface == NULL, "Depth stencil should be NULL\n");
1197
1198     d3dpp.EnableAutoDepthStencil = TRUE;
1199     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1200     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1201     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1202
1203     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1204     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1205     ok(surface != NULL, "Depth stencil should not be NULL\n");
1206     if (surface) IDirect3DSurface9_Release(surface);
1207
1208     d3dpp.EnableAutoDepthStencil = FALSE;
1209     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1210     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1211
1212     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1213     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1214     ok(surface == NULL, "Depth stencil should be NULL\n");
1215
1216     /* Will a sysmem or scratch survive while locked */
1217     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1218             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1219     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1220     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1221     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1222     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1223     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1224     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1225     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1226     IDirect3DSurface9_UnlockRect(surface);
1227     IDirect3DSurface9_Release(surface);
1228
1229     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1230     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1231     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1232     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1233     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1234     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1235     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1236     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1237     IDirect3DSurface9_UnlockRect(surface);
1238     IDirect3DSurface9_Release(surface);
1239
1240     hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
1241     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
1242     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1243     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1244     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1245     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1246     IDirect3DTexture9_Release(texture);
1247
1248     /* A reference held to an implicit surface causes failures as well */
1249     hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1250     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
1251     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1252     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1253     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1254     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1255     IDirect3DSurface9_Release(surface);
1256     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1257     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1258     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1259     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1260
1261     /* Shaders are fine as well */
1262     hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
1263     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
1264     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1265     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1266     IDirect3DVertexShader9_Release(shader);
1267
1268     /* Try setting invalid modes */
1269     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1270     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1271     d3dpp.Windowed         = FALSE;
1272     d3dpp.BackBufferWidth  = 32;
1273     d3dpp.BackBufferHeight = 32;
1274     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1275     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
1276     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1277     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1278
1279     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1280     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1281     d3dpp.Windowed         = FALSE;
1282     d3dpp.BackBufferWidth  = 801;
1283     d3dpp.BackBufferHeight = 600;
1284     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1285     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
1286     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1287     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1288
1289     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1290
1291     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1292     d3dpp.Windowed         = TRUE;
1293     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1294     d3dpp.BackBufferFormat = d3ddm.Format;
1295     d3dpp.EnableAutoDepthStencil = FALSE;
1296     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1297
1298     hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1299             hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1300     if (FAILED(hr))
1301     {
1302         skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
1303         goto cleanup;
1304     }
1305
1306     hr = IDirect3DDevice9_TestCooperativeLevel(device2);
1307     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1308
1309     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1310     d3dpp.Windowed         = TRUE;
1311     d3dpp.BackBufferWidth  = 400;
1312     d3dpp.BackBufferHeight = 300;
1313     d3dpp.EnableAutoDepthStencil = TRUE;
1314     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1315
1316     hr = IDirect3DDevice9_Reset(device2, &d3dpp);
1317     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1318
1319     if (FAILED(hr)) goto cleanup;
1320
1321     hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
1322     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1323     ok(surface != NULL, "Depth stencil should not be NULL\n");
1324     if (surface) IDirect3DSurface9_Release(surface);
1325
1326 cleanup:
1327     HeapFree(GetProcessHeap(), 0, modes);
1328     if (device2)
1329     {
1330         UINT refcount = IDirect3DDevice9_Release(device2);
1331         ok(!refcount, "Device has %u references left.\n", refcount);
1332     }
1333     if (device1)
1334     {
1335         UINT refcount = IDirect3DDevice9_Release(device1);
1336         ok(!refcount, "Device has %u references left.\n", refcount);
1337     }
1338     if (pD3d) IDirect3D9_Release(pD3d);
1339     if (hwnd) DestroyWindow(hwnd);
1340 }
1341
1342 /* Test adapter display modes */
1343 static void test_display_modes(void)
1344 {
1345     D3DDISPLAYMODE dmode;
1346     IDirect3D9 *pD3d;
1347
1348     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1349     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1350     if(!pD3d) return;
1351
1352 #define TEST_FMT(x,r) do { \
1353     HRESULT res = IDirect3D9_EnumAdapterModes(pD3d, 0, (x), 0, &dmode); \
1354     ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
1355 } while(0)
1356
1357     TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
1358     TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
1359     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1360     /* D3DFMT_R5G6B5 */
1361     TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
1362     TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
1363     TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
1364     TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
1365     TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
1366     TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
1367     TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
1368     TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
1369     TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
1370     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1371     TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
1372     TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
1373
1374     TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
1375     TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
1376
1377     TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
1378     TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
1379     TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
1380
1381     TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
1382     TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
1383     TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
1384     TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
1385     TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
1386     TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
1387
1388     TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
1389     TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
1390     TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
1391     TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
1392     TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
1393     TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
1394     TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
1395     TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
1396     TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
1397     TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
1398
1399     TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
1400     TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
1401     TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
1402     TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
1403     TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
1404     TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
1405     TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
1406     TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
1407     TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
1408     TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
1409
1410     TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
1411     TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
1412     TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
1413     TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
1414     /* Floating point formats */
1415     TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
1416     TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
1417     TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
1418
1419     /* IEEE formats */
1420     TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
1421     TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
1422     TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
1423
1424     TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
1425
1426     TEST_FMT(0, D3DERR_INVALIDCALL);
1427
1428     IDirect3D9_Release(pD3d);
1429 }
1430
1431 static void test_scene(void)
1432 {
1433     HRESULT                      hr;
1434     HWND                         hwnd               = NULL;
1435     IDirect3D9                  *pD3d               = NULL;
1436     IDirect3DDevice9            *pDevice            = NULL;
1437     D3DPRESENT_PARAMETERS        d3dpp;
1438     D3DDISPLAYMODE               d3ddm;
1439     IDirect3DSurface9            *pSurface1 = NULL, *pSurface2 = NULL, *pSurface3 = NULL, *pRenderTarget = NULL;
1440     IDirect3DSurface9            *pBackBuffer = NULL, *pDepthStencil = NULL;
1441     RECT rect = {0, 0, 128, 128};
1442     D3DCAPS9                     caps;
1443
1444     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1445     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1446     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1447     ok(hwnd != NULL, "Failed to create window\n");
1448     if (!pD3d || !hwnd) goto cleanup;
1449
1450     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1451     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1452     d3dpp.Windowed         = TRUE;
1453     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1454     d3dpp.BackBufferWidth  = 800;
1455     d3dpp.BackBufferHeight = 600;
1456     d3dpp.BackBufferFormat = d3ddm.Format;
1457     d3dpp.EnableAutoDepthStencil = TRUE;
1458     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1459
1460     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1461                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1462     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1463     if(!pDevice)
1464     {
1465         skip("Failed to create a d3d device\n");
1466         goto cleanup;
1467     }
1468
1469     /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
1470     memset(&caps, 0, sizeof(caps));
1471     hr = IDirect3DDevice9_GetDeviceCaps(pDevice, &caps);
1472     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
1473     if(FAILED(hr)) goto cleanup;
1474
1475     /* Test an EndScene without BeginScene. Should return an error */
1476     hr = IDirect3DDevice9_EndScene(pDevice);
1477     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1478
1479     /* Test a normal BeginScene / EndScene pair, this should work */
1480     hr = IDirect3DDevice9_BeginScene(pDevice);
1481     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1482     if(SUCCEEDED(hr))
1483     {
1484         hr = IDirect3DDevice9_EndScene(pDevice);
1485         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1486     }
1487
1488     /* Test another EndScene without having begun a new scene. Should return an error */
1489     hr = IDirect3DDevice9_EndScene(pDevice);
1490     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1491
1492     /* Two nested BeginScene and EndScene calls */
1493     hr = IDirect3DDevice9_BeginScene(pDevice);
1494     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1495     hr = IDirect3DDevice9_BeginScene(pDevice);
1496     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
1497     hr = IDirect3DDevice9_EndScene(pDevice);
1498     ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1499     hr = IDirect3DDevice9_EndScene(pDevice);
1500     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1501
1502     /* Create some surfaces to test stretchrect between the scenes */
1503     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface1, NULL);
1504     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1505     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface2, NULL);
1506     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1507     hr = IDirect3DDevice9_CreateDepthStencilSurface(pDevice, 800, 600, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface3, NULL);
1508     ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
1509     hr = IDirect3DDevice9_CreateRenderTarget(pDevice, 128, 128, d3ddm.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pRenderTarget, NULL);
1510     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
1511
1512     hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
1513     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1514     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1515     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1516
1517     /* First make sure a simple StretchRect call works */
1518     if(pSurface1 && pSurface2) {
1519         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1520         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1521     }
1522     if(pBackBuffer && pRenderTarget) {
1523         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1524         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1525     }
1526     if(pDepthStencil && pSurface3) {
1527         HRESULT expected;
1528         if(0) /* Disabled for now because it crashes in wine */ {
1529             expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
1530             hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1531             ok( hr == expected, "IDirect3DDevice9_StretchRect returned %08x, expected %08x\n", hr, expected);
1532         }
1533     }
1534
1535     /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a beginScene - Endscene pair
1536      * with normal surfaces and render targets, but not depth stencil surfaces.
1537      */
1538     hr = IDirect3DDevice9_BeginScene(pDevice);
1539     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1540
1541     if(pSurface1 && pSurface2)
1542     {
1543         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1544         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1545     }
1546     if(pBackBuffer && pRenderTarget)
1547     {
1548         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1549         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1550     }
1551     if(pDepthStencil && pSurface3)
1552     {
1553         /* This is supposed to fail inside a BeginScene - EndScene pair. */
1554         hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1555         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
1556     }
1557
1558     hr = IDirect3DDevice9_EndScene(pDevice);
1559     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1560
1561     /* Does a SetRenderTarget influence BeginScene / EndScene ?
1562      * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
1563      * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
1564      */
1565     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pRenderTarget);
1566     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1567     hr = IDirect3DDevice9_BeginScene(pDevice);
1568     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1569     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pBackBuffer);
1570     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1571     hr = IDirect3DDevice9_EndScene(pDevice);
1572     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1573
1574 cleanup:
1575     if(pRenderTarget) IDirect3DSurface9_Release(pRenderTarget);
1576     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1577     if(pBackBuffer) IDirect3DSurface9_Release(pBackBuffer);
1578     if(pSurface1) IDirect3DSurface9_Release(pSurface1);
1579     if(pSurface2) IDirect3DSurface9_Release(pSurface2);
1580     if(pSurface3) IDirect3DSurface9_Release(pSurface3);
1581     if (pDevice)
1582     {
1583         UINT refcount = IDirect3DDevice9_Release(pDevice);
1584         ok(!refcount, "Device has %u references left.\n", refcount);
1585     }
1586     if (pD3d) IDirect3D9_Release(pD3d);
1587     if(hwnd) DestroyWindow(hwnd);
1588 }
1589
1590 static void test_limits(void)
1591 {
1592     HRESULT                      hr;
1593     HWND                         hwnd               = NULL;
1594     IDirect3D9                  *pD3d               = NULL;
1595     IDirect3DDevice9            *pDevice            = NULL;
1596     D3DPRESENT_PARAMETERS        d3dpp;
1597     D3DDISPLAYMODE               d3ddm;
1598     IDirect3DTexture9           *pTexture           = NULL;
1599     int i;
1600
1601     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1602     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1603     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1604     ok(hwnd != NULL, "Failed to create window\n");
1605     if (!pD3d || !hwnd) goto cleanup;
1606
1607     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1608     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1609     d3dpp.Windowed         = TRUE;
1610     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1611     d3dpp.BackBufferWidth  = 800;
1612     d3dpp.BackBufferHeight = 600;
1613     d3dpp.BackBufferFormat = d3ddm.Format;
1614     d3dpp.EnableAutoDepthStencil = TRUE;
1615     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1616
1617     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1618                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1619     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1620     if(!pDevice)
1621     {
1622         skip("Failed to create a d3d device\n");
1623         goto cleanup;
1624     }
1625
1626     hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL);
1627     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
1628     if(!pTexture) goto cleanup;
1629
1630     /* There are 16 pixel samplers. We should be able to access all of them */
1631     for(i = 0; i < 16; i++) {
1632         hr = IDirect3DDevice9_SetTexture(pDevice, i, (IDirect3DBaseTexture9 *) pTexture);
1633         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1634         hr = IDirect3DDevice9_SetTexture(pDevice, i, NULL);
1635         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1636         hr = IDirect3DDevice9_SetSamplerState(pDevice, i, D3DSAMP_SRGBTEXTURE, TRUE);
1637         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
1638     }
1639
1640     /* Now test all 8 textures stage states */
1641     for(i = 0; i < 8; i++) {
1642         hr = IDirect3DDevice9_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1643         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
1644     }
1645
1646     /* Investigations show that accessing higher samplers / textures stage states does not return an error either. Writing
1647      * to too high samplers(approximately sampler 40) causes memory corruption in windows, so there is no bounds checking
1648      * but how do I test that?
1649      */
1650 cleanup:
1651     if(pTexture) IDirect3DTexture9_Release(pTexture);
1652     if (pDevice)
1653     {
1654         UINT refcount = IDirect3D9_Release(pDevice);
1655         ok(!refcount, "Device has %u references left.\n", refcount);
1656     }
1657     if (pD3d) IDirect3D9_Release(pD3d);
1658     if(hwnd) DestroyWindow(hwnd);
1659 }
1660
1661 static void test_depthstenciltest(void)
1662 {
1663     HRESULT                      hr;
1664     HWND                         hwnd               = NULL;
1665     IDirect3D9                  *pD3d               = NULL;
1666     IDirect3DDevice9            *pDevice            = NULL;
1667     D3DPRESENT_PARAMETERS        d3dpp;
1668     D3DDISPLAYMODE               d3ddm;
1669     IDirect3DSurface9           *pDepthStencil           = NULL;
1670     IDirect3DSurface9           *pDepthStencil2          = NULL;
1671     DWORD                        state;
1672
1673     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1674     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1675     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1676     ok(hwnd != NULL, "Failed to create window\n");
1677     if (!pD3d || !hwnd) goto cleanup;
1678
1679     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1680     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1681     d3dpp.Windowed         = TRUE;
1682     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1683     d3dpp.BackBufferWidth  = 800;
1684     d3dpp.BackBufferHeight = 600;
1685     d3dpp.BackBufferFormat = d3ddm.Format;
1686     d3dpp.EnableAutoDepthStencil = TRUE;
1687     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1688
1689     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1690                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1691     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1692     if(!pDevice)
1693     {
1694         skip("Failed to create a d3d device\n");
1695         goto cleanup;
1696     }
1697
1698     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1699     ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1700
1701     /* Try to clear */
1702     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1703     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1704
1705     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
1706     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1707
1708     /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
1709     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
1710     ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1711     if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
1712
1713     /* This left the render states untouched! */
1714     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1715     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1716     ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1717     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
1718     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1719     ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
1720     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
1721     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1722     ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
1723     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
1724     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1725     ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
1726
1727     /* This is supposed to fail now */
1728     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1729     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1730
1731     hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
1732     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
1733
1734     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
1735     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1736
1737     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1738     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1739     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1740
1741     /* Now it works again */
1742     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1743     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1744
1745     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1746     if(pDevice) IDirect3D9_Release(pDevice);
1747
1748     /* Now see if autodepthstencil disable is honored. First, without a format set */
1749     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1750     d3dpp.Windowed         = TRUE;
1751     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1752     d3dpp.BackBufferWidth  = 800;
1753     d3dpp.BackBufferHeight = 600;
1754     d3dpp.BackBufferFormat = d3ddm.Format;
1755     d3dpp.EnableAutoDepthStencil = FALSE;
1756     d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1757
1758     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1759                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1760     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1761     if(!pDevice)
1762     {
1763         skip("Failed to create a d3d device\n");
1764         goto cleanup;
1765     }
1766
1767     pDepthStencil = NULL;
1768     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1769     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1770     if(pDepthStencil) {
1771         IDirect3DSurface9_Release(pDepthStencil);
1772         pDepthStencil = NULL;
1773     }
1774
1775     /* Check the depth test state */
1776     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1777     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1778     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1779
1780     if(pDevice) IDirect3D9_Release(pDevice);
1781
1782     /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
1783     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1784     d3dpp.Windowed         = TRUE;
1785     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1786     d3dpp.BackBufferWidth  = 800;
1787     d3dpp.BackBufferHeight = 600;
1788     d3dpp.BackBufferFormat = d3ddm.Format;
1789     d3dpp.EnableAutoDepthStencil = FALSE;
1790     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1791
1792     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1793                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1794     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1795     if(!pDevice)
1796     {
1797         skip("Failed to create a d3d device\n");
1798         goto cleanup;
1799     }
1800
1801     pDepthStencil = NULL;
1802     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1803     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1804     if(pDepthStencil) {
1805         IDirect3DSurface9_Release(pDepthStencil);
1806         pDepthStencil = NULL;
1807     }
1808
1809     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1810     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1811     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1812
1813 cleanup:
1814     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1815     if (pDevice)
1816     {
1817         UINT refcount = IDirect3D9_Release(pDevice);
1818         ok(!refcount, "Device has %u references left.\n", refcount);
1819     }
1820     if (pD3d) IDirect3D9_Release(pD3d);
1821     if(hwnd) DestroyWindow(hwnd);
1822 }
1823
1824 static void test_get_rt(void)
1825 {
1826     IDirect3DSurface9 *backbuffer, *rt;
1827     IDirect3DDevice9 *device;
1828     IDirect3D9 *d3d9;
1829     D3DCAPS9 caps;
1830     HWND window;
1831     HRESULT hr;
1832     ULONG ref;
1833     UINT i;
1834
1835     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
1836     {
1837         skip("Failed to create IDirect3D9 object, skipping tests.\n");
1838         return;
1839     }
1840
1841     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1842             0, 0, 128, 128, 0, 0, 0, 0);
1843     device = create_device(d3d9, window, window, TRUE);
1844     if (!device)
1845     {
1846         skip("Failed to create a D3D device, skipping tests.\n");
1847         goto done;
1848     }
1849
1850     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
1851     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
1852     ok(!!backbuffer, "Got a NULL backbuffer.\n");
1853
1854     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1855     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1856
1857     for (i = 1; i < caps.NumSimultaneousRTs; ++i)
1858     {
1859         rt = backbuffer;
1860         hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
1861         ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
1862         ok(!rt, "Got rt %p.\n", rt);
1863     }
1864
1865     IDirect3DSurface9_Release(backbuffer);
1866
1867     ref = IDirect3DDevice9_Release(device);
1868     ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
1869 done:
1870     IDirect3D9_Release(d3d9);
1871     DestroyWindow(window);
1872 }
1873
1874 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
1875 static void test_draw_indexed(void)
1876 {
1877     static const struct {
1878         float position[3];
1879         DWORD color;
1880     } quad[] = {
1881         {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
1882         {{-1.0f,  1.0f, 0.0f}, 0xffff0000},
1883         {{ 1.0f,  1.0f, 0.0f}, 0xffff0000},
1884         {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
1885     };
1886     WORD indices[] = {0, 1, 2, 3, 0, 2};
1887
1888     static const D3DVERTEXELEMENT9 decl_elements[] = {
1889         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1890         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1891         D3DDECL_END()
1892     };
1893
1894     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1895     IDirect3DVertexBuffer9 *vertex_buffer = NULL;
1896     IDirect3DIndexBuffer9 *index_buffer = NULL;
1897     D3DPRESENT_PARAMETERS present_parameters;
1898     IDirect3DDevice9 *device = NULL;
1899     IDirect3D9 *d3d9;
1900     HRESULT hr;
1901     HWND hwnd;
1902     void *ptr;
1903
1904     hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
1905             0, 0, 0, 10, 10, 0, 0, 0, 0);
1906     if (!hwnd)
1907     {
1908         skip("Failed to create window\n");
1909         return;
1910     }
1911
1912     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
1913     if (!d3d9)
1914     {
1915         skip("Failed to create IDirect3D9 object\n");
1916         goto cleanup;
1917     }
1918
1919     ZeroMemory(&present_parameters, sizeof(present_parameters));
1920     present_parameters.Windowed = TRUE;
1921     present_parameters.hDeviceWindow = hwnd;
1922     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1923
1924     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1925             NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1926     if (FAILED(hr) || !device)
1927     {
1928         skip("Failed to create device\n");
1929         goto cleanup;
1930     }
1931
1932     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1933     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1934     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1935     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1936
1937     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
1938     ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
1939     hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1940     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1941     memcpy(ptr, quad, sizeof(quad));
1942     hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
1943     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1944     hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
1945     ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
1946
1947     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
1948     ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
1949     hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1950     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1951     memcpy(ptr, indices, sizeof(indices));
1952     hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
1953     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1954     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1955     ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
1956     hr = IDirect3DDevice9_BeginScene(device);
1957     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1958
1959     /* NULL index buffer. Should fail */
1960     hr = IDirect3DDevice9_SetIndices(device, NULL);
1961     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1962     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1963             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1964     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1965             hr, D3DERR_INVALIDCALL);
1966
1967     /* Valid index buffer, NULL vertex declaration. Should fail */
1968     hr = IDirect3DDevice9_SetIndices(device, index_buffer);
1969     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1970     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1971             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1972     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1973             hr, D3DERR_INVALIDCALL);
1974
1975     /* Valid index buffer and vertex declaration. Should succeed */
1976     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1977     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1978     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1979             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1980     ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
1981
1982     hr = IDirect3DDevice9_EndScene(device);
1983     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1984
1985     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1986     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1987
1988     IDirect3DVertexBuffer9_Release(vertex_buffer);
1989     IDirect3DIndexBuffer9_Release(index_buffer);
1990     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1991
1992 cleanup:
1993     if (device)
1994     {
1995         UINT refcount = IDirect3DDevice9_Release(device);
1996         ok(!refcount, "Device has %u references left.\n", refcount);
1997     }
1998     if (d3d9) IDirect3D9_Release(d3d9);
1999     if (hwnd) DestroyWindow(hwnd);
2000 }
2001
2002 static void test_null_stream(void)
2003 {
2004     IDirect3DVertexBuffer9 *buffer = NULL;
2005     D3DPRESENT_PARAMETERS present_parameters;
2006     IDirect3DDevice9 *device = NULL;
2007     IDirect3D9 *d3d9;
2008     HWND hwnd;
2009     HRESULT hr;
2010     IDirect3DVertexShader9 *shader = NULL;
2011     IDirect3DVertexDeclaration9 *decl = NULL;
2012     DWORD shader_code[] = {
2013         0xfffe0101,                             /* vs_1_1           */
2014         0x0000001f, 0x80000000, 0x900f0000,     /* dcl_position v0  */
2015         0x00000001, 0xc00f0000, 0x90e40000,     /* mov oPos, v0     */
2016         0x0000ffff                              /* end              */
2017     };
2018     static const D3DVERTEXELEMENT9 decl_elements[] = {
2019         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2020         {1, 0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
2021         D3DDECL_END()
2022     };
2023
2024     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2025     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2026     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2027     ok(hwnd != NULL, "Failed to create window\n");
2028     if (!d3d9 || !hwnd) goto cleanup;
2029
2030     ZeroMemory(&present_parameters, sizeof(present_parameters));
2031     present_parameters.Windowed = TRUE;
2032     present_parameters.hDeviceWindow = hwnd;
2033     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2034
2035     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
2036                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2037     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2038     if(!device)
2039     {
2040         skip("Failed to create a d3d device\n");
2041         goto cleanup;
2042     }
2043
2044     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2045     if(FAILED(hr)) {
2046         skip("No vertex shader support\n");
2047         goto cleanup;
2048     }
2049     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2050     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2051     if (FAILED(hr)) {
2052         skip("Vertex declaration handling not possible.\n");
2053         goto cleanup;
2054     }
2055     hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2056     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2057     if (FAILED(hr)) {
2058         skip("Vertex buffer handling not possible.\n");
2059         goto cleanup;
2060     }
2061
2062     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
2063     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2064     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
2065     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2066     hr = IDirect3DDevice9_SetVertexShader(device, shader);
2067     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
2068     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2069     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
2070
2071     hr = IDirect3DDevice9_BeginScene(device);
2072     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (0x%08x)\n", hr);
2073     if(SUCCEEDED(hr)) {
2074         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
2075         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitive failed (0x%08x)\n", hr);
2076
2077         hr = IDirect3DDevice9_EndScene(device);
2078         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed (0x%08x)\n", hr);
2079     }
2080
2081     IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2082     IDirect3DDevice9_SetVertexShader(device, NULL);
2083     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2084
2085 cleanup:
2086     if (buffer) IDirect3DVertexBuffer9_Release(buffer);
2087     if(decl) IDirect3DVertexDeclaration9_Release(decl);
2088     if(shader) IDirect3DVertexShader9_Release(shader);
2089     if (device)
2090     {
2091         UINT refcount = IDirect3DDevice9_Release(device);
2092         ok(!refcount, "Device has %u references left.\n", refcount);
2093     }
2094     if(d3d9) IDirect3D9_Release(d3d9);
2095 }
2096
2097 static void test_lights(void)
2098 {
2099     D3DPRESENT_PARAMETERS present_parameters;
2100     IDirect3DDevice9 *device = NULL;
2101     IDirect3D9 *d3d9;
2102     HWND hwnd;
2103     HRESULT hr;
2104     unsigned int i;
2105     BOOL enabled;
2106     D3DCAPS9 caps;
2107
2108     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2109     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2110     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2111     ok(hwnd != NULL, "Failed to create window\n");
2112     if (!d3d9 || !hwnd) goto cleanup;
2113
2114     ZeroMemory(&present_parameters, sizeof(present_parameters));
2115     present_parameters.Windowed = TRUE;
2116     present_parameters.hDeviceWindow = hwnd;
2117     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2118
2119     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2120                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2121     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2122        "IDirect3D9_CreateDevice failed with %08x\n", hr);
2123     if(!device)
2124     {
2125         skip("Failed to create a d3d device\n");
2126         goto cleanup;
2127     }
2128
2129     memset(&caps, 0, sizeof(caps));
2130     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2131     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
2132
2133     for(i = 1; i <= caps.MaxActiveLights; i++) {
2134         hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
2135         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2136         hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
2137         ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
2138         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2139     }
2140
2141     /* TODO: Test the rendering results in this situation */
2142     hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
2143     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2144     hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
2145     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2146     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2147     hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
2148     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2149
2150     for(i = 1; i <= caps.MaxActiveLights; i++) {
2151         hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2152         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2153     }
2154
2155 cleanup:
2156     if (device)
2157     {
2158         UINT refcount = IDirect3DDevice9_Release(device);
2159         ok(!refcount, "Device has %u references left.\n", refcount);
2160     }
2161     if(d3d9) IDirect3D9_Release(d3d9);
2162 }
2163
2164 static void test_set_stream_source(void)
2165 {
2166     D3DPRESENT_PARAMETERS present_parameters;
2167     IDirect3DDevice9 *device = NULL;
2168     IDirect3D9 *d3d9;
2169     HWND hwnd;
2170     HRESULT hr;
2171     IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
2172
2173     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2174     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2175     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2176     ok(hwnd != NULL, "Failed to create window\n");
2177     if (!d3d9 || !hwnd) goto cleanup;
2178
2179     ZeroMemory(&present_parameters, sizeof(present_parameters));
2180     present_parameters.Windowed = TRUE;
2181     present_parameters.hDeviceWindow = hwnd;
2182     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2183
2184     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2185                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2186     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2187        "IDirect3D9_CreateDevice failed with %08x\n", hr);
2188     if(!device)
2189     {
2190         hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd,
2191                                       D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2192         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2193            "IDirect3D9_CreateDevice failed with %08x\n", hr);
2194         if(!device)
2195         {
2196             skip("Failed to create a d3d device\n");
2197             goto cleanup;
2198         }
2199     }
2200
2201     hr = IDirect3DDevice9_CreateVertexBuffer( device, 512, 0, 0, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
2202     ok(hr == D3D_OK, "Failed to create a vertex buffer, hr = %08x\n", hr);
2203     if (SUCCEEDED(hr)) {
2204         /* Some cards(Geforce 7400 at least) accept non-aligned offsets, others(radeon 9000 verified) reject it,
2205          * so accept both results. Wine currently rejects this to be able to optimize the vbo conversion, but writes
2206          * a WARN
2207          */
2208         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32);
2209         ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2210         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32);
2211         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2212         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 2, 32);
2213         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2214         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 3, 32);
2215         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2216         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 4, 32);
2217         ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2218     }
2219     /* Try to set the NULL buffer with an offset and stride 0 */
2220     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2221     ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2222     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2223     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2224     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2225     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2226     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2227     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2228     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2229     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2230
2231     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2232     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2233
2234 cleanup:
2235     if (pVertexBuffer) IDirect3DVertexBuffer9_Release(pVertexBuffer);
2236     if (device)
2237     {
2238         UINT refcount = IDirect3DDevice9_Release(device);
2239         ok(!refcount, "Device has %u references left.\n", refcount);
2240     }
2241     if(d3d9) IDirect3D9_Release(d3d9);
2242 }
2243
2244 struct formats {
2245     D3DFORMAT DisplayFormat;
2246     D3DFORMAT BackBufferFormat;
2247     BOOL shouldPass;
2248 };
2249
2250 static const struct formats r5g6b5_format_list[] =
2251 {
2252     { D3DFMT_R5G6B5, D3DFMT_R5G6B5, TRUE },
2253     { D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, FALSE },
2254     { D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, FALSE },
2255     { D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, FALSE },
2256     { D3DFMT_R5G6B5, D3DFMT_A8R8G8B8, FALSE },
2257     { 0, 0, 0}
2258 };
2259
2260 static const struct formats x1r5g5b5_format_list[] =
2261 {
2262     { D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, FALSE },
2263     { D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, TRUE },
2264     { D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE },
2265     { D3DFMT_X1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2266     { D3DFMT_X1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2267
2268     /* A1R5G5B5 should not be usable as a display format, it is backbuffer-only */
2269     { D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, FALSE },
2270     { D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, FALSE },
2271     { D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE },
2272     { D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2273     { D3DFMT_A1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2274     { 0, 0, 0}
2275 };
2276
2277 static const struct formats x8r8g8b8_format_list[] =
2278 {
2279     { D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, FALSE },
2280     { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2281     { D3DFMT_X8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2282     { D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, TRUE },
2283     { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE },
2284
2285     /* A1R8G8B8 should not be usable as a display format, it is backbuffer-only */
2286     { D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, FALSE },
2287     { D3DFMT_A8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2288     { D3DFMT_A8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2289     { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, FALSE },
2290     { D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE },
2291     { 0, 0, 0}
2292 };
2293
2294 static void test_display_formats(void)
2295 {
2296     /* Direct3D9 offers 4 display formats R5G6B5, X1R5G5B5, X8R8G8B8 and A2R10G10B10.
2297      * Next to these there are 6 different backbuffer formats. Only a fixed number of
2298      * combinations are possible in FULLSCREEN mode. In windowed mode more combinations are
2299      * allowed due to depth conversion and this is likely driver dependent.
2300      * This test checks which combinations are possible in fullscreen mode and this should not be driver dependent.
2301      * TODO: handle A2R10G10B10 but what hardware supports it? Parhelia? It is very rare. */
2302
2303     UINT Adapter = D3DADAPTER_DEFAULT;
2304     D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
2305     int i, nmodes;
2306     HRESULT hr;
2307
2308     IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2309     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2310     if(!d3d9) return;
2311
2312     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_R5G6B5);
2313     if(!nmodes) {
2314         skip("Display format R5G6B5 not supported, skipping\n");
2315     } else {
2316         trace("Testing display format R5G6B5\n");
2317         for(i=0; r5g6b5_format_list[i].DisplayFormat != 0; i++)
2318         {
2319             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, FALSE);
2320
2321             if(r5g6b5_format_list[i].shouldPass)
2322                 ok(hr == D3D_OK ||
2323                    broken(hr == D3DERR_NOTAVAILABLE),
2324                    "format %d %d didn't pass with hr=%#08x\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, hr);
2325             else
2326                 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);
2327         }
2328     }
2329
2330     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X1R5G5B5);
2331     if(!nmodes) {
2332         skip("Display format X1R5G5B5 not supported, skipping\n");
2333     } else {
2334         trace("Testing display format X1R5G5B5\n");
2335         for(i=0; x1r5g5b5_format_list[i].DisplayFormat != 0; i++)
2336         {
2337             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, FALSE);
2338
2339             if(x1r5g5b5_format_list[i].shouldPass)
2340                 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);
2341             else
2342                 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);
2343         }
2344     }
2345
2346     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
2347     if(!nmodes) {
2348         skip("Display format X8R8G8B8 not supported, skipping\n");
2349     } else {
2350         trace("Testing display format X8R8G8B8\n");
2351         for(i=0; x8r8g8b8_format_list[i].DisplayFormat != 0; i++)
2352         {
2353             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, FALSE);
2354
2355             if(x8r8g8b8_format_list[i].shouldPass)
2356                 ok(hr == D3D_OK ||
2357                    broken(hr == D3DERR_NOTAVAILABLE),
2358                    "format %d %d didn't pass with hr=%#08x\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr);
2359             else
2360                 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);
2361         }
2362     }
2363
2364     if(d3d9) IDirect3D9_Release(d3d9);
2365 }
2366
2367 static void test_scissor_size(void)
2368 {
2369     IDirect3D9 *d3d9_ptr = 0;
2370     unsigned int i;
2371     static struct {
2372         int winx; int winy; int backx; int backy; BOOL window;
2373     } scts[] = { /* scissor tests */
2374         {800, 600, 640, 480, TRUE},
2375         {800, 600, 640, 480, FALSE},
2376         {640, 480, 800, 600, TRUE},
2377         {640, 480, 800, 600, FALSE},
2378     };
2379
2380     d3d9_ptr = pDirect3DCreate9(D3D_SDK_VERSION);
2381     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
2382     if (!d3d9_ptr){
2383         skip("Failed to create IDirect3D9 object\n");
2384         return;
2385     }
2386
2387     for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
2388         IDirect3DDevice9 *device_ptr = 0;
2389         D3DPRESENT_PARAMETERS present_parameters;
2390         HRESULT hr;
2391         HWND hwnd = 0;
2392         RECT scissorrect;
2393
2394         hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
2395                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
2396
2397         if (!scts[i].window)
2398         {
2399             scts[i].backx = screen_width;
2400             scts[i].backy = screen_height;
2401         }
2402
2403         ZeroMemory(&present_parameters, sizeof(present_parameters));
2404         present_parameters.Windowed = scts[i].window;
2405         present_parameters.hDeviceWindow = hwnd;
2406         present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2407         present_parameters.BackBufferWidth = scts[i].backx;
2408         present_parameters.BackBufferHeight = scts[i].backy;
2409         present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
2410         present_parameters.EnableAutoDepthStencil = TRUE;
2411         present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2412
2413         hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2414         if(FAILED(hr)) {
2415             present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
2416             hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2417             if(FAILED(hr)) {
2418                 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2419             }
2420         }
2421         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
2422
2423         if (!device_ptr)
2424         {
2425             DestroyWindow(hwnd);
2426             skip("Creating the device failed\n");
2427             goto err_out;
2428         }
2429
2430         /* Check for the default scissor rect size */
2431         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2432         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2433         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);
2434
2435         /* check the scissorrect values after a reset */
2436         present_parameters.BackBufferWidth = screen_width;
2437         present_parameters.BackBufferHeight = screen_height;
2438         hr = IDirect3DDevice9_Reset(device_ptr, &present_parameters);
2439         ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2440         hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
2441         ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2442
2443         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2444         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2445         ok(scissorrect.right == screen_width && scissorrect.bottom == screen_height && scissorrect.top == 0 && scissorrect.left == 0, "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom, screen_width, screen_height);
2446
2447         if(device_ptr) {
2448             ULONG ref;
2449
2450             ref = IDirect3DDevice9_Release(device_ptr);
2451             DestroyWindow(hwnd);
2452             ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
2453         }
2454     }
2455
2456 err_out:
2457     if(d3d9_ptr) IDirect3D9_Release(d3d9_ptr);
2458     return;
2459 }
2460
2461 static void test_multi_device(void)
2462 {
2463     IDirect3DDevice9 *device1 = NULL, *device2 = NULL;
2464     D3DPRESENT_PARAMETERS present_parameters;
2465     HWND hwnd1 = NULL, hwnd2 = NULL;
2466     IDirect3D9 *d3d9;
2467     ULONG refcount;
2468     HRESULT hr;
2469
2470     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2471     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2472     if (!d3d9) goto fail;
2473
2474     hwnd1 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2475     ok(hwnd1 != NULL, "Failed to create a window.\n");
2476     if (!hwnd1) goto fail;
2477
2478     memset(&present_parameters, 0, sizeof(present_parameters));
2479     present_parameters.Windowed = TRUE;
2480     present_parameters.hDeviceWindow = hwnd1;
2481     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2482
2483     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd1,
2484             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device1);
2485     IDirect3D9_Release(d3d9);
2486     d3d9 = NULL;
2487     if (FAILED(hr)) {
2488         skip("Failed to create a device\n");
2489         goto fail;
2490     }
2491
2492     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2493     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2494     if (!d3d9) goto fail;
2495
2496     hwnd2 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2497     ok(hwnd2 != NULL, "Failed to create a window.\n");
2498     if (!hwnd2) goto fail;
2499
2500     memset(&present_parameters, 0, sizeof(present_parameters));
2501     present_parameters.Windowed = TRUE;
2502     present_parameters.hDeviceWindow = hwnd2;
2503     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2504
2505     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd2,
2506             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device2);
2507     ok(SUCCEEDED(hr), "Failed to create a device, hr %#x\n", hr);
2508     IDirect3D9_Release(d3d9);
2509     d3d9 = NULL;
2510     if (FAILED(hr)) goto fail;
2511
2512 fail:
2513     if (d3d9) IDirect3D9_Release(d3d9);
2514     if (device1)
2515     {
2516         refcount = IDirect3DDevice9_Release(device1);
2517         ok(!refcount, "Device has %u references left.\n", refcount);
2518     }
2519     if (device2)
2520     {
2521         refcount = IDirect3DDevice9_Release(device2);
2522         ok(!refcount, "Device has %u references left.\n", refcount);
2523     }
2524     if (hwnd1) DestroyWindow(hwnd1);
2525     if (hwnd2) DestroyWindow(hwnd2);
2526 }
2527
2528 static HWND filter_messages;
2529
2530 enum message_window
2531 {
2532     DEVICE_WINDOW,
2533     FOCUS_WINDOW,
2534 };
2535
2536 struct message
2537 {
2538     UINT message;
2539     enum message_window window;
2540 };
2541
2542 static const struct message *expect_messages;
2543 static HWND device_window, focus_window;
2544
2545 struct wndproc_thread_param
2546 {
2547     HWND dummy_window;
2548     HANDLE window_created;
2549     HANDLE test_finished;
2550     BOOL running_in_foreground;
2551 };
2552
2553 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2554 {
2555     if (filter_messages && filter_messages == hwnd)
2556     {
2557         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2558             todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2559     }
2560
2561     if (expect_messages)
2562     {
2563         HWND w;
2564
2565         switch (expect_messages->window)
2566         {
2567             case DEVICE_WINDOW:
2568                 w = device_window;
2569                 break;
2570
2571             case FOCUS_WINDOW:
2572                 w = focus_window;
2573                 break;
2574
2575             default:
2576                 w = NULL;
2577                 break;
2578         };
2579
2580         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2581     }
2582
2583     return DefWindowProcA(hwnd, message, wparam, lparam);
2584 }
2585
2586 static DWORD WINAPI wndproc_thread(void *param)
2587 {
2588     struct wndproc_thread_param *p = param;
2589     DWORD res;
2590     BOOL ret;
2591
2592     p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2593             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2594     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2595
2596     ret = SetEvent(p->window_created);
2597     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2598
2599     for (;;)
2600     {
2601         MSG msg;
2602
2603         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2604         res = WaitForSingleObject(p->test_finished, 100);
2605         if (res == WAIT_OBJECT_0) break;
2606         if (res != WAIT_TIMEOUT)
2607         {
2608             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2609             break;
2610         }
2611     }
2612
2613     DestroyWindow(p->dummy_window);
2614
2615     return 0;
2616 }
2617
2618 static void test_wndproc(void)
2619 {
2620     struct wndproc_thread_param thread_params;
2621     IDirect3DDevice9 *device;
2622     WNDCLASSA wc = {0};
2623     IDirect3D9 *d3d9;
2624     HANDLE thread;
2625     LONG_PTR proc;
2626     ULONG ref;
2627     DWORD res, tid;
2628     HWND tmp;
2629
2630     static const struct message messages[] =
2631     {
2632         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2633         {WM_ACTIVATE,           FOCUS_WINDOW},
2634         {WM_SETFOCUS,           FOCUS_WINDOW},
2635         {0,                     0},
2636     };
2637
2638     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2639     {
2640         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2641         return;
2642     }
2643
2644     wc.lpfnWndProc = test_proc;
2645     wc.lpszClassName = "d3d9_test_wndproc_wc";
2646     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2647
2648     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2649     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2650     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2651     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2652
2653     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2654             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2655     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2656             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2657     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2658     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2659
2660     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2661     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2662
2663     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2664     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2665             (LONG_PTR)test_proc, proc);
2666     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2667     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2668             (LONG_PTR)test_proc, proc);
2669
2670     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2671             device_window, focus_window, thread_params.dummy_window);
2672
2673     tmp = GetFocus();
2674     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2675     if (thread_params.running_in_foreground)
2676     {
2677         tmp = GetForegroundWindow();
2678         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2679                 thread_params.dummy_window, tmp);
2680     }
2681     else
2682         skip("Not running in foreground, skip foreground window test\n");
2683
2684     flush_events();
2685
2686     expect_messages = messages;
2687
2688     device = create_device(d3d9, device_window, focus_window, FALSE);
2689     if (!device)
2690     {
2691         skip("Failed to create a D3D device, skipping tests.\n");
2692         goto done;
2693     }
2694
2695     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2696             expect_messages->message, expect_messages->window);
2697     expect_messages = NULL;
2698
2699     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2700     {
2701         tmp = GetFocus();
2702         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2703         tmp = GetForegroundWindow();
2704         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2705     }
2706     SetForegroundWindow(focus_window);
2707     flush_events();
2708
2709     filter_messages = focus_window;
2710
2711     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2712     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2713             (LONG_PTR)test_proc, proc);
2714
2715     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2716     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2717             (LONG_PTR)test_proc, proc);
2718
2719     ref = IDirect3DDevice9_Release(device);
2720     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2721
2722     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2723     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2724             (LONG_PTR)test_proc, proc);
2725
2726     device = create_device(d3d9, focus_window, focus_window, FALSE);
2727     if (!device)
2728     {
2729         skip("Failed to create a D3D device, skipping tests.\n");
2730         goto done;
2731     }
2732
2733     ref = IDirect3DDevice9_Release(device);
2734     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2735
2736     device = create_device(d3d9, device_window, focus_window, FALSE);
2737     if (!device)
2738     {
2739         skip("Failed to create a D3D device, skipping tests.\n");
2740         goto done;
2741     }
2742
2743     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2744     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2745             (LONG_PTR)test_proc, proc);
2746
2747     ref = IDirect3DDevice9_Release(device);
2748     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2749
2750     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2751     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2752             (LONG_PTR)DefWindowProcA, proc);
2753
2754 done:
2755     filter_messages = NULL;
2756     IDirect3D9_Release(d3d9);
2757
2758     SetEvent(thread_params.test_finished);
2759     WaitForSingleObject(thread, INFINITE);
2760     CloseHandle(thread_params.test_finished);
2761     CloseHandle(thread_params.window_created);
2762     CloseHandle(thread);
2763
2764     DestroyWindow(device_window);
2765     DestroyWindow(focus_window);
2766     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2767 }
2768
2769 static void test_wndproc_windowed(void)
2770 {
2771     struct wndproc_thread_param thread_params;
2772     IDirect3DDevice9 *device;
2773     WNDCLASSA wc = {0};
2774     IDirect3D9 *d3d9;
2775     HANDLE thread;
2776     LONG_PTR proc;
2777     HRESULT hr;
2778     ULONG ref;
2779     DWORD res, tid;
2780     HWND tmp;
2781
2782     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2783     {
2784         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2785         return;
2786     }
2787
2788     wc.lpfnWndProc = test_proc;
2789     wc.lpszClassName = "d3d9_test_wndproc_wc";
2790     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2791
2792     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2793     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2794     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2795     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2796
2797     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2798             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2799     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2800             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2801     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2802     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2803
2804     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2805     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2806
2807     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2808     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2809             (LONG_PTR)test_proc, proc);
2810     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2811     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2812             (LONG_PTR)test_proc, proc);
2813
2814     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2815             device_window, focus_window, thread_params.dummy_window);
2816
2817     tmp = GetFocus();
2818     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2819     if (thread_params.running_in_foreground)
2820     {
2821         tmp = GetForegroundWindow();
2822         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2823                 thread_params.dummy_window, tmp);
2824     }
2825     else
2826         skip("Not running in foreground, skip foreground window test\n");
2827
2828     filter_messages = focus_window;
2829
2830     device = create_device(d3d9, device_window, focus_window, TRUE);
2831     if (!device)
2832     {
2833         skip("Failed to create a D3D device, skipping tests.\n");
2834         goto done;
2835     }
2836
2837     tmp = GetFocus();
2838     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2839     tmp = GetForegroundWindow();
2840     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2841             thread_params.dummy_window, tmp);
2842
2843     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2844     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2845             (LONG_PTR)test_proc, proc);
2846
2847     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2848     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2849             (LONG_PTR)test_proc, proc);
2850
2851     filter_messages = NULL;
2852
2853     hr = reset_device(device, device_window, FALSE);
2854     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2855
2856     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2857     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2858             (LONG_PTR)test_proc, proc);
2859
2860     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2861     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2862             (LONG_PTR)test_proc, proc);
2863
2864     hr = reset_device(device, device_window, TRUE);
2865     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2866
2867     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2868     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2869             (LONG_PTR)test_proc, proc);
2870
2871     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2872     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2873             (LONG_PTR)test_proc, proc);
2874
2875     filter_messages = focus_window;
2876
2877     ref = IDirect3DDevice9_Release(device);
2878     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2879
2880     filter_messages = device_window;
2881
2882     device = create_device(d3d9, focus_window, focus_window, TRUE);
2883     if (!device)
2884     {
2885         skip("Failed to create a D3D device, skipping tests.\n");
2886         goto done;
2887     }
2888
2889     filter_messages = NULL;
2890
2891     hr = reset_device(device, focus_window, FALSE);
2892     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2893
2894     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2895     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2896             (LONG_PTR)test_proc, proc);
2897
2898     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2899     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2900             (LONG_PTR)test_proc, proc);
2901
2902     hr = reset_device(device, focus_window, TRUE);
2903     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2904
2905     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2906     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2907             (LONG_PTR)test_proc, proc);
2908
2909     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2910     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2911             (LONG_PTR)test_proc, proc);
2912
2913     filter_messages = device_window;
2914
2915     ref = IDirect3DDevice9_Release(device);
2916     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2917
2918     device = create_device(d3d9, device_window, focus_window, TRUE);
2919     if (!device)
2920     {
2921         skip("Failed to create a D3D device, skipping tests.\n");
2922         goto done;
2923     }
2924
2925     filter_messages = NULL;
2926
2927     hr = reset_device(device, device_window, FALSE);
2928     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2929
2930     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2931     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2932             (LONG_PTR)test_proc, proc);
2933
2934     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2935     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2936             (LONG_PTR)test_proc, proc);
2937
2938     hr = reset_device(device, device_window, TRUE);
2939     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2940
2941     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2942     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2943             (LONG_PTR)test_proc, proc);
2944
2945     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2946     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2947             (LONG_PTR)test_proc, proc);
2948
2949     filter_messages = device_window;
2950
2951     ref = IDirect3DDevice9_Release(device);
2952     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2953
2954 done:
2955     filter_messages = NULL;
2956     IDirect3D9_Release(d3d9);
2957
2958     SetEvent(thread_params.test_finished);
2959     WaitForSingleObject(thread, INFINITE);
2960     CloseHandle(thread_params.test_finished);
2961     CloseHandle(thread_params.window_created);
2962     CloseHandle(thread);
2963
2964     DestroyWindow(device_window);
2965     DestroyWindow(focus_window);
2966     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2967 }
2968
2969 static void test_reset_fullscreen(void)
2970 {
2971     WNDCLASSEX wc = {0};
2972     IDirect3DDevice9 *device = NULL;
2973     IDirect3D9 *d3d = NULL;
2974     ATOM atom;
2975     static const struct message messages[] =
2976     {
2977         {WM_ACTIVATEAPP,    FOCUS_WINDOW},
2978         {0,                     0},
2979     };
2980
2981     d3d = pDirect3DCreate9(D3D_SDK_VERSION);
2982     ok(d3d != NULL, "Failed to create an IDirect3D object.\n");
2983     expect_messages = messages;
2984
2985     wc.cbSize = sizeof(WNDCLASSEX);
2986     wc.lpfnWndProc = test_proc;
2987     wc.lpszClassName = "test_reset_fullscreen";
2988
2989     atom = RegisterClassEx(&wc);
2990     ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
2991
2992     device_window = focus_window = CreateWindowEx(0, wc.lpszClassName, "Test Reset Fullscreen", 0, 0, 0, screen_width, screen_height, NULL, NULL, NULL, NULL);
2993     ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
2994
2995     /*
2996      * Create a device in windowed mode.
2997      * Since the device is windowed and we haven't called any methods that
2998      * could show the window (such as ShowWindow or SetWindowPos) yet,
2999      * WM_ACTIVATEAPP will not have been sent.
3000      */
3001     device = create_device(d3d, device_window, focus_window, TRUE);
3002     if (!device)
3003     {
3004         skip("Unable to create device.  Skipping test.\n");
3005         goto cleanup;
3006     }
3007
3008     /*
3009      * Switch to fullscreen mode.
3010      * This will force the window to be shown and will cause the WM_ACTIVATEAPP
3011      * message to be sent.
3012      */
3013     ok(SUCCEEDED(reset_device(device, device_window, FALSE)), "Failed to reset device.\n");
3014
3015     flush_events();
3016     ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
3017     expect_messages = NULL;
3018
3019 cleanup:
3020     if (device) IDirect3DDevice9_Release(device);
3021     if (d3d) IDirect3D9_Release(d3d);
3022     DestroyWindow(device_window);
3023     device_window = focus_window = NULL;
3024     UnregisterClass(wc.lpszClassName, GetModuleHandle(NULL));
3025 }
3026
3027
3028 static inline void set_fpu_cw(WORD cw)
3029 {
3030 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3031 #define D3D9_TEST_SET_FPU_CW 1
3032     __asm__ volatile ("fnclex");
3033     __asm__ volatile ("fldcw %0" : : "m" (cw));
3034 #elif defined(__i386__) && defined(_MSC_VER)
3035 #define D3D9_TEST_SET_FPU_CW 1
3036     __asm fnclex;
3037     __asm fldcw cw;
3038 #endif
3039 }
3040
3041 static inline WORD get_fpu_cw(void)
3042 {
3043     WORD cw = 0;
3044 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3045 #define D3D9_TEST_GET_FPU_CW 1
3046     __asm__ volatile ("fnstcw %0" : "=m" (cw));
3047 #elif defined(__i386__) && defined(_MSC_VER)
3048 #define D3D9_TEST_GET_FPU_CW 1
3049     __asm fnstcw cw;
3050 #endif
3051     return cw;
3052 }
3053
3054 static void test_fpu_setup(void)
3055 {
3056 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
3057     D3DPRESENT_PARAMETERS present_parameters;
3058     IDirect3DDevice9 *device;
3059     HWND window = NULL;
3060     IDirect3D9 *d3d9;
3061     HRESULT hr;
3062     WORD cw;
3063
3064     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
3065     ok(!!d3d9, "Failed to create a d3d9 object.\n");
3066     if (!d3d9) return;
3067
3068     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3069     ok(!!window, "Failed to create a window.\n");
3070     if (!window) goto done;
3071
3072     memset(&present_parameters, 0, sizeof(present_parameters));
3073     present_parameters.Windowed = TRUE;
3074     present_parameters.hDeviceWindow = window;
3075     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
3076
3077     set_fpu_cw(0xf60);
3078     cw = get_fpu_cw();
3079     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3080
3081     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3082             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
3083     if (FAILED(hr))
3084     {
3085         skip("Failed to create a device, hr %#x.\n", hr);
3086         set_fpu_cw(0x37f);
3087         goto done;
3088     }
3089
3090     cw = get_fpu_cw();
3091     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3092
3093     IDirect3DDevice9_Release(device);
3094
3095     cw = get_fpu_cw();
3096     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3097     set_fpu_cw(0xf60);
3098     cw = get_fpu_cw();
3099     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3100
3101     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3102             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
3103     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
3104
3105     cw = get_fpu_cw();
3106     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3107     set_fpu_cw(0x37f);
3108
3109     IDirect3DDevice9_Release(device);
3110
3111 done:
3112     if (window) DestroyWindow(window);
3113     if (d3d9) IDirect3D9_Release(d3d9);
3114 #endif
3115 }
3116
3117 static void test_window_style(void)
3118 {
3119     RECT focus_rect, fullscreen_rect, r;
3120     LONG device_style, device_exstyle;
3121     LONG focus_style, focus_exstyle;
3122     LONG style, expected_style;
3123     IDirect3DDevice9 *device;
3124     IDirect3D9 *d3d9;
3125     ULONG ref;
3126
3127
3128     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3129     {
3130         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3131         return;
3132     }
3133
3134     focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3135             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3136     device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3137             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3138
3139     device_style = GetWindowLongA(device_window, GWL_STYLE);
3140     device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3141     focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3142     focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3143
3144     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3145     GetWindowRect(focus_window, &focus_rect);
3146
3147     device = create_device(d3d9, device_window, focus_window, FALSE);
3148     if (!device)
3149     {
3150         skip("Failed to create a D3D device, skipping tests.\n");
3151         goto done;
3152     }
3153
3154     style = GetWindowLongA(device_window, GWL_STYLE);
3155     expected_style = device_style | WS_VISIBLE;
3156     todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3157             expected_style, style);
3158     style = GetWindowLongA(device_window, GWL_EXSTYLE);
3159     expected_style = device_exstyle | WS_EX_TOPMOST;
3160     todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3161             expected_style, style);
3162
3163     style = GetWindowLongA(focus_window, GWL_STYLE);
3164     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3165             focus_style, style);
3166     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3167     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3168             focus_exstyle, style);
3169
3170     GetWindowRect(device_window, &r);
3171     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3172             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3173             r.left, r.top, r.right, r.bottom);
3174     GetClientRect(device_window, &r);
3175     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3176     GetWindowRect(focus_window, &r);
3177     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3178             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3179             r.left, r.top, r.right, r.bottom);
3180
3181     ref = IDirect3DDevice9_Release(device);
3182     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3183
3184 done:
3185     IDirect3D9_Release(d3d9);
3186
3187     DestroyWindow(device_window);
3188     DestroyWindow(focus_window);
3189 }
3190
3191 static const POINT *expect_pos;
3192
3193 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
3194 {
3195     if (message == WM_MOUSEMOVE)
3196     {
3197         if (expect_pos && expect_pos->x && expect_pos->y)
3198         {
3199             POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
3200
3201             ClientToScreen(window, &p);
3202             if (expect_pos->x == p.x && expect_pos->y == p.y)
3203                 ++expect_pos;
3204         }
3205     }
3206
3207     return DefWindowProcA(window, message, wparam, lparam);
3208 }
3209
3210 static void test_cursor_pos(void)
3211 {
3212     IDirect3DSurface9 *cursor;
3213     IDirect3DDevice9 *device;
3214     WNDCLASSA wc = {0};
3215     IDirect3D9 *d3d9;
3216     UINT refcount;
3217     HWND window;
3218     HRESULT hr;
3219     BOOL ret;
3220
3221     /* Note that we don't check for movement we're not supposed to receive.
3222      * That's because it's hard to distinguish from the user accidentally
3223      * moving the mouse. */
3224     static const POINT points[] =
3225     {
3226         {50, 50},
3227         {75, 75},
3228         {100, 100},
3229         {125, 125},
3230         {150, 150},
3231         {125, 125},
3232         {150, 150},
3233         {150, 150},
3234         {0, 0},
3235     };
3236
3237     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3238     {
3239         skip("Failed to create IDirect3D9 object, skipping cursor tests.\n");
3240         return;
3241     }
3242
3243     wc.lpfnWndProc = test_cursor_proc;
3244     wc.lpszClassName = "d3d9_test_cursor_wc";
3245     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3246     window = CreateWindow("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3247             0, 0, 320, 240, NULL, NULL, NULL, NULL);
3248     ShowWindow(window, SW_SHOW);
3249
3250     device = create_device(d3d9, window, window, TRUE);
3251     if (!device)
3252     {
3253         skip("Failed to create a D3D device, skipping tests.\n");
3254         goto done;
3255     }
3256
3257     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
3258             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
3259     ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
3260     hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
3261     ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
3262     IDirect3DSurface9_Release(cursor);
3263     ret = IDirect3DDevice9_ShowCursor(device, TRUE);
3264     ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
3265
3266     flush_events();
3267     expect_pos = points;
3268
3269     ret = SetCursorPos(50, 50);
3270     ok(ret, "Failed to set cursor position.\n");
3271     flush_events();
3272
3273     IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3274     flush_events();
3275     /* SetCursorPosition() eats duplicates. */
3276     IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3277     flush_events();
3278
3279     ret = SetCursorPos(100, 100);
3280     ok(ret, "Failed to set cursor position.\n");
3281     flush_events();
3282     /* Even if the position was set with SetCursorPos(). */
3283     IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
3284     flush_events();
3285
3286     IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3287     flush_events();
3288     ret = SetCursorPos(150, 150);
3289     ok(ret, "Failed to set cursor position.\n");
3290     flush_events();
3291     IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3292     flush_events();
3293
3294     IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
3295     flush_events();
3296     /* SetCursorPos() doesn't. */
3297     ret = SetCursorPos(150, 150);
3298     ok(ret, "Failed to set cursor position.\n");
3299     flush_events();
3300
3301     ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
3302        (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
3303
3304     refcount = IDirect3DDevice9_Release(device);
3305     ok(!refcount, "Device has %u references left.\n", refcount);
3306 done:
3307     DestroyWindow(window);
3308     UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
3309     if (d3d9)
3310         IDirect3D9_Release(d3d9);
3311 }
3312
3313 static void test_mode_change(void)
3314 {
3315     RECT fullscreen_rect, focus_rect, r;
3316     IDirect3DSurface9 *backbuffer;
3317     IDirect3DDevice9 *device;
3318     D3DSURFACE_DESC desc;
3319     IDirect3D9 *d3d9;
3320     DEVMODEW devmode;
3321     UINT refcount;
3322     HRESULT hr;
3323     DWORD ret;
3324
3325     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3326     {
3327         skip("Failed to create IDirect3D9 object, skipping mode change tests.\n");
3328         return;
3329     }
3330
3331     focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3332             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3333     device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3334             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3335
3336     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3337     GetWindowRect(focus_window, &focus_rect);
3338
3339     device = create_device(d3d9, device_window, focus_window, FALSE);
3340     if (!device)
3341     {
3342         skip("Failed to create a D3D device, skipping tests.\n");
3343         goto done;
3344     }
3345
3346     memset(&devmode, 0, sizeof(devmode));
3347     devmode.dmSize = sizeof(devmode);
3348     devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3349     devmode.dmPelsWidth = 640;
3350     devmode.dmPelsHeight = 480;
3351
3352     ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3353     ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3354
3355     memset(&devmode, 0, sizeof(devmode));
3356     devmode.dmSize = sizeof(devmode);
3357     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3358     ok(ret, "Failed to get display mode.\n");
3359     ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3360     ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3361
3362     GetWindowRect(device_window, &r);
3363     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3364             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3365             r.left, r.top, r.right, r.bottom);
3366     GetWindowRect(focus_window, &r);
3367     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3368             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3369             r.left, r.top, r.right, r.bottom);
3370
3371     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3372     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3373     hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
3374     ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3375     ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3376     ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3377     IDirect3DSurface9_Release(backbuffer);
3378
3379     refcount = IDirect3DDevice9_Release(device);
3380     ok(!refcount, "Device has %u references left.\n", refcount);
3381
3382     memset(&devmode, 0, sizeof(devmode));
3383     devmode.dmSize = sizeof(devmode);
3384     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3385     ok(ret, "Failed to get display mode.\n");
3386     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3387     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3388
3389 done:
3390     DestroyWindow(device_window);
3391     DestroyWindow(focus_window);
3392     if (d3d9)
3393         IDirect3D9_Release(d3d9);
3394
3395     memset(&devmode, 0, sizeof(devmode));
3396     devmode.dmSize = sizeof(devmode);
3397     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3398     ok(ret, "Failed to get display mode.\n");
3399     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3400     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3401 }
3402
3403 static void test_device_window_reset(void)
3404 {
3405     RECT fullscreen_rect, device_rect, r;
3406     IDirect3DDevice9 *device;
3407     WNDCLASSA wc = {0};
3408     IDirect3D9 *d3d9;
3409     LONG_PTR proc;
3410     HRESULT hr;
3411     ULONG ref;
3412
3413     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3414     {
3415         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3416         return;
3417     }
3418
3419     wc.lpfnWndProc = test_proc;
3420     wc.lpszClassName = "d3d9_test_wndproc_wc";
3421     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3422
3423     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3424             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3425     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3426             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3427
3428     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3429     GetWindowRect(device_window, &device_rect);
3430
3431     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3432     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3433             (LONG_PTR)test_proc, proc);
3434     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3435     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3436             (LONG_PTR)test_proc, proc);
3437
3438     device = create_device(d3d9, NULL, focus_window, FALSE);
3439     if (!device)
3440     {
3441         skip("Failed to create a D3D device, skipping tests.\n");
3442         goto done;
3443     }
3444
3445     GetWindowRect(focus_window, &r);
3446     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3447             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3448             r.left, r.top, r.right, r.bottom);
3449     GetWindowRect(device_window, &r);
3450     ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3451             device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3452             r.left, r.top, r.right, r.bottom);
3453
3454     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3455     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3456             (LONG_PTR)test_proc, proc);
3457     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3458     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3459             (LONG_PTR)test_proc, proc);
3460
3461     hr = reset_device(device, device_window, FALSE);
3462     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3463
3464     GetWindowRect(focus_window, &r);
3465     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3466             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3467             r.left, r.top, r.right, r.bottom);
3468     GetWindowRect(device_window, &r);
3469     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3470             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3471             r.left, r.top, r.right, r.bottom);
3472
3473     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3474     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3475             (LONG_PTR)test_proc, proc);
3476     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3477     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3478             (LONG_PTR)test_proc, proc);
3479
3480     ref = IDirect3DDevice9_Release(device);
3481     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3482
3483 done:
3484     IDirect3D9_Release(d3d9);
3485     DestroyWindow(device_window);
3486     DestroyWindow(focus_window);
3487     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3488 }
3489
3490 static void test_reset_resources(void)
3491 {
3492     IDirect3DSurface9 *surface, *rt;
3493     IDirect3DTexture9 *texture;
3494     IDirect3DDevice9 *device;
3495     IDirect3D9 *d3d9;
3496     unsigned int i;
3497     D3DCAPS9 caps;
3498     HWND window;
3499     HRESULT hr;
3500     ULONG ref;
3501
3502     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3503             0, 0, 640, 480, 0, 0, 0, 0);
3504
3505     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3506     {
3507         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3508         DestroyWindow(window);
3509         return;
3510     }
3511
3512     if (!(device = create_device(d3d9, window, window, TRUE)))
3513     {
3514         skip("Failed to create a D3D device, skipping tests.\n");
3515         goto done;
3516     }
3517
3518     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3519     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3520
3521     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_DEPTHSTENCIL,
3522             D3DFMT_D24S8, D3DPOOL_DEFAULT, &texture, NULL);
3523     ok(SUCCEEDED(hr), "Failed to create depth/stencil texture, hr %#x.\n", hr);
3524     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3525     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3526     IDirect3DTexture9_Release(texture);
3527     hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
3528     ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
3529     IDirect3DSurface9_Release(surface);
3530
3531     for (i = 0; i < caps.NumSimultaneousRTs; ++i)
3532     {
3533         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3534                 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
3535         ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
3536         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3537         ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
3538         IDirect3DTexture9_Release(texture);
3539         hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
3540         ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
3541         IDirect3DSurface9_Release(surface);
3542     }
3543
3544     hr = reset_device(device, device_window, TRUE);
3545     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3546
3547     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3548     ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3549     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
3550     ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3551     ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3552     IDirect3DSurface9_Release(surface);
3553     IDirect3DSurface9_Release(rt);
3554
3555     for (i = 1; i < caps.NumSimultaneousRTs; ++i)
3556     {
3557         hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
3558         ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
3559     }
3560
3561     ref = IDirect3DDevice9_Release(device);
3562     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3563
3564 done:
3565     IDirect3D9_Release(d3d9);
3566     DestroyWindow(window);
3567 }
3568
3569 static void test_set_rt_vp_scissor(void)
3570 {
3571     IDirect3DStateBlock9 *stateblock;
3572     IDirect3DDevice9 *device;
3573     IDirect3DSurface9 *rt;
3574     IDirect3D9 *d3d9;
3575     D3DVIEWPORT9 vp;
3576     UINT refcount;
3577     HWND window;
3578     HRESULT hr;
3579     RECT rect;
3580
3581     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3582     {
3583         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3584         return;
3585     }
3586
3587     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3588             0, 0, 640, 480, 0, 0, 0, 0);
3589     if (!(device = create_device(d3d9, window, window, TRUE)))
3590     {
3591         skip("Failed to create a D3D device, skipping tests.\n");
3592         DestroyWindow(window);
3593         return;
3594     }
3595
3596     hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3597             D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
3598     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3599
3600     hr = IDirect3DDevice9_GetViewport(device, &vp);
3601     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3602     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3603     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3604     ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3605     ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3606     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3607     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3608
3609     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3610     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3611     ok(rect.left == 0 && rect.top == 0 && rect.right == screen_width && rect.bottom == screen_height,
3612             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3613             rect.left, rect.top, rect.right, rect.bottom);
3614
3615     hr = IDirect3DDevice9_BeginStateBlock(device);
3616     ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3617
3618     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3619     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3620
3621     hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
3622     ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3623     IDirect3DStateBlock9_Release(stateblock);
3624
3625     hr = IDirect3DDevice9_GetViewport(device, &vp);
3626     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3627     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3628     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3629     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3630     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3631     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3632     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3633
3634     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3635     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3636     ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3637             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3638             rect.left, rect.top, rect.right, rect.bottom);
3639
3640     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3641     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3642
3643     vp.X = 10;
3644     vp.Y = 20;
3645     vp.Width = 30;
3646     vp.Height = 40;
3647     vp.MinZ = 0.25f;
3648     vp.MaxZ = 0.75f;
3649     hr = IDirect3DDevice9_SetViewport(device, &vp);
3650     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3651
3652     SetRect(&rect, 50, 60, 70, 80);
3653     hr = IDirect3DDevice9_SetScissorRect(device, &rect);
3654     ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
3655
3656     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3657     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3658
3659     hr = IDirect3DDevice9_GetViewport(device, &vp);
3660     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3661     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3662     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3663     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3664     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3665     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3666     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3667
3668     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3669     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3670     ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3671             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3672             rect.left, rect.top, rect.right, rect.bottom);
3673
3674     IDirect3DSurface9_Release(rt);
3675     refcount = IDirect3DDevice9_Release(device);
3676     ok(!refcount, "Device has %u references left.\n", refcount);
3677     IDirect3D9_Release(d3d9);
3678     DestroyWindow(window);
3679 }
3680
3681 static void test_volume_get_container(void)
3682 {
3683     IDirect3DVolumeTexture9 *texture = NULL;
3684     IDirect3DVolume9 *volume = NULL;
3685     IDirect3DDevice9 *device;
3686     IUnknown *container;
3687     IDirect3D9 *d3d9;
3688     ULONG refcount;
3689     D3DCAPS9 caps;
3690     HWND window;
3691     HRESULT hr;
3692
3693     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3694     {
3695         skip("Failed to create d3d9 object, skipping tests.\n");
3696         return;
3697     }
3698
3699     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3700             0, 0, 640, 480, 0, 0, 0, 0);
3701     if (!(device = create_device(d3d9, window, window, TRUE)))
3702     {
3703         skip("Failed to create a D3D device, skipping tests.\n");
3704         IDirect3D9_Release(d3d9);
3705         DestroyWindow(window);
3706         return;
3707     }
3708
3709     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3710     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3711     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3712     {
3713         skip("No volume texture support, skipping tests.\n");
3714         IDirect3DDevice9_Release(device);
3715         IDirect3D9_Release(d3d9);
3716         DestroyWindow(window);
3717         return;
3718     }
3719
3720     hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3721             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3722     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3723     ok(!!texture, "Got unexpected texture %p.\n", texture);
3724
3725     hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3726     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3727     ok(!!volume, "Got unexpected volume %p.\n", volume);
3728
3729     /* These should work... */
3730     container = NULL;
3731     hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
3732     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3733     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3734     IUnknown_Release(container);
3735
3736     container = NULL;
3737     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
3738     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3739     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3740     IUnknown_Release(container);
3741
3742     container = NULL;
3743     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
3744     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3745     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3746     IUnknown_Release(container);
3747
3748     container = NULL;
3749     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
3750     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3751     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3752     IUnknown_Release(container);
3753
3754     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3755     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
3756     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3757     ok(!container, "Got unexpected container %p.\n", container);
3758
3759     IDirect3DVolume9_Release(volume);
3760     IDirect3DVolumeTexture9_Release(texture);
3761     refcount = IDirect3DDevice9_Release(device);
3762     ok(!refcount, "Device has %u references left.\n", refcount);
3763     IDirect3D9_Release(d3d9);
3764     DestroyWindow(window);
3765 }
3766
3767 static void test_volume_resource(void)
3768 {
3769     IDirect3DVolumeTexture9 *texture;
3770     IDirect3DResource9 *resource;
3771     IDirect3DVolume9 *volume;
3772     IDirect3DDevice9 *device;
3773     IDirect3D9 *d3d9;
3774     ULONG refcount;
3775     D3DCAPS9 caps;
3776     HWND window;
3777     HRESULT hr;
3778
3779     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3780     {
3781         skip("Failed to create d3d9 object, skipping tests.\n");
3782         return;
3783     }
3784
3785     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3786             0, 0, 640, 480, 0, 0, 0, 0);
3787     if (!(device = create_device(d3d9, window, window, TRUE)))
3788     {
3789         skip("Failed to create a D3D device, skipping tests.\n");
3790         IDirect3D9_Release(d3d9);
3791         DestroyWindow(window);
3792         return;
3793     }
3794
3795     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3796     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3797     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3798     {
3799         skip("No volume texture support, skipping tests.\n");
3800         IDirect3DDevice9_Release(device);
3801         IDirect3D9_Release(d3d9);
3802         DestroyWindow(window);
3803         return;
3804     }
3805
3806     hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3807             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3808     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3809     hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3810     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3811     IDirect3DVolumeTexture9_Release(texture);
3812
3813     hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
3814     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3815
3816     IDirect3DVolume9_Release(volume);
3817     refcount = IDirect3DDevice9_Release(device);
3818     ok(!refcount, "Device has %u references left.\n", refcount);
3819     IDirect3D9_Release(d3d9);
3820     DestroyWindow(window);
3821 }
3822
3823 static void test_vb_lock_flags(void)
3824 {
3825     static const struct
3826     {
3827         DWORD flags;
3828         const char *debug_string;
3829         HRESULT win7_result;
3830     }
3831     test_data[] =
3832     {
3833         {D3DLOCK_READONLY,                          "D3DLOCK_READONLY",                         D3D_OK            },
3834         {D3DLOCK_DISCARD,                           "D3DLOCK_DISCARD",                          D3D_OK            },
3835         {D3DLOCK_NOOVERWRITE,                       "D3DLOCK_NOOVERWRITE",                      D3D_OK            },
3836         {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD,     "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD",    D3D_OK            },
3837         {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY,    "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY",   D3D_OK            },
3838         {D3DLOCK_READONLY | D3DLOCK_DISCARD,        "D3DLOCK_READONLY | D3DLOCK_DISCARD",       D3DERR_INVALIDCALL},
3839         /* Completely bogus flags aren't an error. */
3840         {0xdeadbeef,                                "0xdeadbeef",                               D3DERR_INVALIDCALL},
3841     };
3842     IDirect3DVertexBuffer9 *buffer;
3843     IDirect3DDevice9 *device;
3844     IDirect3D9 *d3d9;
3845     unsigned int i;
3846     ULONG refcount;
3847     HWND window;
3848     HRESULT hr;
3849     void *data;
3850
3851     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3852     {
3853         skip("Failed to create d3d9 object, skipping tests.\n");
3854         return;
3855     }
3856
3857     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3858             0, 0, 640, 480, 0, 0, 0, 0);
3859     if (!(device = create_device(d3d9, window, window, TRUE)))
3860     {
3861         skip("Failed to create a D3D device, skipping tests.\n");
3862         IDirect3D9_Release(d3d9);
3863         DestroyWindow(window);
3864         return;
3865     }
3866
3867     hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
3868     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3869
3870     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
3871     {
3872         hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
3873         /* Windows XP always returns D3D_OK even with flags that don't make
3874          * sense. Windows 7 returns an error. At least one game (Shaiya)
3875          * depends on the Windows XP result, so mark the Windows 7 behavior as
3876          * broken. */
3877         ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
3878                 hr, test_data[i].debug_string);
3879         if (SUCCEEDED(hr))
3880         {
3881             ok(!!data, "Got unexpected data %p.\n", data);
3882             hr = IDirect3DVertexBuffer9_Unlock(buffer);
3883             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3884         }
3885     }
3886
3887     IDirect3DVertexBuffer9_Release(buffer);
3888     refcount = IDirect3DDevice9_Release(device);
3889     ok(!refcount, "Device has %u references left.\n", refcount);
3890     IDirect3D9_Release(d3d9);
3891     DestroyWindow(window);
3892 }
3893
3894 static const char *debug_d3dpool(D3DPOOL pool)
3895 {
3896     switch (pool)
3897     {
3898         case D3DPOOL_DEFAULT:
3899             return "D3DPOOL_DEFAULT";
3900         case D3DPOOL_SYSTEMMEM:
3901             return "D3DPOOL_SYSTEMMEM";
3902         case D3DPOOL_SCRATCH:
3903             return "D3DPOOL_SCRATCH";
3904         case D3DPOOL_MANAGED:
3905             return "D3DPOOL_MANAGED";
3906         default:
3907             return "unknown pool";
3908     }
3909 }
3910
3911 static void test_vertex_buffer_alignment(void)
3912 {
3913     static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
3914     static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
3915     IDirect3DVertexBuffer9 *buffer = NULL;
3916     const unsigned int align = 16;
3917     IDirect3DDevice9 *device;
3918     unsigned int i, j;
3919     IDirect3D9 *d3d9;
3920     ULONG refcount;
3921     HWND window;
3922     HRESULT hr;
3923     void *data;
3924
3925     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3926     {
3927         skip("Failed to create d3d9 object, skipping tests.\n");
3928         return;
3929     }
3930
3931     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3932             0, 0, 640, 480, 0, 0, 0, 0);
3933     if (!(device = create_device(d3d9, window, window, TRUE)))
3934     {
3935         skip("Failed to create a D3D device, skipping tests.\n");
3936         IDirect3D9_Release(d3d9);
3937         DestroyWindow(window);
3938         return;
3939     }
3940
3941     for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
3942     {
3943         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
3944         {
3945             hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
3946             if (pools[j] == D3DPOOL_SCRATCH)
3947                 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
3948             else
3949                 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
3950                         debug_d3dpool(pools[j]), sizes[i], hr);
3951             if (FAILED(hr))
3952                 continue;
3953
3954             hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
3955             ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3956             ok(!((DWORD_PTR)data & (align - 1)),
3957                     "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
3958                     data, align, sizes[i], debug_d3dpool(pools[j]));
3959             hr = IDirect3DVertexBuffer9_Unlock(buffer);
3960             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3961             IDirect3DVertexBuffer9_Release(buffer);
3962         }
3963     }
3964
3965     refcount = IDirect3DDevice9_Release(device);
3966     ok(!refcount, "Device has %u references left.\n", refcount);
3967     IDirect3D9_Release(d3d9);
3968     DestroyWindow(window);
3969 }
3970
3971 static void test_query_support(void)
3972 {
3973     static const D3DQUERYTYPE queries[] =
3974     {
3975         D3DQUERYTYPE_VCACHE,
3976         D3DQUERYTYPE_RESOURCEMANAGER,
3977         D3DQUERYTYPE_VERTEXSTATS,
3978         D3DQUERYTYPE_EVENT,
3979         D3DQUERYTYPE_OCCLUSION,
3980         D3DQUERYTYPE_TIMESTAMP,
3981         D3DQUERYTYPE_TIMESTAMPDISJOINT,
3982         D3DQUERYTYPE_TIMESTAMPFREQ,
3983         D3DQUERYTYPE_PIPELINETIMINGS,
3984         D3DQUERYTYPE_INTERFACETIMINGS,
3985         D3DQUERYTYPE_VERTEXTIMINGS,
3986         D3DQUERYTYPE_PIXELTIMINGS,
3987         D3DQUERYTYPE_BANDWIDTHTIMINGS,
3988         D3DQUERYTYPE_CACHEUTILIZATION,
3989     };
3990     IDirect3DQuery9 *query = NULL;
3991     IDirect3DDevice9 *device;
3992     IDirect3D9 *d3d9;
3993     unsigned int i;
3994     ULONG refcount;
3995     BOOL supported;
3996     HWND window;
3997     HRESULT hr;
3998
3999     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4000     {
4001         skip("Failed to create d3d9 object, skipping tests.\n");
4002         return;
4003     }
4004
4005     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4006             0, 0, 640, 480, 0, 0, 0, 0);
4007     if (!(device = create_device(d3d9, window, window, TRUE)))
4008     {
4009         skip("Failed to create a D3D device, skipping tests.\n");
4010         IDirect3D9_Release(d3d9);
4011         DestroyWindow(window);
4012         return;
4013     }
4014
4015     for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
4016     {
4017         hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
4018         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4019
4020         supported = hr == D3D_OK;
4021
4022         hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
4023         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4024
4025         ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
4026         ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
4027
4028         if (query)
4029         {
4030             IDirect3DQuery9_Release(query);
4031             query = NULL;
4032         }
4033     }
4034
4035     refcount = IDirect3DDevice9_Release(device);
4036     ok(!refcount, "Device has %u references left.\n", refcount);
4037     IDirect3D9_Release(d3d9);
4038     DestroyWindow(window);
4039 }
4040
4041 static void test_occlusion_query_states(void)
4042 {
4043     static const float point[3] = {0.0, 0.0, 0.0};
4044     IDirect3DQuery9 *query = NULL;
4045     unsigned int data_size, i;
4046     IDirect3DDevice9 *device;
4047     IDirect3D9 *d3d9;
4048     ULONG refcount;
4049     HWND window;
4050     HRESULT hr;
4051     BYTE *data;
4052
4053     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4054     {
4055         skip("Failed to create d3d9 object, skipping tests.\n");
4056         return;
4057     }
4058
4059     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4060             0, 0, 640, 480, 0, 0, 0, 0);
4061     if (!(device = create_device(d3d9, window, window, TRUE)))
4062     {
4063         skip("Failed to create a D3D device, skipping tests.\n");
4064         IDirect3D9_Release(d3d9);
4065         DestroyWindow(window);
4066         return;
4067     }
4068
4069     hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
4070     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
4071     if (!query)
4072     {
4073         skip("Occlusion queries are not supported, skipping tests.\n");
4074         IDirect3DDevice9_Release(device);
4075         IDirect3D9_Release(d3d9);
4076         DestroyWindow(window);
4077         return;
4078     }
4079
4080     data_size = IDirect3DQuery9_GetDataSize(query);
4081     data = HeapAlloc(GetProcessHeap(), 0, data_size);
4082
4083     hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4084     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4085     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4086     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4087
4088     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4089     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4090     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4091     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4092     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4093     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4094
4095     *((DWORD *)data) = 0x12345678;
4096     hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4097     ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4098     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4099     ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4100     if (hr == D3D_OK)
4101         ok(!*(DWORD *)data, "Got unexpected query result %u.\n", *(DWORD *)data);
4102
4103     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4104     ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
4105     hr = IDirect3DDevice9_BeginScene(device);
4106     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4107     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
4108     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4109     hr = IDirect3DDevice9_EndScene(device);
4110     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4111
4112     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4113     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4114     for (i = 0; i < 500; ++i)
4115     {
4116         if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4117             break;
4118         Sleep(10);
4119     }
4120     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4121
4122     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4123     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4124     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4125     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4126
4127     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4128     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4129     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4130     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4131     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4132     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4133
4134     HeapFree(GetProcessHeap(), 0, data);
4135     IDirect3DQuery9_Release(query);
4136     refcount = IDirect3DDevice9_Release(device);
4137     ok(!refcount, "Device has %u references left.\n", refcount);
4138     IDirect3D9_Release(d3d9);
4139     DestroyWindow(window);
4140 }
4141
4142 START_TEST(device)
4143 {
4144     HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
4145     WNDCLASS wc = {0};
4146
4147     wc.lpfnWndProc = DefWindowProc;
4148     wc.lpszClassName = "d3d9_test_wc";
4149     RegisterClass(&wc);
4150
4151     if (!d3d9_handle)
4152     {
4153         skip("Could not load d3d9.dll\n");
4154         goto out;
4155     }
4156
4157     pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
4158     ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
4159     if (pDirect3DCreate9)
4160     {
4161         IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
4162         if(!d3d9)
4163         {
4164             skip("could not create D3D9 object\n");
4165             goto out;
4166         }
4167         IDirect3D9_Release(d3d9);
4168
4169         screen_width = GetSystemMetrics(SM_CXSCREEN);
4170         screen_height = GetSystemMetrics(SM_CYSCREEN);
4171
4172         test_fpu_setup();
4173         test_multi_device();
4174         test_display_formats();
4175         test_display_modes();
4176         test_swapchain();
4177         test_refcount();
4178         test_mipmap_levels();
4179         test_checkdevicemultisampletype();
4180         test_cursor();
4181         test_cursor_pos();
4182         test_reset_fullscreen();
4183         test_reset();
4184         test_scene();
4185         test_limits();
4186         test_depthstenciltest();
4187         test_get_rt();
4188         test_draw_indexed();
4189         test_null_stream();
4190         test_lights();
4191         test_set_stream_source();
4192         test_scissor_size();
4193         test_wndproc();
4194         test_wndproc_windowed();
4195         test_window_style();
4196         test_mode_change();
4197         test_device_window_reset();
4198         test_reset_resources();
4199         test_set_rt_vp_scissor();
4200         test_volume_get_container();
4201         test_volume_resource();
4202         test_vb_lock_flags();
4203         test_vertex_buffer_alignment();
4204         test_query_support();
4205         test_occlusion_query_states();
4206     }
4207
4208 out:
4209     UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));
4210 }