wbemprox: Return an empty object if the path is NULL or empty.
[wine] / dlls / d3d9 / tests / device.c
1 /*
2  * Copyright (C) 2006 Vitaliy Margolen
3  * Copyright (C) 2006 Chris Robinson
4  * Copyright 2006-2008, 2010-2011, 2013 Stefan Dösinger for CodeWeavers
5  * Copyright 2005, 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 const DWORD simple_vs[] =
35 {
36     0xfffe0101,                                                             /* vs_1_1                       */
37     0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position0 v0             */
38     0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000,                         /* dp4 oPos.x, v0, c0           */
39     0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001,                         /* dp4 oPos.y, v0, c1           */
40     0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002,                         /* dp4 oPos.z, v0, c2           */
41     0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003,                         /* dp4 oPos.w, v0, c3           */
42     0x0000ffff,                                                             /* end                          */
43 };
44
45 static DWORD simple_ps[] =
46 {
47     0xffff0101,                                                             /* ps_1_1                       */
48     0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
49     0x00000042, 0xb00f0000,                                                 /* tex t0                       */
50     0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000,                         /* dp3 r0, c1, c0               */
51     0x00000005, 0x800f0000, 0x90e40000, 0x80e40000,                         /* mul r0, v0, r0               */
52     0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000,                         /* mul r0, t0, r0               */
53     0x0000ffff,                                                             /* end                          */
54 };
55
56 static int get_refcount(IUnknown *object)
57 {
58     IUnknown_AddRef( object );
59     return IUnknown_Release( object );
60 }
61
62 /* try to make sure pending X events have been processed before continuing */
63 static void flush_events(void)
64 {
65     MSG msg;
66     int diff = 200;
67     int min_timeout = 100;
68     DWORD time = GetTickCount() + diff;
69
70     while (diff > 0)
71     {
72         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
73         while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
74         diff = time - GetTickCount();
75     }
76 }
77
78 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND device_window, HWND focus_window, BOOL windowed)
79 {
80     D3DPRESENT_PARAMETERS present_parameters = {0};
81     IDirect3DDevice9 *device;
82
83     present_parameters.Windowed = windowed;
84     present_parameters.hDeviceWindow = device_window;
85     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
86     present_parameters.BackBufferWidth = screen_width;
87     present_parameters.BackBufferHeight = screen_height;
88     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
89     present_parameters.EnableAutoDepthStencil = TRUE;
90     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
91
92     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
93             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
94
95     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
96     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
97             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
98
99     if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
100             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
101
102     return NULL;
103 }
104
105 static HRESULT reset_device(IDirect3DDevice9 *device, HWND device_window, BOOL windowed)
106 {
107     D3DPRESENT_PARAMETERS present_parameters = {0};
108
109     present_parameters.Windowed = windowed;
110     present_parameters.hDeviceWindow = device_window;
111     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
112     present_parameters.BackBufferWidth = screen_width;
113     present_parameters.BackBufferHeight = screen_height;
114     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
115     present_parameters.EnableAutoDepthStencil = TRUE;
116     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
117
118     return IDirect3DDevice9_Reset(device, &present_parameters);
119 }
120
121 #define CHECK_CALL(r,c,d,rc) \
122     if (SUCCEEDED(r)) {\
123         int tmp1 = get_refcount( (IUnknown *)d ); \
124         int rc_new = rc; \
125         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
126     } else {\
127         trace("%s failed: %08x\n", c, r); \
128     }
129
130 #define CHECK_RELEASE(obj,d,rc) \
131     if (obj) { \
132         int tmp1, rc_new = rc; \
133         IUnknown_Release( (IUnknown*)obj ); \
134         tmp1 = get_refcount( (IUnknown *)d ); \
135         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
136     }
137
138 #define CHECK_REFCOUNT(obj,rc) \
139     { \
140         int rc_new = rc; \
141         int count = get_refcount( (IUnknown *)obj ); \
142         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
143     }
144
145 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
146     { \
147         int rc_new = rc; \
148         int count = IUnknown_Release( (IUnknown *)obj ); \
149         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
150     }
151
152 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
153     { \
154         int rc_new = rc; \
155         int count = IUnknown_AddRef( (IUnknown *)obj ); \
156         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
157     }
158
159 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
160     { \
161         void *container_ptr = (void *)0x1337c0d3; \
162         hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
163         ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
164             "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
165         if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
166     }
167
168 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
169 {
170     IDirect3DBaseTexture9* texture = NULL;
171     HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
172             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
173
174     if (SUCCEEDED(hr)) {
175         DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
176         ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
177     } else
178         trace("CreateTexture failed: %08x\n", hr);
179
180     if (texture) IDirect3DBaseTexture9_Release( texture );
181 }
182
183 static void test_mipmap_levels(void)
184 {
185
186     HRESULT               hr;
187     HWND                  hwnd = NULL;
188
189     IDirect3D9            *pD3d = NULL;
190     IDirect3DDevice9      *pDevice = NULL;
191     D3DPRESENT_PARAMETERS d3dpp;
192     D3DDISPLAYMODE        d3ddm;
193
194     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
195     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
196     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
197     ok(hwnd != NULL, "Failed to create window\n");
198     if (!pD3d || !hwnd) goto cleanup;
199
200     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
201     ZeroMemory( &d3dpp, sizeof(d3dpp) );
202     d3dpp.Windowed         = TRUE;
203     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
204     d3dpp.BackBufferFormat = d3ddm.Format;
205
206     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
207                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
208     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
209     if (FAILED(hr)) {
210         skip("failed to create a d3d device\n");
211         goto cleanup;
212     }
213
214     check_mipmap_levels(pDevice, 32, 32, 6);
215     check_mipmap_levels(pDevice, 256, 1, 9);
216     check_mipmap_levels(pDevice, 1, 256, 9);
217     check_mipmap_levels(pDevice, 1, 1, 1);
218
219 cleanup:
220     if (pDevice)
221     {
222         UINT refcount = IDirect3DDevice9_Release( pDevice );
223         ok(!refcount, "Device has %u references left.\n", refcount);
224     }
225     if (pD3d) IDirect3D9_Release( pD3d );
226     DestroyWindow( hwnd );
227 }
228
229 static void test_checkdevicemultisampletype(void)
230 {
231
232     HRESULT               hr;
233     HWND                  hwnd = NULL;
234
235     IDirect3D9            *pD3d = NULL;
236     IDirect3DDevice9      *pDevice = NULL;
237     D3DPRESENT_PARAMETERS d3dpp;
238     D3DDISPLAYMODE        d3ddm;
239     DWORD                 qualityLevels;
240
241     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
242     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
243     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
244     ok(hwnd != NULL, "Failed to create window\n");
245     if (!pD3d || !hwnd) goto cleanup;
246
247     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
248     ZeroMemory( &d3dpp, sizeof(d3dpp) );
249     d3dpp.Windowed         = TRUE;
250     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
251     d3dpp.BackBufferFormat = d3ddm.Format;
252
253     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
254                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
255     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
256     if (FAILED(hr)) {
257         skip("failed to create a d3d device\n");
258         goto cleanup;
259     }
260
261     qualityLevels = 0;
262
263     hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE,
264     D3DMULTISAMPLE_NONE, &qualityLevels);
265     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
266     if(hr == D3DERR_NOTAVAILABLE)
267     {
268         skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
269         goto cleanup;
270     }
271     ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
272
273     hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, FALSE,
274     D3DMULTISAMPLE_NONE, &qualityLevels);
275     ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
276     ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
277
278 cleanup:
279     if (pDevice)
280     {
281         UINT refcount = IDirect3DDevice9_Release( pDevice );
282         ok(!refcount, "Device has %u references left.\n", refcount);
283     }
284     if (pD3d) IDirect3D9_Release( pD3d );
285     DestroyWindow( hwnd );
286 }
287
288 static void test_swapchain(void)
289 {
290     HRESULT                      hr;
291     HWND                         hwnd               = NULL;
292     IDirect3D9                  *pD3d               = NULL;
293     IDirect3DDevice9            *pDevice            = NULL;
294     IDirect3DSwapChain9         *swapchain0         = NULL;
295     IDirect3DSwapChain9         *swapchain1         = NULL;
296     IDirect3DSwapChain9         *swapchain2         = NULL;
297     IDirect3DSwapChain9         *swapchain3         = NULL;
298     IDirect3DSwapChain9         *swapchainX         = NULL;
299     IDirect3DSurface9           *backbuffer         = NULL;
300     D3DPRESENT_PARAMETERS        d3dpp;
301     D3DDISPLAYMODE               d3ddm;
302
303     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
304     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
305     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
306     ok(hwnd != NULL, "Failed to create window\n");
307     if (!pD3d || !hwnd) goto cleanup;
308
309     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
310     ZeroMemory( &d3dpp, sizeof(d3dpp) );
311     d3dpp.Windowed         = TRUE;
312     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
313     d3dpp.BackBufferFormat = d3ddm.Format;
314     d3dpp.BackBufferCount  = 0;
315
316     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
317                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
318     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
319        "Failed to create IDirect3D9Device (%08x)\n", hr);
320     if (FAILED(hr)) goto cleanup;
321
322     /* Check if the back buffer count was modified */
323     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
324
325     /* Get the implicit swapchain */
326     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &swapchain0);
327     ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
328     if(swapchain0) IDirect3DSwapChain9_Release(swapchain0);
329
330     /* Check if there is a back buffer */
331     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
332     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
333     ok(backbuffer != NULL, "The back buffer is NULL\n");
334     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
335
336     /* Try to get a nonexistent swapchain */
337     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
338     ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
339     ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
340     if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
341
342     /* Create a bunch of swapchains */
343     d3dpp.BackBufferCount = 0;
344     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
345     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
346     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
347
348     d3dpp.BackBufferCount  = 1;
349     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
350     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
351
352     d3dpp.BackBufferCount  = 2;
353     hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
354     ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
355     if(SUCCEEDED(hr)) {
356         /* Swapchain 3, created with backbuffercount 2 */
357         backbuffer = (void *) 0xdeadbeef;
358         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
359         ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
360         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
361         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
362
363         backbuffer = (void *) 0xdeadbeef;
364         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
365         ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
366         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
367         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
368
369         backbuffer = (void *) 0xdeadbeef;
370         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
371         ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
372         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
373         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
374
375         backbuffer = (void *) 0xdeadbeef;
376         hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
377         ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
378         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
379         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
380     }
381
382     /* Check the back buffers of the swapchains */
383     /* Swapchain 1, created with backbuffercount 0 */
384     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
385     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
386     ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
387     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
388
389     backbuffer = (void *) 0xdeadbeef;
390     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
391     ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
392     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
393     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
394
395     /* Swapchain 2 - created with backbuffercount 1 */
396     backbuffer = (void *) 0xdeadbeef;
397     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
398     ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
399     ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
400     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
401
402     backbuffer = (void *) 0xdeadbeef;
403     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
404     ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
405     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
406     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
407
408     backbuffer = (void *) 0xdeadbeef;
409     hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
410     ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
411     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
412     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
413
414     /* Try getSwapChain on a manually created swapchain
415      * it should fail, apparently GetSwapChain only returns implicit swapchains
416      */
417     swapchainX = (void *) 0xdeadbeef;
418     hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
419     ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
420     ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
421     if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
422
423 cleanup:
424     if(swapchain1) IDirect3DSwapChain9_Release(swapchain1);
425     if(swapchain2) IDirect3DSwapChain9_Release(swapchain2);
426     if(swapchain3) IDirect3DSwapChain9_Release(swapchain3);
427     if (pDevice)
428     {
429         UINT refcount = IDirect3DDevice9_Release(pDevice);
430         ok(!refcount, "Device has %u references left.\n", refcount);
431     }
432     if (pD3d) IDirect3D9_Release(pD3d);
433     DestroyWindow( hwnd );
434 }
435
436 static void test_refcount(void)
437 {
438     HRESULT                      hr;
439     HWND                         hwnd               = NULL;
440     IDirect3D9                  *pD3d               = NULL;
441     IDirect3D9                  *pD3d2              = NULL;
442     IDirect3DDevice9            *pDevice            = NULL;
443     IDirect3DVertexBuffer9      *pVertexBuffer      = NULL;
444     IDirect3DIndexBuffer9       *pIndexBuffer       = NULL;
445     IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
446     IDirect3DVertexShader9      *pVertexShader      = NULL;
447     IDirect3DPixelShader9       *pPixelShader       = NULL;
448     IDirect3DCubeTexture9       *pCubeTexture       = NULL;
449     IDirect3DTexture9           *pTexture           = NULL;
450     IDirect3DVolumeTexture9     *pVolumeTexture     = NULL;
451     IDirect3DVolume9            *pVolumeLevel       = NULL;
452     IDirect3DSurface9           *pStencilSurface    = NULL;
453     IDirect3DSurface9           *pOffscreenSurface  = NULL;
454     IDirect3DSurface9           *pRenderTarget      = NULL;
455     IDirect3DSurface9           *pRenderTarget2     = NULL;
456     IDirect3DSurface9           *pRenderTarget3     = NULL;
457     IDirect3DSurface9           *pTextureLevel      = NULL;
458     IDirect3DSurface9           *pBackBuffer        = NULL;
459     IDirect3DStateBlock9        *pStateBlock        = NULL;
460     IDirect3DStateBlock9        *pStateBlock1       = NULL;
461     IDirect3DSwapChain9         *pSwapChain         = NULL;
462     IDirect3DQuery9             *pQuery             = NULL;
463     D3DPRESENT_PARAMETERS        d3dpp;
464     D3DDISPLAYMODE               d3ddm;
465     int                          refcount = 0, tmp;
466
467     D3DVERTEXELEMENT9 decl[] =
468     {
469         D3DDECL_END()
470     };
471
472     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
473     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
474     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
475     ok(hwnd != NULL, "Failed to create window\n");
476     if (!pD3d || !hwnd) goto cleanup;
477
478     CHECK_REFCOUNT( pD3d, 1 );
479
480     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
481     ZeroMemory( &d3dpp, sizeof(d3dpp) );
482     d3dpp.Windowed         = TRUE;
483     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
484     d3dpp.BackBufferFormat = d3ddm.Format;
485     d3dpp.EnableAutoDepthStencil = TRUE;
486     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
487
488     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
489                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
490     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
491        "Failed to create IDirect3D9Device (%08x)\n", hr);
492     if (FAILED(hr)) goto cleanup;
493
494     refcount = get_refcount( (IUnknown *)pDevice );
495     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
496
497     CHECK_REFCOUNT( pD3d, 2 );
498
499     hr = IDirect3DDevice9_GetDirect3D(pDevice, &pD3d2);
500     CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
501
502     ok(pD3d2 == pD3d, "Expected IDirect3D9 pointers to be equal\n");
503     CHECK_REFCOUNT( pD3d, 3 );
504     CHECK_RELEASE_REFCOUNT( pD3d, 2 );
505
506     /**
507      * Check refcount of implicit surfaces and implicit swapchain. Findings:
508      *   - the container is the device OR swapchain
509      *   - they hold a reference to the device
510      *   - they are created with a refcount of 0 (Get/Release returns original refcount)
511      *   - they are not freed if refcount reaches 0.
512      *   - the refcount is not forwarded to the container.
513      */
514     hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
515     CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
516     if (pSwapChain)
517     {
518         CHECK_REFCOUNT( pSwapChain, 1);
519
520         hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
521         CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
522         CHECK_REFCOUNT( pSwapChain, 1);
523         if(pRenderTarget)
524         {
525             CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
526             CHECK_REFCOUNT( pRenderTarget, 1);
527
528             CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
529             CHECK_REFCOUNT(pDevice, refcount);
530             CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
531             CHECK_REFCOUNT(pDevice, refcount);
532
533             hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
534             CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
535             CHECK_REFCOUNT( pRenderTarget, 2);
536             CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
537             CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
538             CHECK_REFCOUNT( pDevice, --refcount);
539
540             /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
541             CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
542             CHECK_REFCOUNT(pDevice, ++refcount);
543             CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
544             CHECK_REFCOUNT(pDevice, --refcount);
545         }
546
547         /* Render target and back buffer are identical. */
548         hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
549         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
550         if(pBackBuffer)
551         {
552             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
553             ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
554             pRenderTarget, pBackBuffer);
555             pBackBuffer = NULL;
556         }
557         CHECK_REFCOUNT( pDevice, --refcount);
558
559         hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
560         CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
561         CHECK_REFCOUNT( pSwapChain, 1);
562         if(pStencilSurface)
563         {
564             CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
565             CHECK_REFCOUNT( pStencilSurface, 1);
566
567             CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
568             CHECK_REFCOUNT(pDevice, refcount);
569             CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
570             CHECK_REFCOUNT(pDevice, refcount);
571
572             CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
573             CHECK_REFCOUNT( pDevice, --refcount);
574
575             /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
576             CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
577             CHECK_REFCOUNT(pDevice, ++refcount);
578             CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
579             CHECK_REFCOUNT(pDevice, --refcount);
580             pStencilSurface = NULL;
581         }
582
583         CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
584         CHECK_REFCOUNT( pDevice, --refcount);
585
586         /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
587         CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
588         CHECK_REFCOUNT(pDevice, ++refcount);
589         CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
590         CHECK_REFCOUNT(pDevice, --refcount);
591         pSwapChain = NULL;
592     }
593
594     /* Buffers */
595     hr = IDirect3DDevice9_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL );
596     CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
597     if(pIndexBuffer)
598     {
599         tmp = get_refcount( (IUnknown *)pIndexBuffer );
600
601         hr = IDirect3DDevice9_SetIndices(pDevice, pIndexBuffer);
602         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
603         hr = IDirect3DDevice9_SetIndices(pDevice, NULL);
604         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
605     }
606
607     hr = IDirect3DDevice9_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
608     CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
609     if(pVertexBuffer)
610     {
611         IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
612         UINT offset = ~0;
613         UINT stride = ~0;
614
615         tmp = get_refcount( (IUnknown *)pVertexBuffer );
616
617         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, pVertexBuffer, 0, 3 * sizeof(float));
618         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
619         hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, NULL, 0, 0);
620         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
621
622         hr = IDirect3DDevice9_GetStreamSource(pDevice, 0, &pVBuf, &offset, &stride);
623         ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
624         ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
625         ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
626         ok(offset==0, "offset not 0 (got %u)!\n", offset);
627     }
628     /* Shaders */
629     hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, decl, &pVertexDeclaration );
630     CHECK_CALL( hr, "CreateVertexDeclaration", pDevice, ++refcount );
631     hr = IDirect3DDevice9_CreateVertexShader( pDevice, simple_vs, &pVertexShader );
632     CHECK_CALL( hr, "CreateVertexShader", pDevice, ++refcount );
633     hr = IDirect3DDevice9_CreatePixelShader( pDevice, simple_ps, &pPixelShader );
634     CHECK_CALL( hr, "CreatePixelShader", pDevice, ++refcount );
635     /* Textures */
636     hr = IDirect3DDevice9_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL );
637     CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
638     if (pTexture)
639     {
640         tmp = get_refcount( (IUnknown *)pTexture );
641
642         /* SetTexture should not increase refcounts */
643         hr = IDirect3DDevice9_SetTexture(pDevice, 0, (IDirect3DBaseTexture9 *) pTexture);
644         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
645         hr = IDirect3DDevice9_SetTexture(pDevice, 0, NULL);
646         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
647
648         /* This should not increment device refcount */
649         hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
650         CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
651         /* But should increment texture's refcount */
652         CHECK_REFCOUNT( pTexture, tmp+1 );
653         /* Because the texture and surface refcount are identical */
654         if (pTextureLevel)
655         {
656             CHECK_REFCOUNT        ( pTextureLevel, tmp+1 );
657             CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
658             CHECK_REFCOUNT        ( pTexture     , tmp+2 );
659             CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
660             CHECK_REFCOUNT        ( pTexture     , tmp+1 );
661             CHECK_RELEASE_REFCOUNT( pTexture     , tmp   );
662             CHECK_REFCOUNT        ( pTextureLevel, tmp   );
663         }
664     }
665     hr = IDirect3DDevice9_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL );
666     CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
667     hr = IDirect3DDevice9_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL );
668     CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
669     if (pVolumeTexture)
670     {
671         tmp = get_refcount( (IUnknown *)pVolumeTexture );
672
673         /* This should not increment device refcount */
674         hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
675         CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
676         /* But should increment volume texture's refcount */
677         CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
678         /* Because the volume texture and volume refcount are identical */
679         if (pVolumeLevel)
680         {
681             CHECK_REFCOUNT        ( pVolumeLevel  , tmp+1 );
682             CHECK_ADDREF_REFCOUNT ( pVolumeLevel  , tmp+2 );
683             CHECK_REFCOUNT        ( pVolumeTexture, tmp+2 );
684             CHECK_RELEASE_REFCOUNT( pVolumeLevel  , tmp+1 );
685             CHECK_REFCOUNT        ( pVolumeTexture, tmp+1 );
686             CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp   );
687             CHECK_REFCOUNT        ( pVolumeLevel  , tmp   );
688         }
689     }
690     /* Surfaces */
691     hr = IDirect3DDevice9_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL );
692     CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
693     CHECK_REFCOUNT( pStencilSurface, 1 );
694     hr = IDirect3DDevice9_CreateOffscreenPlainSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL );
695     CHECK_CALL( hr, "CreateOffscreenPlainSurface", pDevice, ++refcount );
696     CHECK_REFCOUNT( pOffscreenSurface, 1 );
697     hr = IDirect3DDevice9_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL );
698     CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
699     CHECK_REFCOUNT( pRenderTarget3, 1 );
700     /* Misc */
701     hr = IDirect3DDevice9_CreateStateBlock( pDevice, D3DSBT_ALL, &pStateBlock );
702     CHECK_CALL( hr, "CreateStateBlock", pDevice, ++refcount );
703     hr = IDirect3DDevice9_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
704     CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
705     if(pSwapChain)
706     {
707         /* check implicit back buffer */
708         hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
709         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
710         CHECK_REFCOUNT( pSwapChain, 1);
711         if(pBackBuffer)
712         {
713             CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
714             CHECK_REFCOUNT( pBackBuffer, 1);
715             CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
716             CHECK_REFCOUNT( pDevice, --refcount);
717
718             /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
719             CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
720             CHECK_REFCOUNT(pDevice, ++refcount);
721             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
722             CHECK_REFCOUNT(pDevice, --refcount);
723             pBackBuffer = NULL;
724         }
725         CHECK_REFCOUNT( pSwapChain, 1);
726     }
727     hr = IDirect3DDevice9_CreateQuery( pDevice, D3DQUERYTYPE_EVENT, &pQuery );
728     CHECK_CALL( hr, "CreateQuery", pDevice, ++refcount );
729
730     hr = IDirect3DDevice9_BeginStateBlock( pDevice );
731     CHECK_CALL( hr, "BeginStateBlock", pDevice, refcount );
732     hr = IDirect3DDevice9_EndStateBlock( pDevice, &pStateBlock1 );
733     CHECK_CALL( hr, "EndStateBlock", pDevice, ++refcount );
734
735     /* The implicit render target is not freed if refcount reaches 0.
736      * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
737     hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget2);
738     CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
739     if(pRenderTarget2)
740     {
741         CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
742         ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
743            pRenderTarget, pRenderTarget2);
744         CHECK_REFCOUNT( pDevice, --refcount);
745         pRenderTarget2 = NULL;
746     }
747     pRenderTarget = NULL;
748
749 cleanup:
750     CHECK_RELEASE(pDevice,              pDevice, --refcount);
751
752     /* Buffers */
753     CHECK_RELEASE(pVertexBuffer,        pDevice, --refcount);
754     CHECK_RELEASE(pIndexBuffer,         pDevice, --refcount);
755     /* Shaders */
756     CHECK_RELEASE(pVertexDeclaration,   pDevice, --refcount);
757     CHECK_RELEASE(pVertexShader,        pDevice, --refcount);
758     CHECK_RELEASE(pPixelShader,         pDevice, --refcount);
759     /* Textures */
760     CHECK_RELEASE(pTextureLevel,        pDevice, --refcount);
761     CHECK_RELEASE(pCubeTexture,         pDevice, --refcount);
762     CHECK_RELEASE(pVolumeTexture,       pDevice, --refcount);
763     /* Surfaces */
764     CHECK_RELEASE(pStencilSurface,      pDevice, --refcount);
765     CHECK_RELEASE(pOffscreenSurface,    pDevice, --refcount);
766     CHECK_RELEASE(pRenderTarget3,       pDevice, --refcount);
767     /* Misc */
768     CHECK_RELEASE(pStateBlock,          pDevice, --refcount);
769     CHECK_RELEASE(pSwapChain,           pDevice, --refcount);
770     CHECK_RELEASE(pQuery,               pDevice, --refcount);
771     /* This will destroy device - cannot check the refcount here */
772     if (pStateBlock1)         CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
773
774     if (pD3d)                 CHECK_RELEASE_REFCOUNT( pD3d, 0);
775
776     DestroyWindow( hwnd );
777 }
778
779 static void test_cursor(void)
780 {
781     HRESULT                      hr;
782     HWND                         hwnd               = NULL;
783     IDirect3D9                  *pD3d               = NULL;
784     IDirect3DDevice9            *pDevice            = NULL;
785     D3DPRESENT_PARAMETERS        d3dpp;
786     D3DDISPLAYMODE               d3ddm;
787     CURSORINFO                   info;
788     IDirect3DSurface9 *cursor = NULL;
789     HCURSOR cur;
790
791     memset(&info, 0, sizeof(info));
792     info.cbSize = sizeof(info);
793     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
794     cur = info.hCursor;
795
796     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
797     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
798     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
799     ok(hwnd != NULL, "Failed to create window\n");
800     if (!pD3d || !hwnd) goto cleanup;
801
802     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
803     ZeroMemory( &d3dpp, sizeof(d3dpp) );
804     d3dpp.Windowed         = TRUE;
805     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
806     d3dpp.BackBufferFormat = d3ddm.Format;
807
808     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
809                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
810     ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
811        "Failed to create IDirect3D9Device (%08x)\n", hr);
812     if (FAILED(hr)) goto cleanup;
813
814     IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, 0);
815     ok(cursor != NULL, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
816
817     /* Initially hidden */
818     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
819     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
820
821     /* Not enabled without a surface*/
822     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
823     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
824
825     /* Fails */
826     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, NULL);
827     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
828
829     hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, cursor);
830     ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
831
832     IDirect3DSurface9_Release(cursor);
833
834     memset(&info, 0, sizeof(info));
835     info.cbSize = sizeof(info);
836     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
837     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
838     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
839
840     /* Still hidden */
841     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
842     ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
843
844     /* Enabled now*/
845     hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
846     ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
847
848     /* GDI cursor unchanged */
849     memset(&info, 0, sizeof(info));
850     info.cbSize = sizeof(info);
851     ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
852     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
853     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
854
855 cleanup:
856     if (pDevice)
857     {
858         UINT refcount = IDirect3DDevice9_Release(pDevice);
859         ok(!refcount, "Device has %u references left.\n", refcount);
860     }
861     if (pD3d) IDirect3D9_Release(pD3d);
862     DestroyWindow( hwnd );
863 }
864
865 static void test_reset(void)
866 {
867     HRESULT                      hr;
868     HWND                         hwnd               = NULL;
869     RECT                         winrect;
870     IDirect3D9                  *pD3d               = NULL;
871     D3DPRESENT_PARAMETERS        d3dpp;
872     D3DDISPLAYMODE               d3ddm, d3ddm2;
873     D3DVIEWPORT9                 vp;
874     DWORD                        width, orig_width = GetSystemMetrics(SM_CXSCREEN);
875     DWORD                        height, orig_height = GetSystemMetrics(SM_CYSCREEN);
876     IDirect3DSwapChain9          *pSwapchain;
877     IDirect3DSurface9            *surface;
878     IDirect3DTexture9            *texture;
879     IDirect3DVertexShader9       *shader;
880     UINT                         i, adapter_mode_count;
881     D3DLOCKED_RECT               lockrect;
882     IDirect3DDevice9 *device1 = NULL;
883     IDirect3DDevice9 *device2 = NULL;
884     D3DCAPS9 caps;
885     DWORD value;
886     struct
887     {
888         UINT w;
889         UINT h;
890     } *modes = NULL;
891     UINT mode_count = 0;
892
893     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
894     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
895     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
896     ok(hwnd != NULL, "Failed to create window\n");
897     if (!pD3d || !hwnd) goto cleanup;
898
899     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
900     adapter_mode_count = IDirect3D9_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format);
901     modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
902     for(i = 0; i < adapter_mode_count; ++i)
903     {
904         UINT j;
905         ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
906         hr = IDirect3D9_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
907         ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
908
909         for (j = 0; j < mode_count; ++j)
910         {
911             if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
912                 break;
913         }
914         if (j == mode_count)
915         {
916             modes[j].w = d3ddm2.Width;
917             modes[j].h = d3ddm2.Height;
918             ++mode_count;
919         }
920
921         /* We use them as invalid modes */
922         if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
923            (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
924             skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
925                  d3ddm2.Width, d3ddm2.Height);
926             goto cleanup;
927         }
928     }
929
930     if (mode_count < 2)
931     {
932         skip("Less than 2 modes supported, skipping mode tests\n");
933         goto cleanup;
934     }
935
936     i = 0;
937     if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
938
939     ZeroMemory( &d3dpp, sizeof(d3dpp) );
940     d3dpp.Windowed         = FALSE;
941     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
942     d3dpp.BackBufferWidth  = modes[i].w;
943     d3dpp.BackBufferHeight = modes[i].h;
944     d3dpp.BackBufferFormat = d3ddm.Format;
945     d3dpp.EnableAutoDepthStencil = TRUE;
946     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
947
948     hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
949             hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
950     if (FAILED(hr))
951     {
952         skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
953         goto cleanup;
954     }
955     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
956     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
957
958     hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
959     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
960
961     width = GetSystemMetrics(SM_CXSCREEN);
962     height = GetSystemMetrics(SM_CYSCREEN);
963     ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
964     ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
965
966     hr = IDirect3DDevice9_GetViewport(device1, &vp);
967     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
968     if(SUCCEEDED(hr))
969     {
970         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
971         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
972         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
973         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
974         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
975         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
976     }
977
978     i = 1;
979     vp.X = 10;
980     vp.Y = 20;
981     vp.MinZ = 2;
982     vp.MaxZ = 3;
983     hr = IDirect3DDevice9_SetViewport(device1, &vp);
984     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
985
986     hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
987     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
988     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
989     hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
990     ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
991
992     ZeroMemory( &d3dpp, sizeof(d3dpp) );
993     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
994     d3dpp.Windowed         = FALSE;
995     d3dpp.BackBufferWidth  = modes[i].w;
996     d3dpp.BackBufferHeight = modes[i].h;
997     d3dpp.BackBufferFormat = d3ddm.Format;
998     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
999     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1000     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1001     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1002
1003     hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1004     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1005     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1006
1007     ZeroMemory(&vp, sizeof(vp));
1008     hr = IDirect3DDevice9_GetViewport(device1, &vp);
1009     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1010     if(SUCCEEDED(hr))
1011     {
1012         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1013         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1014         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1015         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1016         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1017         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1018     }
1019
1020     width = GetSystemMetrics(SM_CXSCREEN);
1021     height = GetSystemMetrics(SM_CYSCREEN);
1022     ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1023     ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1024
1025     hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1026     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1027     if(SUCCEEDED(hr))
1028     {
1029         ZeroMemory(&d3dpp, sizeof(d3dpp));
1030         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1031         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1032         if(SUCCEEDED(hr))
1033         {
1034             ok(d3dpp.BackBufferWidth == modes[i].w, "Back buffer width is %u, expected %u\n",
1035                     d3dpp.BackBufferWidth, modes[i].w);
1036             ok(d3dpp.BackBufferHeight == modes[i].h, "Back buffer height is %u, expected %u\n",
1037                     d3dpp.BackBufferHeight, modes[i].h);
1038         }
1039         IDirect3DSwapChain9_Release(pSwapchain);
1040     }
1041
1042     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1043     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1044     d3dpp.Windowed         = TRUE;
1045     d3dpp.BackBufferWidth  = 400;
1046     d3dpp.BackBufferHeight = 300;
1047     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1048     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1049     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1050     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1051
1052     width = GetSystemMetrics(SM_CXSCREEN);
1053     height = GetSystemMetrics(SM_CYSCREEN);
1054     ok(width == orig_width, "Screen width is %d\n", width);
1055     ok(height == orig_height, "Screen height is %d\n", height);
1056
1057     ZeroMemory(&vp, sizeof(vp));
1058     hr = IDirect3DDevice9_GetViewport(device1, &vp);
1059     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1060     if(SUCCEEDED(hr))
1061     {
1062         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1063         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1064         ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1065         ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1066         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1067         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1068     }
1069
1070     hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1071     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1072     if(SUCCEEDED(hr))
1073     {
1074         ZeroMemory(&d3dpp, sizeof(d3dpp));
1075         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1076         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1077         if(SUCCEEDED(hr))
1078         {
1079             ok(d3dpp.BackBufferWidth == 400, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1080             ok(d3dpp.BackBufferHeight == 300, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1081         }
1082         IDirect3DSwapChain9_Release(pSwapchain);
1083     }
1084
1085     winrect.left = 0;
1086     winrect.top = 0;
1087     winrect.right = 200;
1088     winrect.bottom = 150;
1089     ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1090     ok(SetWindowPos(hwnd, NULL, 0, 0,
1091                     winrect.right-winrect.left,
1092                     winrect.bottom-winrect.top,
1093                     SWP_NOMOVE|SWP_NOZORDER),
1094        "SetWindowPos failed\n");
1095
1096     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1097     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1098     d3dpp.Windowed         = TRUE;
1099     d3dpp.BackBufferWidth  = 0;
1100     d3dpp.BackBufferHeight = 0;
1101     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1102     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1103     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1104     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1105
1106     ZeroMemory(&vp, sizeof(vp));
1107     hr = IDirect3DDevice9_GetViewport(device1, &vp);
1108     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1109     if(SUCCEEDED(hr))
1110     {
1111         ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1112         ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1113         todo_wine ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
1114         todo_wine ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
1115         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1116         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1117     }
1118
1119     hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1120     ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1121     if(SUCCEEDED(hr))
1122     {
1123         ZeroMemory(&d3dpp, sizeof(d3dpp));
1124         hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1125         ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1126         if(SUCCEEDED(hr))
1127         {
1128             todo_wine ok(d3dpp.BackBufferWidth == 200, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1129             todo_wine ok(d3dpp.BackBufferHeight == 150, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1130         }
1131         IDirect3DSwapChain9_Release(pSwapchain);
1132     }
1133
1134     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1135     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1136     d3dpp.Windowed         = TRUE;
1137     d3dpp.BackBufferWidth  = 400;
1138     d3dpp.BackBufferHeight = 300;
1139
1140     /* _Reset fails if there is a resource in the default pool */
1141     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1142     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1143     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1144     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1145     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1146     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1147     IDirect3DSurface9_Release(surface);
1148     /* Reset again to get the device out of the lost state */
1149     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1150     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1151     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1152     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1153
1154     if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1155     {
1156         IDirect3DVolumeTexture9 *volume_texture;
1157
1158         hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1159                 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1160         ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1161         hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1162         ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1163         hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1164         ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1165                 hr, D3DERR_DEVICENOTRESET);
1166         IDirect3DVolumeTexture9_Release(volume_texture);
1167         hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1168         ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1169         hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1170         ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1171     }
1172     else
1173     {
1174         skip("Volume textures not supported.\n");
1175     }
1176
1177     /* Scratch, sysmem and managed pools are fine */
1178     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1179     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1180     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1181     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1182     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1183     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1184     IDirect3DSurface9_Release(surface);
1185
1186     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1187             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1188     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1189     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1190     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1191     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1192     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1193     IDirect3DSurface9_Release(surface);
1194
1195     /* The depth stencil should get reset to the auto depth stencil when present. */
1196     hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
1197     ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
1198
1199     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1200     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1201     ok(surface == NULL, "Depth stencil should be NULL\n");
1202
1203     d3dpp.EnableAutoDepthStencil = TRUE;
1204     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1205     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1206     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1207
1208     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1209     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1210     ok(surface != NULL, "Depth stencil should not be NULL\n");
1211     if (surface) IDirect3DSurface9_Release(surface);
1212
1213     d3dpp.EnableAutoDepthStencil = FALSE;
1214     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1215     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1216
1217     hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1218     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1219     ok(surface == NULL, "Depth stencil should be NULL\n");
1220
1221     /* Will a sysmem or scratch survive while locked */
1222     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1223             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1224     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1225     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1226     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1227     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1228     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1229     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1230     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1231     IDirect3DSurface9_UnlockRect(surface);
1232     IDirect3DSurface9_Release(surface);
1233
1234     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1235     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1236     hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1237     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1238     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1239     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1240     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1241     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1242     IDirect3DSurface9_UnlockRect(surface);
1243     IDirect3DSurface9_Release(surface);
1244
1245     hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
1246     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
1247     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1248     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1249     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1250     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1251     IDirect3DTexture9_Release(texture);
1252
1253     /* A reference held to an implicit surface causes failures as well */
1254     hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1255     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
1256     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1257     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1258     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1259     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1260     IDirect3DSurface9_Release(surface);
1261     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1262     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1263     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1264     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1265
1266     /* Shaders are fine as well */
1267     hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
1268     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
1269     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1270     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1271     IDirect3DVertexShader9_Release(shader);
1272
1273     /* Try setting invalid modes */
1274     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1275     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1276     d3dpp.Windowed         = FALSE;
1277     d3dpp.BackBufferWidth  = 32;
1278     d3dpp.BackBufferHeight = 32;
1279     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1280     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
1281     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1282     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1283
1284     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1285     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1286     d3dpp.Windowed         = FALSE;
1287     d3dpp.BackBufferWidth  = 801;
1288     d3dpp.BackBufferHeight = 600;
1289     hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1290     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
1291     hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1292     ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1293
1294     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1295
1296     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1297     d3dpp.Windowed         = TRUE;
1298     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1299     d3dpp.BackBufferFormat = d3ddm.Format;
1300     d3dpp.EnableAutoDepthStencil = FALSE;
1301     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1302
1303     hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1304             hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1305     if (FAILED(hr))
1306     {
1307         skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
1308         goto cleanup;
1309     }
1310
1311     hr = IDirect3DDevice9_TestCooperativeLevel(device2);
1312     ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1313
1314     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1315     d3dpp.Windowed         = TRUE;
1316     d3dpp.BackBufferWidth  = 400;
1317     d3dpp.BackBufferHeight = 300;
1318     d3dpp.EnableAutoDepthStencil = TRUE;
1319     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1320
1321     hr = IDirect3DDevice9_Reset(device2, &d3dpp);
1322     ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1323
1324     if (FAILED(hr)) goto cleanup;
1325
1326     hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
1327     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1328     ok(surface != NULL, "Depth stencil should not be NULL\n");
1329     if (surface) IDirect3DSurface9_Release(surface);
1330
1331 cleanup:
1332     HeapFree(GetProcessHeap(), 0, modes);
1333     if (device2)
1334     {
1335         UINT refcount = IDirect3DDevice9_Release(device2);
1336         ok(!refcount, "Device has %u references left.\n", refcount);
1337     }
1338     if (device1)
1339     {
1340         UINT refcount = IDirect3DDevice9_Release(device1);
1341         ok(!refcount, "Device has %u references left.\n", refcount);
1342     }
1343     if (pD3d) IDirect3D9_Release(pD3d);
1344     if (hwnd) DestroyWindow(hwnd);
1345 }
1346
1347 /* Test adapter display modes */
1348 static void test_display_modes(void)
1349 {
1350     D3DDISPLAYMODE dmode;
1351     IDirect3D9 *pD3d;
1352
1353     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1354     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1355     if(!pD3d) return;
1356
1357 #define TEST_FMT(x,r) do { \
1358     HRESULT res = IDirect3D9_EnumAdapterModes(pD3d, 0, (x), 0, &dmode); \
1359     ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
1360 } while(0)
1361
1362     TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
1363     TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
1364     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1365     /* D3DFMT_R5G6B5 */
1366     TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
1367     TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
1368     TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
1369     TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
1370     TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
1371     TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
1372     TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
1373     TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
1374     TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
1375     TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1376     TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
1377     TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
1378
1379     TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
1380     TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
1381
1382     TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
1383     TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
1384     TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
1385
1386     TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
1387     TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
1388     TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
1389     TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
1390     TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
1391     TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
1392
1393     TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
1394     TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
1395     TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
1396     TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
1397     TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
1398     TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
1399     TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
1400     TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
1401     TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
1402     TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
1403
1404     TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
1405     TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
1406     TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
1407     TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
1408     TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
1409     TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
1410     TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
1411     TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
1412     TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
1413     TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
1414
1415     TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
1416     TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
1417     TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
1418     TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
1419     /* Floating point formats */
1420     TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
1421     TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
1422     TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
1423
1424     /* IEEE formats */
1425     TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
1426     TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
1427     TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
1428
1429     TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
1430
1431     TEST_FMT(0, D3DERR_INVALIDCALL);
1432
1433     IDirect3D9_Release(pD3d);
1434 }
1435
1436 static void test_scene(void)
1437 {
1438     HRESULT                      hr;
1439     HWND                         hwnd               = NULL;
1440     IDirect3D9                  *pD3d               = NULL;
1441     IDirect3DDevice9            *pDevice            = NULL;
1442     D3DPRESENT_PARAMETERS        d3dpp;
1443     D3DDISPLAYMODE               d3ddm;
1444     IDirect3DSurface9            *pSurface1 = NULL, *pSurface2 = NULL, *pSurface3 = NULL, *pRenderTarget = NULL;
1445     IDirect3DSurface9            *pBackBuffer = NULL, *pDepthStencil = NULL;
1446     RECT rect = {0, 0, 128, 128};
1447     D3DCAPS9                     caps;
1448
1449     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1450     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1451     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1452     ok(hwnd != NULL, "Failed to create window\n");
1453     if (!pD3d || !hwnd) goto cleanup;
1454
1455     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1456     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1457     d3dpp.Windowed         = TRUE;
1458     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1459     d3dpp.BackBufferWidth  = 800;
1460     d3dpp.BackBufferHeight = 600;
1461     d3dpp.BackBufferFormat = d3ddm.Format;
1462     d3dpp.EnableAutoDepthStencil = TRUE;
1463     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1464
1465     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1466                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1467     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1468     if(!pDevice)
1469     {
1470         skip("Failed to create a d3d device\n");
1471         goto cleanup;
1472     }
1473
1474     /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
1475     memset(&caps, 0, sizeof(caps));
1476     hr = IDirect3DDevice9_GetDeviceCaps(pDevice, &caps);
1477     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
1478     if(FAILED(hr)) goto cleanup;
1479
1480     /* Test an EndScene without BeginScene. Should return an error */
1481     hr = IDirect3DDevice9_EndScene(pDevice);
1482     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1483
1484     /* Test a normal BeginScene / EndScene pair, this should work */
1485     hr = IDirect3DDevice9_BeginScene(pDevice);
1486     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1487     if(SUCCEEDED(hr))
1488     {
1489         hr = IDirect3DDevice9_EndScene(pDevice);
1490         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1491     }
1492
1493     /* Test another EndScene without having begun a new scene. Should return an error */
1494     hr = IDirect3DDevice9_EndScene(pDevice);
1495     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1496
1497     /* Two nested BeginScene and EndScene calls */
1498     hr = IDirect3DDevice9_BeginScene(pDevice);
1499     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1500     hr = IDirect3DDevice9_BeginScene(pDevice);
1501     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
1502     hr = IDirect3DDevice9_EndScene(pDevice);
1503     ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1504     hr = IDirect3DDevice9_EndScene(pDevice);
1505     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1506
1507     /* Create some surfaces to test stretchrect between the scenes */
1508     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface1, NULL);
1509     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1510     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface2, NULL);
1511     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1512     hr = IDirect3DDevice9_CreateDepthStencilSurface(pDevice, 800, 600, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface3, NULL);
1513     ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
1514     hr = IDirect3DDevice9_CreateRenderTarget(pDevice, 128, 128, d3ddm.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pRenderTarget, NULL);
1515     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
1516
1517     hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
1518     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1519     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1520     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1521
1522     /* First make sure a simple StretchRect call works */
1523     if(pSurface1 && pSurface2) {
1524         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1525         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1526     }
1527     if(pBackBuffer && pRenderTarget) {
1528         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1529         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1530     }
1531     if(pDepthStencil && pSurface3) {
1532         HRESULT expected;
1533         if(0) /* Disabled for now because it crashes in wine */ {
1534             expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
1535             hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1536             ok( hr == expected, "IDirect3DDevice9_StretchRect returned %08x, expected %08x\n", hr, expected);
1537         }
1538     }
1539
1540     /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a beginScene - Endscene pair
1541      * with normal surfaces and render targets, but not depth stencil surfaces.
1542      */
1543     hr = IDirect3DDevice9_BeginScene(pDevice);
1544     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1545
1546     if(pSurface1 && pSurface2)
1547     {
1548         hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1549         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1550     }
1551     if(pBackBuffer && pRenderTarget)
1552     {
1553         hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1554         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1555     }
1556     if(pDepthStencil && pSurface3)
1557     {
1558         /* This is supposed to fail inside a BeginScene - EndScene pair. */
1559         hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1560         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
1561     }
1562
1563     hr = IDirect3DDevice9_EndScene(pDevice);
1564     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1565
1566     /* Does a SetRenderTarget influence BeginScene / EndScene ?
1567      * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
1568      * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
1569      */
1570     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pRenderTarget);
1571     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1572     hr = IDirect3DDevice9_BeginScene(pDevice);
1573     ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1574     hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pBackBuffer);
1575     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1576     hr = IDirect3DDevice9_EndScene(pDevice);
1577     ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1578
1579 cleanup:
1580     if(pRenderTarget) IDirect3DSurface9_Release(pRenderTarget);
1581     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1582     if(pBackBuffer) IDirect3DSurface9_Release(pBackBuffer);
1583     if(pSurface1) IDirect3DSurface9_Release(pSurface1);
1584     if(pSurface2) IDirect3DSurface9_Release(pSurface2);
1585     if(pSurface3) IDirect3DSurface9_Release(pSurface3);
1586     if (pDevice)
1587     {
1588         UINT refcount = IDirect3DDevice9_Release(pDevice);
1589         ok(!refcount, "Device has %u references left.\n", refcount);
1590     }
1591     if (pD3d) IDirect3D9_Release(pD3d);
1592     if(hwnd) DestroyWindow(hwnd);
1593 }
1594
1595 static void test_limits(void)
1596 {
1597     HRESULT                      hr;
1598     HWND                         hwnd               = NULL;
1599     IDirect3D9                  *pD3d               = NULL;
1600     IDirect3DDevice9            *pDevice            = NULL;
1601     D3DPRESENT_PARAMETERS        d3dpp;
1602     D3DDISPLAYMODE               d3ddm;
1603     IDirect3DTexture9           *pTexture           = NULL;
1604     int i;
1605
1606     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1607     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1608     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1609     ok(hwnd != NULL, "Failed to create window\n");
1610     if (!pD3d || !hwnd) goto cleanup;
1611
1612     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1613     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1614     d3dpp.Windowed         = TRUE;
1615     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1616     d3dpp.BackBufferWidth  = 800;
1617     d3dpp.BackBufferHeight = 600;
1618     d3dpp.BackBufferFormat = d3ddm.Format;
1619     d3dpp.EnableAutoDepthStencil = TRUE;
1620     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1621
1622     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1623                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1624     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1625     if(!pDevice)
1626     {
1627         skip("Failed to create a d3d device\n");
1628         goto cleanup;
1629     }
1630
1631     hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL);
1632     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
1633     if(!pTexture) goto cleanup;
1634
1635     /* There are 16 pixel samplers. We should be able to access all of them */
1636     for(i = 0; i < 16; i++) {
1637         hr = IDirect3DDevice9_SetTexture(pDevice, i, (IDirect3DBaseTexture9 *) pTexture);
1638         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1639         hr = IDirect3DDevice9_SetTexture(pDevice, i, NULL);
1640         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1641         hr = IDirect3DDevice9_SetSamplerState(pDevice, i, D3DSAMP_SRGBTEXTURE, TRUE);
1642         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
1643     }
1644
1645     /* Now test all 8 textures stage states */
1646     for(i = 0; i < 8; i++) {
1647         hr = IDirect3DDevice9_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1648         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
1649     }
1650
1651     /* Investigations show that accessing higher samplers / textures stage states does not return an error either. Writing
1652      * to too high samplers(approximately sampler 40) causes memory corruption in windows, so there is no bounds checking
1653      * but how do I test that?
1654      */
1655 cleanup:
1656     if(pTexture) IDirect3DTexture9_Release(pTexture);
1657     if (pDevice)
1658     {
1659         UINT refcount = IDirect3D9_Release(pDevice);
1660         ok(!refcount, "Device has %u references left.\n", refcount);
1661     }
1662     if (pD3d) IDirect3D9_Release(pD3d);
1663     if(hwnd) DestroyWindow(hwnd);
1664 }
1665
1666 static void test_depthstenciltest(void)
1667 {
1668     HRESULT                      hr;
1669     HWND                         hwnd               = NULL;
1670     IDirect3D9                  *pD3d               = NULL;
1671     IDirect3DDevice9            *pDevice            = NULL;
1672     D3DPRESENT_PARAMETERS        d3dpp;
1673     D3DDISPLAYMODE               d3ddm;
1674     IDirect3DSurface9           *pDepthStencil           = NULL;
1675     IDirect3DSurface9           *pDepthStencil2          = NULL;
1676     DWORD                        state;
1677
1678     pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1679     ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1680     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1681     ok(hwnd != NULL, "Failed to create window\n");
1682     if (!pD3d || !hwnd) goto cleanup;
1683
1684     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1685     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1686     d3dpp.Windowed         = TRUE;
1687     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1688     d3dpp.BackBufferWidth  = 800;
1689     d3dpp.BackBufferHeight = 600;
1690     d3dpp.BackBufferFormat = d3ddm.Format;
1691     d3dpp.EnableAutoDepthStencil = TRUE;
1692     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1693
1694     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1695                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1696     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1697     if(!pDevice)
1698     {
1699         skip("Failed to create a d3d device\n");
1700         goto cleanup;
1701     }
1702
1703     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1704     ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1705
1706     /* Try to clear */
1707     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1708     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1709
1710     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
1711     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1712
1713     /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
1714     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
1715     ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1716     if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
1717
1718     /* This left the render states untouched! */
1719     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1720     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1721     ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1722     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
1723     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1724     ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
1725     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
1726     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1727     ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
1728     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
1729     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1730     ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
1731
1732     /* This is supposed to fail now */
1733     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1734     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1735
1736     hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
1737     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
1738
1739     hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
1740     ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1741
1742     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1743     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1744     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1745
1746     /* Now it works again */
1747     hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1748     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1749
1750     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1751     if(pDevice) IDirect3D9_Release(pDevice);
1752
1753     /* Now see if autodepthstencil disable is honored. First, without a format set */
1754     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1755     d3dpp.Windowed         = TRUE;
1756     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1757     d3dpp.BackBufferWidth  = 800;
1758     d3dpp.BackBufferHeight = 600;
1759     d3dpp.BackBufferFormat = d3ddm.Format;
1760     d3dpp.EnableAutoDepthStencil = FALSE;
1761     d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1762
1763     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1764                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1765     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1766     if(!pDevice)
1767     {
1768         skip("Failed to create a d3d device\n");
1769         goto cleanup;
1770     }
1771
1772     pDepthStencil = NULL;
1773     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1774     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1775     if(pDepthStencil) {
1776         IDirect3DSurface9_Release(pDepthStencil);
1777         pDepthStencil = NULL;
1778     }
1779
1780     /* Check the depth test state */
1781     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1782     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1783     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1784
1785     if(pDevice) IDirect3D9_Release(pDevice);
1786
1787     /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
1788     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1789     d3dpp.Windowed         = TRUE;
1790     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1791     d3dpp.BackBufferWidth  = 800;
1792     d3dpp.BackBufferHeight = 600;
1793     d3dpp.BackBufferFormat = d3ddm.Format;
1794     d3dpp.EnableAutoDepthStencil = FALSE;
1795     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1796
1797     hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1798                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1799     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1800     if(!pDevice)
1801     {
1802         skip("Failed to create a d3d device\n");
1803         goto cleanup;
1804     }
1805
1806     pDepthStencil = NULL;
1807     hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1808     ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1809     if(pDepthStencil) {
1810         IDirect3DSurface9_Release(pDepthStencil);
1811         pDepthStencil = NULL;
1812     }
1813
1814     hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1815     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1816     ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1817
1818 cleanup:
1819     if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1820     if (pDevice)
1821     {
1822         UINT refcount = IDirect3D9_Release(pDevice);
1823         ok(!refcount, "Device has %u references left.\n", refcount);
1824     }
1825     if (pD3d) IDirect3D9_Release(pD3d);
1826     if(hwnd) DestroyWindow(hwnd);
1827 }
1828
1829 static void test_get_rt(void)
1830 {
1831     IDirect3DSurface9 *backbuffer, *rt;
1832     IDirect3DDevice9 *device;
1833     IDirect3D9 *d3d9;
1834     D3DCAPS9 caps;
1835     HWND window;
1836     HRESULT hr;
1837     ULONG ref;
1838     UINT i;
1839
1840     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
1841     {
1842         skip("Failed to create IDirect3D9 object, skipping tests.\n");
1843         return;
1844     }
1845
1846     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1847             0, 0, 128, 128, 0, 0, 0, 0);
1848     device = create_device(d3d9, window, window, TRUE);
1849     if (!device)
1850     {
1851         skip("Failed to create a D3D device, skipping tests.\n");
1852         goto done;
1853     }
1854
1855     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
1856     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
1857     ok(!!backbuffer, "Got a NULL backbuffer.\n");
1858
1859     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1860     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1861
1862     for (i = 1; i < caps.NumSimultaneousRTs; ++i)
1863     {
1864         rt = backbuffer;
1865         hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
1866         ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
1867         ok(!rt, "Got rt %p.\n", rt);
1868     }
1869
1870     IDirect3DSurface9_Release(backbuffer);
1871
1872     ref = IDirect3DDevice9_Release(device);
1873     ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
1874 done:
1875     IDirect3D9_Release(d3d9);
1876     DestroyWindow(window);
1877 }
1878
1879 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
1880 static void test_draw_indexed(void)
1881 {
1882     static const struct {
1883         float position[3];
1884         DWORD color;
1885     } quad[] = {
1886         {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
1887         {{-1.0f,  1.0f, 0.0f}, 0xffff0000},
1888         {{ 1.0f,  1.0f, 0.0f}, 0xffff0000},
1889         {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
1890     };
1891     WORD indices[] = {0, 1, 2, 3, 0, 2};
1892
1893     static const D3DVERTEXELEMENT9 decl_elements[] = {
1894         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1895         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1896         D3DDECL_END()
1897     };
1898
1899     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1900     IDirect3DVertexBuffer9 *vertex_buffer = NULL;
1901     IDirect3DIndexBuffer9 *index_buffer = NULL;
1902     D3DPRESENT_PARAMETERS present_parameters;
1903     IDirect3DDevice9 *device = NULL;
1904     IDirect3D9 *d3d9;
1905     HRESULT hr;
1906     HWND hwnd;
1907     void *ptr;
1908
1909     hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
1910             0, 0, 0, 10, 10, 0, 0, 0, 0);
1911     if (!hwnd)
1912     {
1913         skip("Failed to create window\n");
1914         return;
1915     }
1916
1917     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
1918     if (!d3d9)
1919     {
1920         skip("Failed to create IDirect3D9 object\n");
1921         goto cleanup;
1922     }
1923
1924     ZeroMemory(&present_parameters, sizeof(present_parameters));
1925     present_parameters.Windowed = TRUE;
1926     present_parameters.hDeviceWindow = hwnd;
1927     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1928
1929     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1930             NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1931     if (FAILED(hr) || !device)
1932     {
1933         skip("Failed to create device\n");
1934         goto cleanup;
1935     }
1936
1937     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1938     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1939     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1940     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1941
1942     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
1943     ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
1944     hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1945     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1946     memcpy(ptr, quad, sizeof(quad));
1947     hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
1948     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1949     hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
1950     ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
1951
1952     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
1953     ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
1954     hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1955     ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1956     memcpy(ptr, indices, sizeof(indices));
1957     hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
1958     ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1959     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1960     ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
1961     hr = IDirect3DDevice9_BeginScene(device);
1962     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1963
1964     /* NULL index buffer. Should fail */
1965     hr = IDirect3DDevice9_SetIndices(device, NULL);
1966     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1967     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1968             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1969     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1970             hr, D3DERR_INVALIDCALL);
1971
1972     /* Valid index buffer, NULL vertex declaration. Should fail */
1973     hr = IDirect3DDevice9_SetIndices(device, index_buffer);
1974     ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1975     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1976             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1977     ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1978             hr, D3DERR_INVALIDCALL);
1979
1980     /* Valid index buffer and vertex declaration. Should succeed */
1981     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1982     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1983     hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1984             4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1985     ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
1986
1987     hr = IDirect3DDevice9_EndScene(device);
1988     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1989
1990     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1991     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1992
1993     IDirect3DVertexBuffer9_Release(vertex_buffer);
1994     IDirect3DIndexBuffer9_Release(index_buffer);
1995     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1996
1997 cleanup:
1998     if (device)
1999     {
2000         UINT refcount = IDirect3DDevice9_Release(device);
2001         ok(!refcount, "Device has %u references left.\n", refcount);
2002     }
2003     if (d3d9) IDirect3D9_Release(d3d9);
2004     if (hwnd) DestroyWindow(hwnd);
2005 }
2006
2007 static void test_null_stream(void)
2008 {
2009     IDirect3DVertexBuffer9 *buffer = NULL;
2010     D3DPRESENT_PARAMETERS present_parameters;
2011     IDirect3DDevice9 *device = NULL;
2012     IDirect3D9 *d3d9;
2013     HWND hwnd;
2014     HRESULT hr;
2015     IDirect3DVertexShader9 *shader = NULL;
2016     IDirect3DVertexDeclaration9 *decl = NULL;
2017     DWORD shader_code[] = {
2018         0xfffe0101,                             /* vs_1_1           */
2019         0x0000001f, 0x80000000, 0x900f0000,     /* dcl_position v0  */
2020         0x00000001, 0xc00f0000, 0x90e40000,     /* mov oPos, v0     */
2021         0x0000ffff                              /* end              */
2022     };
2023     static const D3DVERTEXELEMENT9 decl_elements[] = {
2024         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2025         {1, 0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
2026         D3DDECL_END()
2027     };
2028
2029     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2030     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2031     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2032     ok(hwnd != NULL, "Failed to create window\n");
2033     if (!d3d9 || !hwnd) goto cleanup;
2034
2035     ZeroMemory(&present_parameters, sizeof(present_parameters));
2036     present_parameters.Windowed = TRUE;
2037     present_parameters.hDeviceWindow = hwnd;
2038     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2039
2040     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
2041                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2042     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2043     if(!device)
2044     {
2045         skip("Failed to create a d3d device\n");
2046         goto cleanup;
2047     }
2048
2049     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2050     if(FAILED(hr)) {
2051         skip("No vertex shader support\n");
2052         goto cleanup;
2053     }
2054     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2055     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2056     if (FAILED(hr)) {
2057         skip("Vertex declaration handling not possible.\n");
2058         goto cleanup;
2059     }
2060     hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2061     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2062     if (FAILED(hr)) {
2063         skip("Vertex buffer handling not possible.\n");
2064         goto cleanup;
2065     }
2066
2067     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
2068     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2069     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
2070     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2071     hr = IDirect3DDevice9_SetVertexShader(device, shader);
2072     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
2073     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2074     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
2075
2076     hr = IDirect3DDevice9_BeginScene(device);
2077     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (0x%08x)\n", hr);
2078     if(SUCCEEDED(hr)) {
2079         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
2080         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitive failed (0x%08x)\n", hr);
2081
2082         hr = IDirect3DDevice9_EndScene(device);
2083         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed (0x%08x)\n", hr);
2084     }
2085
2086     IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2087     IDirect3DDevice9_SetVertexShader(device, NULL);
2088     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2089
2090 cleanup:
2091     if (buffer) IDirect3DVertexBuffer9_Release(buffer);
2092     if(decl) IDirect3DVertexDeclaration9_Release(decl);
2093     if(shader) IDirect3DVertexShader9_Release(shader);
2094     if (device)
2095     {
2096         UINT refcount = IDirect3DDevice9_Release(device);
2097         ok(!refcount, "Device has %u references left.\n", refcount);
2098     }
2099     if(d3d9) IDirect3D9_Release(d3d9);
2100 }
2101
2102 static void test_lights(void)
2103 {
2104     D3DPRESENT_PARAMETERS present_parameters;
2105     IDirect3DDevice9 *device = NULL;
2106     IDirect3D9 *d3d9;
2107     HWND hwnd;
2108     HRESULT hr;
2109     unsigned int i;
2110     BOOL enabled;
2111     D3DCAPS9 caps;
2112
2113     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2114     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2115     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2116     ok(hwnd != NULL, "Failed to create window\n");
2117     if (!d3d9 || !hwnd) goto cleanup;
2118
2119     ZeroMemory(&present_parameters, sizeof(present_parameters));
2120     present_parameters.Windowed = TRUE;
2121     present_parameters.hDeviceWindow = hwnd;
2122     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2123
2124     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2125                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2126     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2127        "IDirect3D9_CreateDevice failed with %08x\n", hr);
2128     if(!device)
2129     {
2130         skip("Failed to create a d3d device\n");
2131         goto cleanup;
2132     }
2133
2134     memset(&caps, 0, sizeof(caps));
2135     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2136     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
2137
2138     for(i = 1; i <= caps.MaxActiveLights; i++) {
2139         hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
2140         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2141         hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
2142         ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
2143         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2144     }
2145
2146     /* TODO: Test the rendering results in this situation */
2147     hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
2148     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2149     hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
2150     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2151     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2152     hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
2153     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2154
2155     for(i = 1; i <= caps.MaxActiveLights; i++) {
2156         hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2157         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2158     }
2159
2160 cleanup:
2161     if (device)
2162     {
2163         UINT refcount = IDirect3DDevice9_Release(device);
2164         ok(!refcount, "Device has %u references left.\n", refcount);
2165     }
2166     if(d3d9) IDirect3D9_Release(d3d9);
2167 }
2168
2169 static void test_set_stream_source(void)
2170 {
2171     D3DPRESENT_PARAMETERS present_parameters;
2172     IDirect3DDevice9 *device = NULL;
2173     IDirect3D9 *d3d9;
2174     HWND hwnd;
2175     HRESULT hr;
2176     IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
2177
2178     d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2179     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2180     hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2181     ok(hwnd != NULL, "Failed to create window\n");
2182     if (!d3d9 || !hwnd) goto cleanup;
2183
2184     ZeroMemory(&present_parameters, sizeof(present_parameters));
2185     present_parameters.Windowed = TRUE;
2186     present_parameters.hDeviceWindow = hwnd;
2187     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2188
2189     hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2190                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2191     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2192        "IDirect3D9_CreateDevice failed with %08x\n", hr);
2193     if(!device)
2194     {
2195         hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd,
2196                                       D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2197         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2198            "IDirect3D9_CreateDevice failed with %08x\n", hr);
2199         if(!device)
2200         {
2201             skip("Failed to create a d3d device\n");
2202             goto cleanup;
2203         }
2204     }
2205
2206     hr = IDirect3DDevice9_CreateVertexBuffer( device, 512, 0, 0, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
2207     ok(hr == D3D_OK, "Failed to create a vertex buffer, hr = %08x\n", hr);
2208     if (SUCCEEDED(hr)) {
2209         /* Some cards(Geforce 7400 at least) accept non-aligned offsets, others(radeon 9000 verified) reject it,
2210          * so accept both results. Wine currently rejects this to be able to optimize the vbo conversion, but writes
2211          * a WARN
2212          */
2213         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32);
2214         ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2215         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32);
2216         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2217         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 2, 32);
2218         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2219         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 3, 32);
2220         ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2221         hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 4, 32);
2222         ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2223     }
2224     /* Try to set the NULL buffer with an offset and stride 0 */
2225     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2226     ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2227     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2228     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2229     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2230     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2231     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2232     ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2233     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2234     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2235
2236     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2237     ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2238
2239 cleanup:
2240     if (pVertexBuffer) IDirect3DVertexBuffer9_Release(pVertexBuffer);
2241     if (device)
2242     {
2243         UINT refcount = IDirect3DDevice9_Release(device);
2244         ok(!refcount, "Device has %u references left.\n", refcount);
2245     }
2246     if(d3d9) IDirect3D9_Release(d3d9);
2247 }
2248
2249 struct formats {
2250     D3DFORMAT DisplayFormat;
2251     D3DFORMAT BackBufferFormat;
2252     BOOL shouldPass;
2253 };
2254
2255 static const struct formats r5g6b5_format_list[] =
2256 {
2257     { D3DFMT_R5G6B5, D3DFMT_R5G6B5, TRUE },
2258     { D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, FALSE },
2259     { D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, FALSE },
2260     { D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, FALSE },
2261     { D3DFMT_R5G6B5, D3DFMT_A8R8G8B8, FALSE },
2262     { 0, 0, 0}
2263 };
2264
2265 static const struct formats x1r5g5b5_format_list[] =
2266 {
2267     { D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, FALSE },
2268     { D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, TRUE },
2269     { D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE },
2270     { D3DFMT_X1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2271     { D3DFMT_X1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2272
2273     /* A1R5G5B5 should not be usable as a display format, it is backbuffer-only */
2274     { D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, FALSE },
2275     { D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, FALSE },
2276     { D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE },
2277     { D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2278     { D3DFMT_A1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2279     { 0, 0, 0}
2280 };
2281
2282 static const struct formats x8r8g8b8_format_list[] =
2283 {
2284     { D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, FALSE },
2285     { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2286     { D3DFMT_X8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2287     { D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, TRUE },
2288     { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE },
2289
2290     /* A1R8G8B8 should not be usable as a display format, it is backbuffer-only */
2291     { D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, FALSE },
2292     { D3DFMT_A8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2293     { D3DFMT_A8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2294     { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, FALSE },
2295     { D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE },
2296     { 0, 0, 0}
2297 };
2298
2299 static void test_display_formats(void)
2300 {
2301     /* Direct3D9 offers 4 display formats R5G6B5, X1R5G5B5, X8R8G8B8 and A2R10G10B10.
2302      * Next to these there are 6 different backbuffer formats. Only a fixed number of
2303      * combinations are possible in FULLSCREEN mode. In windowed mode more combinations are
2304      * allowed due to depth conversion and this is likely driver dependent.
2305      * This test checks which combinations are possible in fullscreen mode and this should not be driver dependent.
2306      * TODO: handle A2R10G10B10 but what hardware supports it? Parhelia? It is very rare. */
2307
2308     UINT Adapter = D3DADAPTER_DEFAULT;
2309     D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
2310     int i, nmodes;
2311     HRESULT hr;
2312
2313     IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2314     ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2315     if(!d3d9) return;
2316
2317     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_R5G6B5);
2318     if(!nmodes) {
2319         skip("Display format R5G6B5 not supported, skipping\n");
2320     } else {
2321         trace("Testing display format R5G6B5\n");
2322         for(i=0; r5g6b5_format_list[i].DisplayFormat != 0; i++)
2323         {
2324             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, FALSE);
2325
2326             if(r5g6b5_format_list[i].shouldPass)
2327                 ok(hr == D3D_OK ||
2328                    broken(hr == D3DERR_NOTAVAILABLE),
2329                    "format %d %d didn't pass with hr=%#08x\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, hr);
2330             else
2331                 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);
2332         }
2333     }
2334
2335     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X1R5G5B5);
2336     if(!nmodes) {
2337         skip("Display format X1R5G5B5 not supported, skipping\n");
2338     } else {
2339         trace("Testing display format X1R5G5B5\n");
2340         for(i=0; x1r5g5b5_format_list[i].DisplayFormat != 0; i++)
2341         {
2342             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, FALSE);
2343
2344             if(x1r5g5b5_format_list[i].shouldPass)
2345                 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);
2346             else
2347                 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);
2348         }
2349     }
2350
2351     nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
2352     if(!nmodes) {
2353         skip("Display format X8R8G8B8 not supported, skipping\n");
2354     } else {
2355         trace("Testing display format X8R8G8B8\n");
2356         for(i=0; x8r8g8b8_format_list[i].DisplayFormat != 0; i++)
2357         {
2358             hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, FALSE);
2359
2360             if(x8r8g8b8_format_list[i].shouldPass)
2361                 ok(hr == D3D_OK ||
2362                    broken(hr == D3DERR_NOTAVAILABLE),
2363                    "format %d %d didn't pass with hr=%#08x\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr);
2364             else
2365                 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);
2366         }
2367     }
2368
2369     if(d3d9) IDirect3D9_Release(d3d9);
2370 }
2371
2372 static void test_scissor_size(void)
2373 {
2374     IDirect3D9 *d3d9_ptr = 0;
2375     unsigned int i;
2376     static struct {
2377         int winx; int winy; int backx; int backy; BOOL window;
2378     } scts[] = { /* scissor tests */
2379         {800, 600, 640, 480, TRUE},
2380         {800, 600, 640, 480, FALSE},
2381         {640, 480, 800, 600, TRUE},
2382         {640, 480, 800, 600, FALSE},
2383     };
2384
2385     d3d9_ptr = pDirect3DCreate9(D3D_SDK_VERSION);
2386     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
2387     if (!d3d9_ptr){
2388         skip("Failed to create IDirect3D9 object\n");
2389         return;
2390     }
2391
2392     for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
2393         IDirect3DDevice9 *device_ptr = 0;
2394         D3DPRESENT_PARAMETERS present_parameters;
2395         HRESULT hr;
2396         HWND hwnd = 0;
2397         RECT scissorrect;
2398
2399         hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
2400                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
2401
2402         if (!scts[i].window)
2403         {
2404             scts[i].backx = screen_width;
2405             scts[i].backy = screen_height;
2406         }
2407
2408         ZeroMemory(&present_parameters, sizeof(present_parameters));
2409         present_parameters.Windowed = scts[i].window;
2410         present_parameters.hDeviceWindow = hwnd;
2411         present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2412         present_parameters.BackBufferWidth = scts[i].backx;
2413         present_parameters.BackBufferHeight = scts[i].backy;
2414         present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
2415         present_parameters.EnableAutoDepthStencil = TRUE;
2416         present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2417
2418         hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2419         if(FAILED(hr)) {
2420             present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
2421             hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2422             if(FAILED(hr)) {
2423                 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2424             }
2425         }
2426         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
2427
2428         if (!device_ptr)
2429         {
2430             DestroyWindow(hwnd);
2431             skip("Creating the device failed\n");
2432             goto err_out;
2433         }
2434
2435         /* Check for the default scissor rect size */
2436         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2437         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2438         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);
2439
2440         /* check the scissorrect values after a reset */
2441         present_parameters.BackBufferWidth = screen_width;
2442         present_parameters.BackBufferHeight = screen_height;
2443         hr = IDirect3DDevice9_Reset(device_ptr, &present_parameters);
2444         ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2445         hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
2446         ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2447
2448         hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2449         ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2450         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);
2451
2452         if(device_ptr) {
2453             ULONG ref;
2454
2455             ref = IDirect3DDevice9_Release(device_ptr);
2456             DestroyWindow(hwnd);
2457             ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
2458         }
2459     }
2460
2461 err_out:
2462     if(d3d9_ptr) IDirect3D9_Release(d3d9_ptr);
2463     return;
2464 }
2465
2466 static void test_multi_device(void)
2467 {
2468     IDirect3DDevice9 *device1 = NULL, *device2 = NULL;
2469     D3DPRESENT_PARAMETERS present_parameters;
2470     HWND hwnd1 = NULL, hwnd2 = NULL;
2471     IDirect3D9 *d3d9;
2472     ULONG refcount;
2473     HRESULT hr;
2474
2475     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2476     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2477     if (!d3d9) goto fail;
2478
2479     hwnd1 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2480     ok(hwnd1 != NULL, "Failed to create a window.\n");
2481     if (!hwnd1) goto fail;
2482
2483     memset(&present_parameters, 0, sizeof(present_parameters));
2484     present_parameters.Windowed = TRUE;
2485     present_parameters.hDeviceWindow = hwnd1;
2486     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2487
2488     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd1,
2489             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device1);
2490     IDirect3D9_Release(d3d9);
2491     d3d9 = NULL;
2492     if (FAILED(hr)) {
2493         skip("Failed to create a device\n");
2494         goto fail;
2495     }
2496
2497     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2498     ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2499     if (!d3d9) goto fail;
2500
2501     hwnd2 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2502     ok(hwnd2 != NULL, "Failed to create a window.\n");
2503     if (!hwnd2) goto fail;
2504
2505     memset(&present_parameters, 0, sizeof(present_parameters));
2506     present_parameters.Windowed = TRUE;
2507     present_parameters.hDeviceWindow = hwnd2;
2508     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2509
2510     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd2,
2511             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device2);
2512     ok(SUCCEEDED(hr), "Failed to create a device, hr %#x\n", hr);
2513     IDirect3D9_Release(d3d9);
2514     d3d9 = NULL;
2515     if (FAILED(hr)) goto fail;
2516
2517 fail:
2518     if (d3d9) IDirect3D9_Release(d3d9);
2519     if (device1)
2520     {
2521         refcount = IDirect3DDevice9_Release(device1);
2522         ok(!refcount, "Device has %u references left.\n", refcount);
2523     }
2524     if (device2)
2525     {
2526         refcount = IDirect3DDevice9_Release(device2);
2527         ok(!refcount, "Device has %u references left.\n", refcount);
2528     }
2529     if (hwnd1) DestroyWindow(hwnd1);
2530     if (hwnd2) DestroyWindow(hwnd2);
2531 }
2532
2533 static HWND filter_messages;
2534
2535 enum message_window
2536 {
2537     DEVICE_WINDOW,
2538     FOCUS_WINDOW,
2539 };
2540
2541 struct message
2542 {
2543     UINT message;
2544     enum message_window window;
2545 };
2546
2547 static const struct message *expect_messages;
2548 static HWND device_window, focus_window;
2549
2550 struct wndproc_thread_param
2551 {
2552     HWND dummy_window;
2553     HANDLE window_created;
2554     HANDLE test_finished;
2555     BOOL running_in_foreground;
2556 };
2557
2558 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2559 {
2560     if (filter_messages && filter_messages == hwnd)
2561     {
2562         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2563             todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2564     }
2565
2566     if (expect_messages)
2567     {
2568         HWND w;
2569
2570         switch (expect_messages->window)
2571         {
2572             case DEVICE_WINDOW:
2573                 w = device_window;
2574                 break;
2575
2576             case FOCUS_WINDOW:
2577                 w = focus_window;
2578                 break;
2579
2580             default:
2581                 w = NULL;
2582                 break;
2583         };
2584
2585         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2586     }
2587
2588     return DefWindowProcA(hwnd, message, wparam, lparam);
2589 }
2590
2591 static DWORD WINAPI wndproc_thread(void *param)
2592 {
2593     struct wndproc_thread_param *p = param;
2594     DWORD res;
2595     BOOL ret;
2596
2597     p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2598             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2599     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2600
2601     ret = SetEvent(p->window_created);
2602     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2603
2604     for (;;)
2605     {
2606         MSG msg;
2607
2608         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2609         res = WaitForSingleObject(p->test_finished, 100);
2610         if (res == WAIT_OBJECT_0) break;
2611         if (res != WAIT_TIMEOUT)
2612         {
2613             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2614             break;
2615         }
2616     }
2617
2618     DestroyWindow(p->dummy_window);
2619
2620     return 0;
2621 }
2622
2623 static void test_wndproc(void)
2624 {
2625     struct wndproc_thread_param thread_params;
2626     IDirect3DDevice9 *device;
2627     WNDCLASSA wc = {0};
2628     IDirect3D9 *d3d9;
2629     HANDLE thread;
2630     LONG_PTR proc;
2631     ULONG ref;
2632     DWORD res, tid;
2633     HWND tmp;
2634
2635     static const struct message messages[] =
2636     {
2637         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2638         {WM_ACTIVATE,           FOCUS_WINDOW},
2639         {WM_SETFOCUS,           FOCUS_WINDOW},
2640         {0,                     0},
2641     };
2642
2643     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2644     {
2645         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2646         return;
2647     }
2648
2649     wc.lpfnWndProc = test_proc;
2650     wc.lpszClassName = "d3d9_test_wndproc_wc";
2651     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2652
2653     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2654     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2655     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2656     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2657
2658     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2659             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2660     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2661             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2662     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2663     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2664
2665     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2666     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2667
2668     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2669     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2670             (LONG_PTR)test_proc, proc);
2671     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2672     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2673             (LONG_PTR)test_proc, proc);
2674
2675     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2676             device_window, focus_window, thread_params.dummy_window);
2677
2678     tmp = GetFocus();
2679     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2680     if (thread_params.running_in_foreground)
2681     {
2682         tmp = GetForegroundWindow();
2683         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2684                 thread_params.dummy_window, tmp);
2685     }
2686     else
2687         skip("Not running in foreground, skip foreground window test\n");
2688
2689     flush_events();
2690
2691     expect_messages = messages;
2692
2693     device = create_device(d3d9, device_window, focus_window, FALSE);
2694     if (!device)
2695     {
2696         skip("Failed to create a D3D device, skipping tests.\n");
2697         goto done;
2698     }
2699
2700     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2701             expect_messages->message, expect_messages->window);
2702     expect_messages = NULL;
2703
2704     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2705     {
2706         tmp = GetFocus();
2707         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2708         tmp = GetForegroundWindow();
2709         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2710     }
2711     SetForegroundWindow(focus_window);
2712     flush_events();
2713
2714     filter_messages = focus_window;
2715
2716     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2717     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2718             (LONG_PTR)test_proc, proc);
2719
2720     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2721     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2722             (LONG_PTR)test_proc, proc);
2723
2724     ref = IDirect3DDevice9_Release(device);
2725     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2726
2727     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2728     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2729             (LONG_PTR)test_proc, proc);
2730
2731     device = create_device(d3d9, focus_window, focus_window, FALSE);
2732     if (!device)
2733     {
2734         skip("Failed to create a D3D device, skipping tests.\n");
2735         goto done;
2736     }
2737
2738     ref = IDirect3DDevice9_Release(device);
2739     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2740
2741     device = create_device(d3d9, device_window, focus_window, FALSE);
2742     if (!device)
2743     {
2744         skip("Failed to create a D3D device, skipping tests.\n");
2745         goto done;
2746     }
2747
2748     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2749     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2750             (LONG_PTR)test_proc, proc);
2751
2752     ref = IDirect3DDevice9_Release(device);
2753     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2754
2755     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2756     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2757             (LONG_PTR)DefWindowProcA, proc);
2758
2759 done:
2760     filter_messages = NULL;
2761     IDirect3D9_Release(d3d9);
2762
2763     SetEvent(thread_params.test_finished);
2764     WaitForSingleObject(thread, INFINITE);
2765     CloseHandle(thread_params.test_finished);
2766     CloseHandle(thread_params.window_created);
2767     CloseHandle(thread);
2768
2769     DestroyWindow(device_window);
2770     DestroyWindow(focus_window);
2771     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2772 }
2773
2774 static void test_wndproc_windowed(void)
2775 {
2776     struct wndproc_thread_param thread_params;
2777     IDirect3DDevice9 *device;
2778     WNDCLASSA wc = {0};
2779     IDirect3D9 *d3d9;
2780     HANDLE thread;
2781     LONG_PTR proc;
2782     HRESULT hr;
2783     ULONG ref;
2784     DWORD res, tid;
2785     HWND tmp;
2786
2787     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2788     {
2789         skip("Failed to create IDirect3D9 object, skipping tests.\n");
2790         return;
2791     }
2792
2793     wc.lpfnWndProc = test_proc;
2794     wc.lpszClassName = "d3d9_test_wndproc_wc";
2795     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2796
2797     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2798     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2799     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2800     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2801
2802     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2803             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2804     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2805             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2806     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2807     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2808
2809     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2810     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2811
2812     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2813     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2814             (LONG_PTR)test_proc, proc);
2815     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2816     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2817             (LONG_PTR)test_proc, proc);
2818
2819     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2820             device_window, focus_window, thread_params.dummy_window);
2821
2822     tmp = GetFocus();
2823     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2824     if (thread_params.running_in_foreground)
2825     {
2826         tmp = GetForegroundWindow();
2827         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2828                 thread_params.dummy_window, tmp);
2829     }
2830     else
2831         skip("Not running in foreground, skip foreground window test\n");
2832
2833     filter_messages = focus_window;
2834
2835     device = create_device(d3d9, device_window, focus_window, TRUE);
2836     if (!device)
2837     {
2838         skip("Failed to create a D3D device, skipping tests.\n");
2839         goto done;
2840     }
2841
2842     tmp = GetFocus();
2843     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2844     tmp = GetForegroundWindow();
2845     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2846             thread_params.dummy_window, tmp);
2847
2848     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2849     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2850             (LONG_PTR)test_proc, proc);
2851
2852     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2853     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2854             (LONG_PTR)test_proc, proc);
2855
2856     filter_messages = NULL;
2857
2858     hr = reset_device(device, device_window, FALSE);
2859     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2860
2861     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2862     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2863             (LONG_PTR)test_proc, proc);
2864
2865     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2866     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2867             (LONG_PTR)test_proc, proc);
2868
2869     hr = reset_device(device, device_window, TRUE);
2870     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2871
2872     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2873     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2874             (LONG_PTR)test_proc, proc);
2875
2876     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2877     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2878             (LONG_PTR)test_proc, proc);
2879
2880     filter_messages = focus_window;
2881
2882     ref = IDirect3DDevice9_Release(device);
2883     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2884
2885     filter_messages = device_window;
2886
2887     device = create_device(d3d9, focus_window, focus_window, TRUE);
2888     if (!device)
2889     {
2890         skip("Failed to create a D3D device, skipping tests.\n");
2891         goto done;
2892     }
2893
2894     filter_messages = NULL;
2895
2896     hr = reset_device(device, focus_window, FALSE);
2897     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2898
2899     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2900     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2901             (LONG_PTR)test_proc, proc);
2902
2903     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2904     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2905             (LONG_PTR)test_proc, proc);
2906
2907     hr = reset_device(device, focus_window, TRUE);
2908     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2909
2910     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2911     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2912             (LONG_PTR)test_proc, proc);
2913
2914     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2915     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2916             (LONG_PTR)test_proc, proc);
2917
2918     filter_messages = device_window;
2919
2920     ref = IDirect3DDevice9_Release(device);
2921     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2922
2923     device = create_device(d3d9, device_window, focus_window, TRUE);
2924     if (!device)
2925     {
2926         skip("Failed to create a D3D device, skipping tests.\n");
2927         goto done;
2928     }
2929
2930     filter_messages = NULL;
2931
2932     hr = reset_device(device, device_window, FALSE);
2933     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2934
2935     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2936     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2937             (LONG_PTR)test_proc, proc);
2938
2939     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2940     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2941             (LONG_PTR)test_proc, proc);
2942
2943     hr = reset_device(device, device_window, TRUE);
2944     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2945
2946     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2947     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2948             (LONG_PTR)test_proc, proc);
2949
2950     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2951     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2952             (LONG_PTR)test_proc, proc);
2953
2954     filter_messages = device_window;
2955
2956     ref = IDirect3DDevice9_Release(device);
2957     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2958
2959 done:
2960     filter_messages = NULL;
2961     IDirect3D9_Release(d3d9);
2962
2963     SetEvent(thread_params.test_finished);
2964     WaitForSingleObject(thread, INFINITE);
2965     CloseHandle(thread_params.test_finished);
2966     CloseHandle(thread_params.window_created);
2967     CloseHandle(thread);
2968
2969     DestroyWindow(device_window);
2970     DestroyWindow(focus_window);
2971     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2972 }
2973
2974 static void test_reset_fullscreen(void)
2975 {
2976     WNDCLASSEX wc = {0};
2977     IDirect3DDevice9 *device = NULL;
2978     IDirect3D9 *d3d = NULL;
2979     ATOM atom;
2980     static const struct message messages[] =
2981     {
2982         {WM_ACTIVATEAPP,    FOCUS_WINDOW},
2983         {0,                     0},
2984     };
2985
2986     d3d = pDirect3DCreate9(D3D_SDK_VERSION);
2987     ok(d3d != NULL, "Failed to create an IDirect3D object.\n");
2988     expect_messages = messages;
2989
2990     wc.cbSize = sizeof(WNDCLASSEX);
2991     wc.lpfnWndProc = test_proc;
2992     wc.lpszClassName = "test_reset_fullscreen";
2993
2994     atom = RegisterClassEx(&wc);
2995     ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
2996
2997     device_window = focus_window = CreateWindowEx(0, wc.lpszClassName, "Test Reset Fullscreen", 0, 0, 0, screen_width, screen_height, NULL, NULL, NULL, NULL);
2998     ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
2999
3000     /*
3001      * Create a device in windowed mode.
3002      * Since the device is windowed and we haven't called any methods that
3003      * could show the window (such as ShowWindow or SetWindowPos) yet,
3004      * WM_ACTIVATEAPP will not have been sent.
3005      */
3006     device = create_device(d3d, device_window, focus_window, TRUE);
3007     if (!device)
3008     {
3009         skip("Unable to create device.  Skipping test.\n");
3010         goto cleanup;
3011     }
3012
3013     /*
3014      * Switch to fullscreen mode.
3015      * This will force the window to be shown and will cause the WM_ACTIVATEAPP
3016      * message to be sent.
3017      */
3018     ok(SUCCEEDED(reset_device(device, device_window, FALSE)), "Failed to reset device.\n");
3019
3020     flush_events();
3021     ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
3022     expect_messages = NULL;
3023
3024 cleanup:
3025     if (device) IDirect3DDevice9_Release(device);
3026     if (d3d) IDirect3D9_Release(d3d);
3027     DestroyWindow(device_window);
3028     device_window = focus_window = NULL;
3029     UnregisterClass(wc.lpszClassName, GetModuleHandle(NULL));
3030 }
3031
3032
3033 static inline void set_fpu_cw(WORD cw)
3034 {
3035 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3036 #define D3D9_TEST_SET_FPU_CW 1
3037     __asm__ volatile ("fnclex");
3038     __asm__ volatile ("fldcw %0" : : "m" (cw));
3039 #elif defined(__i386__) && defined(_MSC_VER)
3040 #define D3D9_TEST_SET_FPU_CW 1
3041     __asm fnclex;
3042     __asm fldcw cw;
3043 #endif
3044 }
3045
3046 static inline WORD get_fpu_cw(void)
3047 {
3048     WORD cw = 0;
3049 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3050 #define D3D9_TEST_GET_FPU_CW 1
3051     __asm__ volatile ("fnstcw %0" : "=m" (cw));
3052 #elif defined(__i386__) && defined(_MSC_VER)
3053 #define D3D9_TEST_GET_FPU_CW 1
3054     __asm fnstcw cw;
3055 #endif
3056     return cw;
3057 }
3058
3059 static void test_fpu_setup(void)
3060 {
3061 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
3062     D3DPRESENT_PARAMETERS present_parameters;
3063     IDirect3DDevice9 *device;
3064     HWND window = NULL;
3065     IDirect3D9 *d3d9;
3066     HRESULT hr;
3067     WORD cw;
3068
3069     d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
3070     ok(!!d3d9, "Failed to create a d3d9 object.\n");
3071     if (!d3d9) return;
3072
3073     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3074     ok(!!window, "Failed to create a window.\n");
3075     if (!window) goto done;
3076
3077     memset(&present_parameters, 0, sizeof(present_parameters));
3078     present_parameters.Windowed = TRUE;
3079     present_parameters.hDeviceWindow = window;
3080     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
3081
3082     set_fpu_cw(0xf60);
3083     cw = get_fpu_cw();
3084     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3085
3086     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3087             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
3088     if (FAILED(hr))
3089     {
3090         skip("Failed to create a device, hr %#x.\n", hr);
3091         set_fpu_cw(0x37f);
3092         goto done;
3093     }
3094
3095     cw = get_fpu_cw();
3096     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3097
3098     IDirect3DDevice9_Release(device);
3099
3100     cw = get_fpu_cw();
3101     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3102     set_fpu_cw(0xf60);
3103     cw = get_fpu_cw();
3104     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3105
3106     hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3107             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
3108     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
3109
3110     cw = get_fpu_cw();
3111     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3112     set_fpu_cw(0x37f);
3113
3114     IDirect3DDevice9_Release(device);
3115
3116 done:
3117     if (window) DestroyWindow(window);
3118     if (d3d9) IDirect3D9_Release(d3d9);
3119 #endif
3120 }
3121
3122 static void test_window_style(void)
3123 {
3124     RECT focus_rect, fullscreen_rect, r;
3125     LONG device_style, device_exstyle;
3126     LONG focus_style, focus_exstyle;
3127     LONG style, expected_style;
3128     IDirect3DDevice9 *device;
3129     IDirect3D9 *d3d9;
3130     ULONG ref;
3131
3132
3133     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3134     {
3135         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3136         return;
3137     }
3138
3139     focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3140             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3141     device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3142             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3143
3144     device_style = GetWindowLongA(device_window, GWL_STYLE);
3145     device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3146     focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3147     focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3148
3149     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3150     GetWindowRect(focus_window, &focus_rect);
3151
3152     device = create_device(d3d9, device_window, focus_window, FALSE);
3153     if (!device)
3154     {
3155         skip("Failed to create a D3D device, skipping tests.\n");
3156         goto done;
3157     }
3158
3159     style = GetWindowLongA(device_window, GWL_STYLE);
3160     expected_style = device_style | WS_VISIBLE;
3161     todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3162             expected_style, style);
3163     style = GetWindowLongA(device_window, GWL_EXSTYLE);
3164     expected_style = device_exstyle | WS_EX_TOPMOST;
3165     todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3166             expected_style, style);
3167
3168     style = GetWindowLongA(focus_window, GWL_STYLE);
3169     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3170             focus_style, style);
3171     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3172     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3173             focus_exstyle, style);
3174
3175     GetWindowRect(device_window, &r);
3176     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3177             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3178             r.left, r.top, r.right, r.bottom);
3179     GetClientRect(device_window, &r);
3180     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3181     GetWindowRect(focus_window, &r);
3182     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3183             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3184             r.left, r.top, r.right, r.bottom);
3185
3186     ref = IDirect3DDevice9_Release(device);
3187     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3188
3189 done:
3190     IDirect3D9_Release(d3d9);
3191
3192     DestroyWindow(device_window);
3193     DestroyWindow(focus_window);
3194 }
3195
3196 static const POINT *expect_pos;
3197
3198 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
3199 {
3200     if (message == WM_MOUSEMOVE)
3201     {
3202         if (expect_pos && expect_pos->x && expect_pos->y)
3203         {
3204             POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
3205
3206             ClientToScreen(window, &p);
3207             if (expect_pos->x == p.x && expect_pos->y == p.y)
3208                 ++expect_pos;
3209         }
3210     }
3211
3212     return DefWindowProcA(window, message, wparam, lparam);
3213 }
3214
3215 static void test_cursor_pos(void)
3216 {
3217     IDirect3DSurface9 *cursor;
3218     IDirect3DDevice9 *device;
3219     WNDCLASSA wc = {0};
3220     IDirect3D9 *d3d9;
3221     UINT refcount;
3222     HWND window;
3223     HRESULT hr;
3224     BOOL ret;
3225
3226     /* Note that we don't check for movement we're not supposed to receive.
3227      * That's because it's hard to distinguish from the user accidentally
3228      * moving the mouse. */
3229     static const POINT points[] =
3230     {
3231         {50, 50},
3232         {75, 75},
3233         {100, 100},
3234         {125, 125},
3235         {150, 150},
3236         {125, 125},
3237         {150, 150},
3238         {150, 150},
3239         {0, 0},
3240     };
3241
3242     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3243     {
3244         skip("Failed to create IDirect3D9 object, skipping cursor tests.\n");
3245         return;
3246     }
3247
3248     wc.lpfnWndProc = test_cursor_proc;
3249     wc.lpszClassName = "d3d9_test_cursor_wc";
3250     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3251     window = CreateWindow("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3252             0, 0, 320, 240, NULL, NULL, NULL, NULL);
3253     ShowWindow(window, SW_SHOW);
3254
3255     device = create_device(d3d9, window, window, TRUE);
3256     if (!device)
3257     {
3258         skip("Failed to create a D3D device, skipping tests.\n");
3259         goto done;
3260     }
3261
3262     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
3263             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
3264     ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
3265     hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
3266     ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
3267     IDirect3DSurface9_Release(cursor);
3268     ret = IDirect3DDevice9_ShowCursor(device, TRUE);
3269     ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
3270
3271     flush_events();
3272     expect_pos = points;
3273
3274     ret = SetCursorPos(50, 50);
3275     ok(ret, "Failed to set cursor position.\n");
3276     flush_events();
3277
3278     IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3279     flush_events();
3280     /* SetCursorPosition() eats duplicates. */
3281     IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3282     flush_events();
3283
3284     ret = SetCursorPos(100, 100);
3285     ok(ret, "Failed to set cursor position.\n");
3286     flush_events();
3287     /* Even if the position was set with SetCursorPos(). */
3288     IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
3289     flush_events();
3290
3291     IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3292     flush_events();
3293     ret = SetCursorPos(150, 150);
3294     ok(ret, "Failed to set cursor position.\n");
3295     flush_events();
3296     IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3297     flush_events();
3298
3299     IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
3300     flush_events();
3301     /* SetCursorPos() doesn't. */
3302     ret = SetCursorPos(150, 150);
3303     ok(ret, "Failed to set cursor position.\n");
3304     flush_events();
3305
3306     ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
3307        (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
3308
3309     refcount = IDirect3DDevice9_Release(device);
3310     ok(!refcount, "Device has %u references left.\n", refcount);
3311 done:
3312     DestroyWindow(window);
3313     UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
3314     if (d3d9)
3315         IDirect3D9_Release(d3d9);
3316 }
3317
3318 static void test_mode_change(void)
3319 {
3320     RECT fullscreen_rect, focus_rect, r;
3321     IDirect3DSurface9 *backbuffer;
3322     IDirect3DDevice9 *device;
3323     D3DSURFACE_DESC desc;
3324     IDirect3D9 *d3d9;
3325     DEVMODEW devmode;
3326     UINT refcount;
3327     HRESULT hr;
3328     DWORD ret;
3329
3330     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3331     {
3332         skip("Failed to create IDirect3D9 object, skipping mode change tests.\n");
3333         return;
3334     }
3335
3336     focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3337             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3338     device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3339             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3340
3341     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3342     GetWindowRect(focus_window, &focus_rect);
3343
3344     device = create_device(d3d9, device_window, focus_window, FALSE);
3345     if (!device)
3346     {
3347         skip("Failed to create a D3D device, skipping tests.\n");
3348         goto done;
3349     }
3350
3351     memset(&devmode, 0, sizeof(devmode));
3352     devmode.dmSize = sizeof(devmode);
3353     devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3354     devmode.dmPelsWidth = 640;
3355     devmode.dmPelsHeight = 480;
3356
3357     ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3358     ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3359
3360     memset(&devmode, 0, sizeof(devmode));
3361     devmode.dmSize = sizeof(devmode);
3362     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3363     ok(ret, "Failed to get display mode.\n");
3364     ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3365     ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3366
3367     GetWindowRect(device_window, &r);
3368     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3369             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3370             r.left, r.top, r.right, r.bottom);
3371     GetWindowRect(focus_window, &r);
3372     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3373             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3374             r.left, r.top, r.right, r.bottom);
3375
3376     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3377     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3378     hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
3379     ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3380     ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3381     ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3382     IDirect3DSurface9_Release(backbuffer);
3383
3384     refcount = IDirect3DDevice9_Release(device);
3385     ok(!refcount, "Device has %u references left.\n", refcount);
3386
3387     memset(&devmode, 0, sizeof(devmode));
3388     devmode.dmSize = sizeof(devmode);
3389     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3390     ok(ret, "Failed to get display mode.\n");
3391     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3392     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3393
3394 done:
3395     DestroyWindow(device_window);
3396     DestroyWindow(focus_window);
3397     if (d3d9)
3398         IDirect3D9_Release(d3d9);
3399
3400     memset(&devmode, 0, sizeof(devmode));
3401     devmode.dmSize = sizeof(devmode);
3402     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3403     ok(ret, "Failed to get display mode.\n");
3404     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3405     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3406 }
3407
3408 static void test_device_window_reset(void)
3409 {
3410     RECT fullscreen_rect, device_rect, r;
3411     IDirect3DDevice9 *device;
3412     WNDCLASSA wc = {0};
3413     IDirect3D9 *d3d9;
3414     LONG_PTR proc;
3415     HRESULT hr;
3416     ULONG ref;
3417
3418     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3419     {
3420         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3421         return;
3422     }
3423
3424     wc.lpfnWndProc = test_proc;
3425     wc.lpszClassName = "d3d9_test_wndproc_wc";
3426     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3427
3428     focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3429             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3430     device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3431             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3432
3433     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3434     GetWindowRect(device_window, &device_rect);
3435
3436     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3437     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3438             (LONG_PTR)test_proc, proc);
3439     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3440     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3441             (LONG_PTR)test_proc, proc);
3442
3443     device = create_device(d3d9, NULL, focus_window, FALSE);
3444     if (!device)
3445     {
3446         skip("Failed to create a D3D device, skipping tests.\n");
3447         goto done;
3448     }
3449
3450     GetWindowRect(focus_window, &r);
3451     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3452             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3453             r.left, r.top, r.right, r.bottom);
3454     GetWindowRect(device_window, &r);
3455     ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3456             device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3457             r.left, r.top, r.right, r.bottom);
3458
3459     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3460     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3461             (LONG_PTR)test_proc, proc);
3462     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3463     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3464             (LONG_PTR)test_proc, proc);
3465
3466     hr = reset_device(device, device_window, FALSE);
3467     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3468
3469     GetWindowRect(focus_window, &r);
3470     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3471             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3472             r.left, r.top, r.right, r.bottom);
3473     GetWindowRect(device_window, &r);
3474     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3475             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3476             r.left, r.top, r.right, r.bottom);
3477
3478     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3479     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3480             (LONG_PTR)test_proc, proc);
3481     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3482     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3483             (LONG_PTR)test_proc, proc);
3484
3485     ref = IDirect3DDevice9_Release(device);
3486     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3487
3488 done:
3489     IDirect3D9_Release(d3d9);
3490     DestroyWindow(device_window);
3491     DestroyWindow(focus_window);
3492     UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3493 }
3494
3495 static void test_reset_resources(void)
3496 {
3497     IDirect3DSurface9 *surface, *rt;
3498     IDirect3DTexture9 *texture;
3499     IDirect3DDevice9 *device;
3500     IDirect3D9 *d3d9;
3501     unsigned int i;
3502     D3DCAPS9 caps;
3503     HWND window;
3504     HRESULT hr;
3505     ULONG ref;
3506
3507     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3508             0, 0, 640, 480, 0, 0, 0, 0);
3509
3510     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3511     {
3512         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3513         DestroyWindow(window);
3514         return;
3515     }
3516
3517     if (!(device = create_device(d3d9, window, window, TRUE)))
3518     {
3519         skip("Failed to create a D3D device, skipping tests.\n");
3520         goto done;
3521     }
3522
3523     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3524     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3525
3526     hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
3527             D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
3528     ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
3529     hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
3530     ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
3531     IDirect3DSurface9_Release(surface);
3532
3533     for (i = 0; i < caps.NumSimultaneousRTs; ++i)
3534     {
3535         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3536                 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
3537         ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
3538         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3539         ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
3540         IDirect3DTexture9_Release(texture);
3541         hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
3542         ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
3543         IDirect3DSurface9_Release(surface);
3544     }
3545
3546     hr = reset_device(device, device_window, TRUE);
3547     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3548
3549     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3550     ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3551     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
3552     ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3553     ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3554     IDirect3DSurface9_Release(surface);
3555     IDirect3DSurface9_Release(rt);
3556
3557     for (i = 1; i < caps.NumSimultaneousRTs; ++i)
3558     {
3559         hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
3560         ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
3561     }
3562
3563     ref = IDirect3DDevice9_Release(device);
3564     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3565
3566 done:
3567     IDirect3D9_Release(d3d9);
3568     DestroyWindow(window);
3569 }
3570
3571 static void test_set_rt_vp_scissor(void)
3572 {
3573     IDirect3DStateBlock9 *stateblock;
3574     IDirect3DDevice9 *device;
3575     IDirect3DSurface9 *rt;
3576     IDirect3D9 *d3d9;
3577     D3DVIEWPORT9 vp;
3578     UINT refcount;
3579     HWND window;
3580     HRESULT hr;
3581     RECT rect;
3582
3583     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3584     {
3585         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3586         return;
3587     }
3588
3589     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3590             0, 0, 640, 480, 0, 0, 0, 0);
3591     if (!(device = create_device(d3d9, window, window, TRUE)))
3592     {
3593         skip("Failed to create a D3D device, skipping tests.\n");
3594         DestroyWindow(window);
3595         return;
3596     }
3597
3598     hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3599             D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
3600     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3601
3602     hr = IDirect3DDevice9_GetViewport(device, &vp);
3603     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3604     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3605     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3606     ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3607     ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3608     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3609     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3610
3611     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3612     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3613     ok(rect.left == 0 && rect.top == 0 && rect.right == screen_width && rect.bottom == screen_height,
3614             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3615             rect.left, rect.top, rect.right, rect.bottom);
3616
3617     hr = IDirect3DDevice9_BeginStateBlock(device);
3618     ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3619
3620     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3621     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3622
3623     hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
3624     ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3625     IDirect3DStateBlock9_Release(stateblock);
3626
3627     hr = IDirect3DDevice9_GetViewport(device, &vp);
3628     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3629     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3630     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3631     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3632     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3633     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3634     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3635
3636     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3637     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3638     ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3639             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3640             rect.left, rect.top, rect.right, rect.bottom);
3641
3642     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3643     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3644
3645     vp.X = 10;
3646     vp.Y = 20;
3647     vp.Width = 30;
3648     vp.Height = 40;
3649     vp.MinZ = 0.25f;
3650     vp.MaxZ = 0.75f;
3651     hr = IDirect3DDevice9_SetViewport(device, &vp);
3652     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3653
3654     SetRect(&rect, 50, 60, 70, 80);
3655     hr = IDirect3DDevice9_SetScissorRect(device, &rect);
3656     ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
3657
3658     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3659     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3660
3661     hr = IDirect3DDevice9_GetViewport(device, &vp);
3662     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3663     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3664     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3665     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3666     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3667     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3668     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3669
3670     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3671     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3672     ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3673             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3674             rect.left, rect.top, rect.right, rect.bottom);
3675
3676     IDirect3DSurface9_Release(rt);
3677     refcount = IDirect3DDevice9_Release(device);
3678     ok(!refcount, "Device has %u references left.\n", refcount);
3679     IDirect3D9_Release(d3d9);
3680     DestroyWindow(window);
3681 }
3682
3683 static void test_volume_get_container(void)
3684 {
3685     IDirect3DVolumeTexture9 *texture = NULL;
3686     IDirect3DVolume9 *volume = NULL;
3687     IDirect3DDevice9 *device;
3688     IUnknown *container;
3689     IDirect3D9 *d3d9;
3690     ULONG refcount;
3691     D3DCAPS9 caps;
3692     HWND window;
3693     HRESULT hr;
3694
3695     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3696     {
3697         skip("Failed to create d3d9 object, skipping tests.\n");
3698         return;
3699     }
3700
3701     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3702             0, 0, 640, 480, 0, 0, 0, 0);
3703     if (!(device = create_device(d3d9, window, window, TRUE)))
3704     {
3705         skip("Failed to create a D3D device, skipping tests.\n");
3706         IDirect3D9_Release(d3d9);
3707         DestroyWindow(window);
3708         return;
3709     }
3710
3711     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3712     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3713     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3714     {
3715         skip("No volume texture support, skipping tests.\n");
3716         IDirect3DDevice9_Release(device);
3717         IDirect3D9_Release(d3d9);
3718         DestroyWindow(window);
3719         return;
3720     }
3721
3722     hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3723             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3724     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3725     ok(!!texture, "Got unexpected texture %p.\n", texture);
3726
3727     hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3728     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3729     ok(!!volume, "Got unexpected volume %p.\n", volume);
3730
3731     /* These should work... */
3732     container = NULL;
3733     hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
3734     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3735     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3736     IUnknown_Release(container);
3737
3738     container = NULL;
3739     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
3740     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3741     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3742     IUnknown_Release(container);
3743
3744     container = NULL;
3745     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
3746     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3747     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3748     IUnknown_Release(container);
3749
3750     container = NULL;
3751     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
3752     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3753     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3754     IUnknown_Release(container);
3755
3756     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3757     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
3758     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3759     ok(!container, "Got unexpected container %p.\n", container);
3760
3761     IDirect3DVolume9_Release(volume);
3762     IDirect3DVolumeTexture9_Release(texture);
3763     refcount = IDirect3DDevice9_Release(device);
3764     ok(!refcount, "Device has %u references left.\n", refcount);
3765     IDirect3D9_Release(d3d9);
3766     DestroyWindow(window);
3767 }
3768
3769 static void test_volume_resource(void)
3770 {
3771     IDirect3DVolumeTexture9 *texture;
3772     IDirect3DResource9 *resource;
3773     IDirect3DVolume9 *volume;
3774     IDirect3DDevice9 *device;
3775     IDirect3D9 *d3d9;
3776     ULONG refcount;
3777     D3DCAPS9 caps;
3778     HWND window;
3779     HRESULT hr;
3780
3781     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3782     {
3783         skip("Failed to create d3d9 object, skipping tests.\n");
3784         return;
3785     }
3786
3787     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3788             0, 0, 640, 480, 0, 0, 0, 0);
3789     if (!(device = create_device(d3d9, window, window, TRUE)))
3790     {
3791         skip("Failed to create a D3D device, skipping tests.\n");
3792         IDirect3D9_Release(d3d9);
3793         DestroyWindow(window);
3794         return;
3795     }
3796
3797     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3798     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3799     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3800     {
3801         skip("No volume texture support, skipping tests.\n");
3802         IDirect3DDevice9_Release(device);
3803         IDirect3D9_Release(d3d9);
3804         DestroyWindow(window);
3805         return;
3806     }
3807
3808     hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3809             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3810     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3811     hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3812     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3813     IDirect3DVolumeTexture9_Release(texture);
3814
3815     hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
3816     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3817
3818     IDirect3DVolume9_Release(volume);
3819     refcount = IDirect3DDevice9_Release(device);
3820     ok(!refcount, "Device has %u references left.\n", refcount);
3821     IDirect3D9_Release(d3d9);
3822     DestroyWindow(window);
3823 }
3824
3825 static void test_vb_lock_flags(void)
3826 {
3827     static const struct
3828     {
3829         DWORD flags;
3830         const char *debug_string;
3831         HRESULT win7_result;
3832     }
3833     test_data[] =
3834     {
3835         {D3DLOCK_READONLY,                          "D3DLOCK_READONLY",                         D3D_OK            },
3836         {D3DLOCK_DISCARD,                           "D3DLOCK_DISCARD",                          D3D_OK            },
3837         {D3DLOCK_NOOVERWRITE,                       "D3DLOCK_NOOVERWRITE",                      D3D_OK            },
3838         {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD,     "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD",    D3D_OK            },
3839         {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY,    "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY",   D3D_OK            },
3840         {D3DLOCK_READONLY | D3DLOCK_DISCARD,        "D3DLOCK_READONLY | D3DLOCK_DISCARD",       D3DERR_INVALIDCALL},
3841         /* Completely bogus flags aren't an error. */
3842         {0xdeadbeef,                                "0xdeadbeef",                               D3DERR_INVALIDCALL},
3843     };
3844     IDirect3DVertexBuffer9 *buffer;
3845     IDirect3DDevice9 *device;
3846     IDirect3D9 *d3d9;
3847     unsigned int i;
3848     ULONG refcount;
3849     HWND window;
3850     HRESULT hr;
3851     void *data;
3852
3853     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3854     {
3855         skip("Failed to create d3d9 object, skipping tests.\n");
3856         return;
3857     }
3858
3859     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3860             0, 0, 640, 480, 0, 0, 0, 0);
3861     if (!(device = create_device(d3d9, window, window, TRUE)))
3862     {
3863         skip("Failed to create a D3D device, skipping tests.\n");
3864         IDirect3D9_Release(d3d9);
3865         DestroyWindow(window);
3866         return;
3867     }
3868
3869     hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
3870     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3871
3872     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
3873     {
3874         hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
3875         /* Windows XP always returns D3D_OK even with flags that don't make
3876          * sense. Windows 7 returns an error. At least one game (Shaiya)
3877          * depends on the Windows XP result, so mark the Windows 7 behavior as
3878          * broken. */
3879         ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
3880                 hr, test_data[i].debug_string);
3881         if (SUCCEEDED(hr))
3882         {
3883             ok(!!data, "Got unexpected data %p.\n", data);
3884             hr = IDirect3DVertexBuffer9_Unlock(buffer);
3885             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3886         }
3887     }
3888
3889     IDirect3DVertexBuffer9_Release(buffer);
3890     refcount = IDirect3DDevice9_Release(device);
3891     ok(!refcount, "Device has %u references left.\n", refcount);
3892     IDirect3D9_Release(d3d9);
3893     DestroyWindow(window);
3894 }
3895
3896 static const char *debug_d3dpool(D3DPOOL pool)
3897 {
3898     switch (pool)
3899     {
3900         case D3DPOOL_DEFAULT:
3901             return "D3DPOOL_DEFAULT";
3902         case D3DPOOL_SYSTEMMEM:
3903             return "D3DPOOL_SYSTEMMEM";
3904         case D3DPOOL_SCRATCH:
3905             return "D3DPOOL_SCRATCH";
3906         case D3DPOOL_MANAGED:
3907             return "D3DPOOL_MANAGED";
3908         default:
3909             return "unknown pool";
3910     }
3911 }
3912
3913 static void test_vertex_buffer_alignment(void)
3914 {
3915     static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
3916     static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
3917     IDirect3DVertexBuffer9 *buffer = NULL;
3918     const unsigned int align = 16;
3919     IDirect3DDevice9 *device;
3920     unsigned int i, j;
3921     IDirect3D9 *d3d9;
3922     ULONG refcount;
3923     HWND window;
3924     HRESULT hr;
3925     void *data;
3926
3927     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3928     {
3929         skip("Failed to create d3d9 object, skipping tests.\n");
3930         return;
3931     }
3932
3933     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3934             0, 0, 640, 480, 0, 0, 0, 0);
3935     if (!(device = create_device(d3d9, window, window, TRUE)))
3936     {
3937         skip("Failed to create a D3D device, skipping tests.\n");
3938         IDirect3D9_Release(d3d9);
3939         DestroyWindow(window);
3940         return;
3941     }
3942
3943     for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
3944     {
3945         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
3946         {
3947             hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
3948             if (pools[j] == D3DPOOL_SCRATCH)
3949                 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
3950             else
3951                 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
3952                         debug_d3dpool(pools[j]), sizes[i], hr);
3953             if (FAILED(hr))
3954                 continue;
3955
3956             hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
3957             ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3958             ok(!((DWORD_PTR)data & (align - 1)),
3959                     "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
3960                     data, align, sizes[i], debug_d3dpool(pools[j]));
3961             hr = IDirect3DVertexBuffer9_Unlock(buffer);
3962             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3963             IDirect3DVertexBuffer9_Release(buffer);
3964         }
3965     }
3966
3967     refcount = IDirect3DDevice9_Release(device);
3968     ok(!refcount, "Device has %u references left.\n", refcount);
3969     IDirect3D9_Release(d3d9);
3970     DestroyWindow(window);
3971 }
3972
3973 static void test_query_support(void)
3974 {
3975     static const D3DQUERYTYPE queries[] =
3976     {
3977         D3DQUERYTYPE_VCACHE,
3978         D3DQUERYTYPE_RESOURCEMANAGER,
3979         D3DQUERYTYPE_VERTEXSTATS,
3980         D3DQUERYTYPE_EVENT,
3981         D3DQUERYTYPE_OCCLUSION,
3982         D3DQUERYTYPE_TIMESTAMP,
3983         D3DQUERYTYPE_TIMESTAMPDISJOINT,
3984         D3DQUERYTYPE_TIMESTAMPFREQ,
3985         D3DQUERYTYPE_PIPELINETIMINGS,
3986         D3DQUERYTYPE_INTERFACETIMINGS,
3987         D3DQUERYTYPE_VERTEXTIMINGS,
3988         D3DQUERYTYPE_PIXELTIMINGS,
3989         D3DQUERYTYPE_BANDWIDTHTIMINGS,
3990         D3DQUERYTYPE_CACHEUTILIZATION,
3991     };
3992     IDirect3DQuery9 *query = NULL;
3993     IDirect3DDevice9 *device;
3994     IDirect3D9 *d3d9;
3995     unsigned int i;
3996     ULONG refcount;
3997     BOOL supported;
3998     HWND window;
3999     HRESULT hr;
4000
4001     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4002     {
4003         skip("Failed to create d3d9 object, skipping tests.\n");
4004         return;
4005     }
4006
4007     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4008             0, 0, 640, 480, 0, 0, 0, 0);
4009     if (!(device = create_device(d3d9, window, window, TRUE)))
4010     {
4011         skip("Failed to create a D3D device, skipping tests.\n");
4012         IDirect3D9_Release(d3d9);
4013         DestroyWindow(window);
4014         return;
4015     }
4016
4017     for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
4018     {
4019         hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
4020         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4021
4022         supported = hr == D3D_OK;
4023
4024         hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
4025         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4026
4027         ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
4028         ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
4029
4030         if (query)
4031         {
4032             IDirect3DQuery9_Release(query);
4033             query = NULL;
4034         }
4035     }
4036
4037     refcount = IDirect3DDevice9_Release(device);
4038     ok(!refcount, "Device has %u references left.\n", refcount);
4039     IDirect3D9_Release(d3d9);
4040     DestroyWindow(window);
4041 }
4042
4043 static void test_occlusion_query_states(void)
4044 {
4045     static const float point[3] = {0.0, 0.0, 0.0};
4046     IDirect3DQuery9 *query = NULL;
4047     unsigned int data_size, i;
4048     IDirect3DDevice9 *device;
4049     IDirect3D9 *d3d9;
4050     ULONG refcount;
4051     HWND window;
4052     HRESULT hr;
4053     BYTE *data;
4054
4055     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4056     {
4057         skip("Failed to create d3d9 object, skipping tests.\n");
4058         return;
4059     }
4060
4061     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4062             0, 0, 640, 480, 0, 0, 0, 0);
4063     if (!(device = create_device(d3d9, window, window, TRUE)))
4064     {
4065         skip("Failed to create a D3D device, skipping tests.\n");
4066         IDirect3D9_Release(d3d9);
4067         DestroyWindow(window);
4068         return;
4069     }
4070
4071     hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
4072     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
4073     if (!query)
4074     {
4075         skip("Occlusion queries are not supported, skipping tests.\n");
4076         IDirect3DDevice9_Release(device);
4077         IDirect3D9_Release(d3d9);
4078         DestroyWindow(window);
4079         return;
4080     }
4081
4082     data_size = IDirect3DQuery9_GetDataSize(query);
4083     data = HeapAlloc(GetProcessHeap(), 0, data_size);
4084
4085     hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4086     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4087     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4088     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4089
4090     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
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     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4095     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4096
4097     *((DWORD *)data) = 0x12345678;
4098     hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4099     ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4100     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4101     ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4102     if (hr == D3D_OK)
4103         ok(!*(DWORD *)data, "Got unexpected query result %u.\n", *(DWORD *)data);
4104
4105     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4106     ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
4107     hr = IDirect3DDevice9_BeginScene(device);
4108     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4109     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
4110     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4111     hr = IDirect3DDevice9_EndScene(device);
4112     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4113
4114     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4115     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4116     for (i = 0; i < 500; ++i)
4117     {
4118         if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4119             break;
4120         Sleep(10);
4121     }
4122     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4123
4124     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4125     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4126     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4127     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4128
4129     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
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     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4134     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4135
4136     HeapFree(GetProcessHeap(), 0, data);
4137     IDirect3DQuery9_Release(query);
4138     refcount = IDirect3DDevice9_Release(device);
4139     ok(!refcount, "Device has %u references left.\n", refcount);
4140     IDirect3D9_Release(d3d9);
4141     DestroyWindow(window);
4142 }
4143
4144 static void test_get_set_vertex_shader(void)
4145 {
4146     IDirect3DVertexShader9 *current_shader = NULL;
4147     IDirect3DVertexShader9 *shader = NULL;
4148     IDirect3DDevice9 *device;
4149     ULONG refcount, i;
4150     IDirect3D9 *d3d;
4151     D3DCAPS9 caps;
4152     HWND window;
4153     HRESULT hr;
4154
4155     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4156     {
4157         skip("Failed to create D3D object, skipping tests.\n");
4158         return;
4159     }
4160
4161     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4162             0, 0, 640, 480, 0, 0, 0, 0);
4163     if (!(device = create_device(d3d, window, window, TRUE)))
4164     {
4165         skip("Failed to create a D3D device, skipping tests.\n");
4166         IDirect3D9_Release(d3d);
4167         DestroyWindow(window);
4168         return;
4169     }
4170
4171     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4172     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4173     if (!(caps.VertexShaderVersion & 0xffff))
4174     {
4175         skip("No vertex shader support, skipping tests.\n");
4176         IDirect3DDevice9_Release(device);
4177         IDirect3D9_Release(d3d);
4178         DestroyWindow(window);
4179         return;
4180     }
4181
4182     hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
4183     ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4184     ok(!!shader, "Got unexpected shader %p.\n", shader);
4185
4186     /* SetVertexShader() should not touch the shader's refcount. */
4187     i = get_refcount((IUnknown *)shader);
4188     hr = IDirect3DDevice9_SetVertexShader(device, shader);
4189     refcount = get_refcount((IUnknown *)shader);
4190     ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
4191     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4192
4193     /* GetVertexShader() should increase the shader's refcount by one. */
4194     i = refcount + 1;
4195     hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
4196     refcount = get_refcount((IUnknown *)shader);
4197     ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
4198     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4199     ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4200     IDirect3DVertexShader9_Release(current_shader);
4201
4202     IDirect3DVertexShader9_Release(shader);
4203     refcount = IDirect3DDevice9_Release(device);
4204     ok(!refcount, "Device has %u references left.\n", refcount);
4205     IDirect3D9_Release(d3d);
4206     DestroyWindow(window);
4207 }
4208
4209 static void test_vertex_shader_constant(void)
4210 {
4211     static const float d[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4212     static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4213     IDirect3DDevice9 *device;
4214     IDirect3D9 *d3d;
4215     ULONG refcount;
4216     D3DCAPS9 caps;
4217     DWORD consts;
4218     HWND window;
4219     HRESULT hr;
4220
4221     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4222     {
4223         skip("Failed to create D3D object, skipping tests.\n");
4224         return;
4225     }
4226
4227     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4228             0, 0, 640, 480, 0, 0, 0, 0);
4229     if (!(device = create_device(d3d, window, window, TRUE)))
4230     {
4231         skip("Failed to create a D3D device, skipping tests.\n");
4232         IDirect3D9_Release(d3d);
4233         DestroyWindow(window);
4234         return;
4235     }
4236
4237     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4238     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4239     if (!(caps.VertexShaderVersion & 0xffff))
4240     {
4241         skip("No vertex shader support, skipping tests.\n");
4242         IDirect3DDevice9_Release(device);
4243         IDirect3D9_Release(d3d);
4244         DestroyWindow(window);
4245         return;
4246     }
4247     consts = caps.MaxVertexShaderConst;
4248
4249     /* A simple check that the stuff works at all. */
4250     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
4251     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4252
4253     /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
4254      * consts from MAX - 1. */
4255     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
4256     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4257     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
4258     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4259     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
4260     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4261     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
4262     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4263
4264     /* Constant -1. */
4265     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
4266     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4267
4268     refcount = IDirect3DDevice9_Release(device);
4269     ok(!refcount, "Device has %u references left.\n", refcount);
4270     IDirect3D9_Release(d3d);
4271     DestroyWindow(window);
4272 }
4273
4274 static void test_get_set_pixel_shader(void)
4275 {
4276     IDirect3DPixelShader9 *current_shader = NULL;
4277     IDirect3DPixelShader9 *shader = NULL;
4278     IDirect3DDevice9 *device;
4279     ULONG refcount, i;
4280     IDirect3D9 *d3d;
4281     D3DCAPS9 caps;
4282     HWND window;
4283     HRESULT hr;
4284
4285     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4286     {
4287         skip("Failed to create D3D object, skipping tests.\n");
4288         return;
4289     }
4290
4291     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4292             0, 0, 640, 480, 0, 0, 0, 0);
4293     if (!(device = create_device(d3d, window, window, TRUE)))
4294     {
4295         skip("Failed to create a D3D device, skipping tests.\n");
4296         IDirect3D9_Release(d3d);
4297         DestroyWindow(window);
4298         return;
4299     }
4300
4301     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4302     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4303     if (!(caps.PixelShaderVersion & 0xffff))
4304     {
4305         skip("No pixel shader support, skipping tests.\n");
4306         IDirect3DDevice9_Release(device);
4307         IDirect3D9_Release(d3d);
4308         DestroyWindow(window);
4309         return;
4310     }
4311
4312     hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
4313     ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4314     ok(!!shader, "Got unexpected shader %p.\n", shader);
4315
4316     /* SetPixelShader() should not touch the shader's refcount. */
4317     i = get_refcount((IUnknown *)shader);
4318     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4319     refcount = get_refcount((IUnknown *)shader);
4320     ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
4321     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4322
4323     /* GetPixelShader() should increase the shader's refcount by one. */
4324     i = refcount + 1;
4325     hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
4326     refcount = get_refcount((IUnknown *)shader);
4327     ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
4328     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4329     ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4330     IDirect3DPixelShader9_Release(current_shader);
4331
4332     IDirect3DPixelShader9_Release(shader);
4333     refcount = IDirect3DDevice9_Release(device);
4334     ok(!refcount, "Device has %u references left.\n", refcount);
4335     IDirect3D9_Release(d3d);
4336     DestroyWindow(window);
4337 }
4338
4339 static void test_pixel_shader_constant(void)
4340 {
4341     static const float d[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4342     static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4343     IDirect3DDevice9 *device;
4344     DWORD consts = 0;
4345     IDirect3D9 *d3d;
4346     ULONG refcount;
4347     D3DCAPS9 caps;
4348     HWND window;
4349     HRESULT hr;
4350
4351     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4352     {
4353         skip("Failed to create D3D object, skipping tests.\n");
4354         return;
4355     }
4356
4357     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4358             0, 0, 640, 480, 0, 0, 0, 0);
4359     if (!(device = create_device(d3d, window, window, TRUE)))
4360     {
4361         skip("Failed to create a D3D device, skipping tests.\n");
4362         IDirect3D9_Release(d3d);
4363         DestroyWindow(window);
4364         return;
4365     }
4366
4367     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4368     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4369     if (!(caps.PixelShaderVersion & 0xffff))
4370     {
4371         skip("No pixel shader support, skipping tests.\n");
4372         IDirect3DDevice9_Release(device);
4373         IDirect3D9_Release(d3d);
4374         DestroyWindow(window);
4375         return;
4376     }
4377
4378     /* A simple check that the stuff works at all. */
4379     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
4380     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4381
4382     /* Is there really no max pixel shader constant value??? Test how far I can go. */
4383     while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
4384     consts = consts - 1;
4385     trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
4386
4387     /* Test corner cases: Write 4 consts from MAX - 1, everything else is
4388      * pointless given the way the constant limit was determined. */
4389     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
4390     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4391
4392     /* Constant -1. */
4393     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
4394     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4395
4396     refcount = IDirect3DDevice9_Release(device);
4397     ok(!refcount, "Device has %u references left.\n", refcount);
4398     IDirect3D9_Release(d3d);
4399     DestroyWindow(window);
4400 }
4401
4402 static void test_wrong_shader(void)
4403 {
4404     static const DWORD vs_3_0[] =
4405     {
4406         0xfffe0300,                             /* vs_3_0               */
4407         0x0200001f, 0x80000000, 0x900f0000,     /* dcl_position v0      */
4408         0x0200001f, 0x80000000, 0xe00f0000,     /* dcl_position o0      */
4409         0x02000001, 0xe00f0000, 0x90e40000,     /* mov o0, v0           */
4410         0x0000ffff,                             /* end                  */
4411     };
4412
4413 #if 0
4414 float4 main(const float4 color : COLOR) : SV_TARGET
4415 {
4416     float4 o;
4417
4418     o = color;
4419
4420     return o;
4421 }
4422 #endif
4423     static const DWORD ps_4_0[] =
4424     {
4425         0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
4426         0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
4427         0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
4428         0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
4429         0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
4430         0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
4431         0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
4432         0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
4433         0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
4434         0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
4435         0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
4436         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4437         0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4438         0x00000000, 0x00000000, 0x00000000,
4439     };
4440
4441     IDirect3DVertexShader9 *vs = NULL;
4442     IDirect3DPixelShader9 *ps = NULL;
4443     IDirect3DDevice9 *device;
4444     IDirect3D9 * d3d;
4445     ULONG refcount;
4446     D3DCAPS9 caps;
4447     HWND window;
4448     HRESULT hr;
4449
4450     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4451     {
4452         skip("Failed to create D3D object, skipping tests.\n");
4453         return;
4454     }
4455
4456     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4457             0, 0, 640, 480, 0, 0, 0, 0);
4458     if (!(device = create_device(d3d, window, window, TRUE)))
4459     {
4460         skip("Failed to create a D3D device, skipping tests.\n");
4461         IDirect3D9_Release(d3d);
4462         DestroyWindow(window);
4463         return;
4464     }
4465
4466     /* These should always fail, regardless of supported shader version. */
4467     hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
4468     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4469     hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
4470     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4471     hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
4472     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4473
4474     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4475     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4476     if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
4477     {
4478         hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
4479         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4480     }
4481     else
4482         skip("This GPU supports SM3, skipping unsupported shader test.\n");
4483
4484     refcount = IDirect3DDevice9_Release(device);
4485     ok(!refcount, "Device has %u references left.\n", refcount);
4486     IDirect3D9_Release(d3d);
4487     DestroyWindow(window);
4488 }
4489
4490 /* Test the default texture stage state values */
4491 static void test_texture_stage_states(void)
4492 {
4493     IDirect3DDevice9 *device;
4494     IDirect3D9 *d3d;
4495     unsigned int i;
4496     ULONG refcount;
4497     D3DCAPS9 caps;
4498     DWORD value;
4499     HWND window;
4500     HRESULT hr;
4501
4502     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4503     {
4504         skip("Failed to create D3D object, skipping tests.\n");
4505         return;
4506     }
4507
4508     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4509             0, 0, 640, 480, 0, 0, 0, 0);
4510     if (!(device = create_device(d3d, window, window, TRUE)))
4511     {
4512         skip("Failed to create a D3D device, skipping tests.\n");
4513         IDirect3D9_Release(d3d);
4514         DestroyWindow(window);
4515         return;
4516     }
4517
4518     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4519     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4520
4521     for (i = 0; i < caps.MaxTextureBlendStages; ++i)
4522     {
4523         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
4524         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4525         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
4526                 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
4527         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
4528         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4529         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
4530         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
4531         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4532         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
4533         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
4534         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4535         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
4536                 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
4537         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
4538         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4539         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
4540         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
4541         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4542         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
4543         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
4544         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4545         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
4546         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
4547         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4548         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
4549         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
4550         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4551         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
4552         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
4553         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4554         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
4555         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
4556         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4557         ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
4558         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
4559         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4560         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
4561         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
4562         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4563         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
4564         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
4565         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4566         ok(value == D3DTTFF_DISABLE,
4567                 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
4568         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
4569         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4570         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
4571         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
4572         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4573         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
4574         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
4575         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4576         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
4577         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
4578         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4579         ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
4580     }
4581
4582     refcount = IDirect3DDevice9_Release(device);
4583     ok(!refcount, "Device has %u references left.\n", refcount);
4584     IDirect3D9_Release(d3d);
4585     DestroyWindow(window);
4586 }
4587
4588 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
4589 {
4590     IDirect3DCubeTexture9 *texture;
4591     IDirect3D9 *d3d;
4592     HRESULT hr;
4593
4594     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
4595     ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
4596     hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4597             D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
4598     IDirect3D9_Release(d3d);
4599     if (FAILED(hr))
4600     {
4601         skip("No cube mipmap generation support, skipping tests.\n");
4602         return;
4603     }
4604
4605     hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4606             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4607     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4608     IDirect3DCubeTexture9_Release(texture);
4609
4610     hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4611             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4612     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4613     IDirect3DCubeTexture9_Release(texture);
4614 }
4615
4616 static void test_cube_texture_levels(IDirect3DDevice9 *device)
4617 {
4618     IDirect3DCubeTexture9 *texture;
4619     IDirect3DSurface9 *surface;
4620     D3DSURFACE_DESC desc;
4621     DWORD levels;
4622     HRESULT hr;
4623
4624     if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
4625             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
4626     {
4627         skip("Failed to create cube texture, skipping tests.\n");
4628         return;
4629     }
4630
4631     levels = IDirect3DCubeTexture9_GetLevelCount(texture);
4632     ok(levels == 7, "Got unexpected levels %u.\n", levels);
4633
4634     hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
4635     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4636     hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
4637     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4638     hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
4639     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4640
4641     hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
4642     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4643     IDirect3DSurface9_Release(surface);
4644     hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
4645     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4646     hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
4647     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4648
4649     IDirect3DCubeTexture9_Release(texture);
4650 }
4651
4652 static void test_cube_textures(void)
4653 {
4654     IDirect3DCubeTexture9 *texture;
4655     IDirect3DDevice9 *device;
4656     IDirect3D9 *d3d;
4657     ULONG refcount;
4658     D3DCAPS9 caps;
4659     HWND window;
4660     HRESULT hr;
4661
4662     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4663     {
4664         skip("Failed to create D3D object, skipping tests.\n");
4665         return;
4666     }
4667
4668     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4669             0, 0, 640, 480, 0, 0, 0, 0);
4670     if (!(device = create_device(d3d, window, window, TRUE)))
4671     {
4672         skip("Failed to create a D3D device, skipping tests.\n");
4673         IDirect3D9_Release(d3d);
4674         DestroyWindow(window);
4675         return;
4676     }
4677
4678     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4679     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4680
4681     if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
4682     {
4683         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4684         ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
4685         IDirect3DCubeTexture9_Release(texture);
4686         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4687         ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
4688         IDirect3DCubeTexture9_Release(texture);
4689         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4690         ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
4691         IDirect3DCubeTexture9_Release(texture);
4692     }
4693     else
4694     {
4695         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4696         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
4697         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4698         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
4699         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4700         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
4701     }
4702     hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
4703     ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
4704     IDirect3DCubeTexture9_Release(texture);
4705
4706     test_cube_texture_mipmap_gen(device);
4707     test_cube_texture_levels(device);
4708
4709     refcount = IDirect3DDevice9_Release(device);
4710     ok(!refcount, "Device has %u references left.\n", refcount);
4711     IDirect3D9_Release(d3d);
4712     DestroyWindow(window);
4713 }
4714
4715 static void test_mipmap_gen(void)
4716 {
4717     D3DTEXTUREFILTERTYPE filter_type;
4718     IDirect3DTexture9 *texture;
4719     IDirect3DSurface9 *surface;
4720     IDirect3DDevice9 *device;
4721     D3DSURFACE_DESC desc;
4722     D3DLOCKED_RECT lr;
4723     IDirect3D9 *d3d;
4724     ULONG refcount;
4725     unsigned int i;
4726     DWORD levels;
4727     HWND window;
4728     HRESULT hr;
4729
4730     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4731     {
4732         skip("Failed to create D3D object, skipping tests.\n");
4733         return;
4734     }
4735
4736     if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4737             D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
4738     {
4739         skip("No mipmap generation support, skipping tests.\n");
4740         IDirect3D9_Release(d3d);
4741         return;
4742     }
4743
4744     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4745             0, 0, 640, 480, 0, 0, 0, 0);
4746     if (!(device = create_device(d3d, window, window, TRUE)))
4747     {
4748         skip("Failed to create a D3D device, skipping tests.\n");
4749         IDirect3D9_Release(d3d);
4750         DestroyWindow(window);
4751         return;
4752     }
4753
4754     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4755             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4756     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4757     IDirect3DTexture9_Release(texture);
4758
4759     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4760             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4761     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4762
4763     filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4764     ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
4765             "Got unexpected filter_type %#x.\n", filter_type);
4766     hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
4767     todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4768     hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
4769     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4770     filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4771     ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
4772     hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
4773     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4774
4775     levels = IDirect3DTexture9_GetLevelCount(texture);
4776     ok(levels == 1, "Got unexpected levels %u.\n", levels);
4777
4778     for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
4779     {
4780         surface = NULL;
4781         hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
4782         ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4783         if (surface)
4784             IDirect3DSurface9_Release(surface);
4785
4786         hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
4787         ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4788
4789         hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
4790         ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4791         if (SUCCEEDED(hr))
4792         {
4793             hr = IDirect3DTexture9_UnlockRect(texture, i);
4794             ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
4795         }
4796     }
4797     IDirect3DTexture9_Release(texture);
4798
4799     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
4800             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4801     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4802     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
4803             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4804     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4805
4806     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
4807             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4808     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4809     levels = IDirect3DTexture9_GetLevelCount(texture);
4810     ok(levels == 1, "Got unexpected levels %u.\n", levels);
4811     IDirect3DTexture9_Release(texture);
4812
4813     refcount = IDirect3DDevice9_Release(device);
4814     ok(!refcount, "Device has %u references left.\n", refcount);
4815     IDirect3D9_Release(d3d);
4816     DestroyWindow(window);
4817 }
4818
4819 static void test_filter(void)
4820 {
4821     static const struct
4822     {
4823         DWORD magfilter, minfilter, mipfilter;
4824         BOOL has_texture;
4825         HRESULT result;
4826     }
4827     tests[] =
4828     {
4829         {D3DTEXF_NONE,   D3DTEXF_NONE,   D3DTEXF_NONE,   FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4830         {D3DTEXF_POINT,  D3DTEXF_NONE,   D3DTEXF_NONE,   FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4831         {D3DTEXF_NONE,   D3DTEXF_POINT,  D3DTEXF_NONE,   FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4832         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_NONE,   FALSE, D3D_OK                         },
4833         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_POINT,  FALSE, D3D_OK                         },
4834
4835         {D3DTEXF_NONE,   D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4836         {D3DTEXF_POINT,  D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4837         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_NONE,   TRUE,  D3D_OK                         },
4838         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_POINT,  TRUE,  D3D_OK                         },
4839
4840         {D3DTEXF_NONE,   D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4841         {D3DTEXF_LINEAR, D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4842         {D3DTEXF_LINEAR, D3DTEXF_POINT,  D3DTEXF_NONE,   TRUE,  E_FAIL                         },
4843         {D3DTEXF_POINT,  D3DTEXF_LINEAR, D3DTEXF_NONE,   TRUE,  E_FAIL                         },
4844         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_LINEAR, TRUE,  E_FAIL                         },
4845     };
4846     IDirect3DTexture9 *texture;
4847     IDirect3DDevice9 *device;
4848     IDirect3D9 *d3d;
4849     unsigned int i;
4850     ULONG refcount;
4851     DWORD passes;
4852     HWND window;
4853     HRESULT hr;
4854
4855     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4856     {
4857         skip("Failed to create D3D object, skipping tests.\n");
4858         return;
4859     }
4860
4861     if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4862             0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4863     {
4864         skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
4865         IDirect3D9_Release(d3d);
4866         return;
4867     }
4868
4869     if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4870             D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4871     {
4872         skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
4873         IDirect3D9_Release(d3d);
4874         return;
4875     }
4876
4877     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4878             0, 0, 640, 480, 0, 0, 0, 0);
4879     if (!(device = create_device(d3d, window, window, TRUE)))
4880     {
4881         skip("Failed to create a D3D device, skipping tests.\n");
4882         IDirect3D9_Release(d3d);
4883         DestroyWindow(window);
4884         return;
4885     }
4886
4887     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
4888             D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
4889     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4890
4891     /* Needed for ValidateDevice(). */
4892     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4893     ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
4894
4895     for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
4896     {
4897         if (tests[i].has_texture)
4898         {
4899             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
4900             ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4901         }
4902         else
4903         {
4904             hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4905             ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4906         }
4907
4908         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
4909         ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4910         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
4911         ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4912         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
4913         ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4914
4915         passes = 0xdeadbeef;
4916         hr = IDirect3DDevice9_ValidateDevice(device, &passes);
4917         ok(hr == tests[i].result,
4918                 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
4919                 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
4920                 tests[i].mipfilter, tests[i].has_texture);
4921         if (SUCCEEDED(hr))
4922             ok(!!passes, "Got unexpected passes %#x.\n", passes);
4923         else
4924             ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
4925     }
4926
4927     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4928     ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4929     IDirect3DTexture9_Release(texture);
4930
4931     refcount = IDirect3DDevice9_Release(device);
4932     ok(!refcount, "Device has %u references left.\n", refcount);
4933     IDirect3D9_Release(d3d);
4934     DestroyWindow(window);
4935 }
4936
4937 static void test_get_texture(void)
4938 {
4939     IDirect3DBaseTexture9 *texture;
4940     IDirect3DDevice9 *device;
4941     IDirect3D9 *d3d;
4942     ULONG refcount;
4943     HWND window;
4944     HRESULT hr;
4945
4946     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4947     {
4948         skip("Failed to create D3D object, skipping tests.\n");
4949         return;
4950     }
4951
4952     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4953             0, 0, 640, 480, 0, 0, 0, 0);
4954     if (!(device = create_device(d3d, window, window, TRUE)))
4955     {
4956         skip("Failed to create a D3D device, skipping tests.\n");
4957         IDirect3D9_Release(d3d);
4958         DestroyWindow(window);
4959         return;
4960     }
4961
4962     texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
4963     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4964     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4965     hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
4966     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4967     ok(!texture, "Got unexpected texture %p.\n", texture);
4968
4969     refcount = IDirect3DDevice9_Release(device);
4970     ok(!refcount, "Device has %u references left.\n", refcount);
4971     IDirect3D9_Release(d3d);
4972     DestroyWindow(window);
4973 }
4974
4975 static void test_lod(void)
4976 {
4977     IDirect3DTexture9 *texture;
4978     IDirect3DDevice9 *device;
4979     IDirect3D9 *d3d;
4980     ULONG refcount;
4981     HWND window;
4982     HRESULT hr;
4983     DWORD ret;
4984
4985     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4986     {
4987         skip("Failed to create D3D object, skipping tests.\n");
4988         return;
4989     }
4990
4991     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4992             0, 0, 640, 480, 0, 0, 0, 0);
4993     if (!(device = create_device(d3d, window, window, TRUE)))
4994     {
4995         skip("Failed to create a D3D device, skipping tests.\n");
4996         IDirect3D9_Release(d3d);
4997         DestroyWindow(window);
4998         return;
4999     }
5000
5001     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
5002             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5003     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5004
5005     /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
5006      * return a HRESULT, so it can't return a normal error. Instead, the call
5007      * is simply ignored. */
5008     ret = IDirect3DTexture9_SetLOD(texture, 0);
5009     ok(!ret, "Got unexpected ret %u.\n", ret);
5010     ret = IDirect3DTexture9_SetLOD(texture, 1);
5011     ok(!ret, "Got unexpected ret %u.\n", ret);
5012     ret = IDirect3DTexture9_SetLOD(texture, 2);
5013     ok(!ret, "Got unexpected ret %u.\n", ret);
5014     ret = IDirect3DTexture9_GetLOD(texture);
5015     ok(!ret, "Got unexpected ret %u.\n", ret);
5016
5017     IDirect3DTexture9_Release(texture);
5018     refcount = IDirect3DDevice9_Release(device);
5019     ok(!refcount, "Device has %u references left.\n", refcount);
5020     IDirect3D9_Release(d3d);
5021     DestroyWindow(window);
5022 }
5023
5024 static void test_surface_get_container(void)
5025 {
5026     IDirect3DTexture9 *texture = NULL;
5027     IDirect3DSurface9 *surface = NULL;
5028     IDirect3DDevice9 *device;
5029     IUnknown *container;
5030     IDirect3D9 *d3d;
5031     ULONG refcount;
5032     HWND window;
5033     HRESULT hr;
5034
5035     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5036     {
5037         skip("Failed to create D3D object, skipping tests.\n");
5038         return;
5039     }
5040
5041     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5042             0, 0, 640, 480, 0, 0, 0, 0);
5043     if (!(device = create_device(d3d, window, window, TRUE)))
5044     {
5045         skip("Failed to create a D3D device, skipping tests.\n");
5046         IDirect3D9_Release(d3d);
5047         DestroyWindow(window);
5048         return;
5049     }
5050
5051     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
5052             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5053     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5054     ok(!!texture, "Got unexpected texture %p.\n", texture);
5055
5056     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5057     ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5058     ok(!!surface, "Got unexpected surface %p.\n", surface);
5059
5060     /* These should work... */
5061     container = NULL;
5062     hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
5063     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5064     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5065     IUnknown_Release(container);
5066
5067     container = NULL;
5068     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
5069     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5070     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5071     IUnknown_Release(container);
5072
5073     container = NULL;
5074     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
5075     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5076     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5077     IUnknown_Release(container);
5078
5079     container = NULL;
5080     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
5081     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5082     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5083     IUnknown_Release(container);
5084
5085     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5086     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
5087     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5088     ok(!container, "Got unexpected container %p.\n", container);
5089
5090     IDirect3DSurface9_Release(surface);
5091     IDirect3DTexture9_Release(texture);
5092     refcount = IDirect3DDevice9_Release(device);
5093     ok(!refcount, "Device has %u references left.\n", refcount);
5094     IDirect3D9_Release(d3d);
5095     DestroyWindow(window);
5096 }
5097
5098 static void test_surface_alignment(void)
5099 {
5100     IDirect3DSurface9 *surface;
5101     IDirect3DDevice9 *device;
5102     D3DLOCKED_RECT lr;
5103     unsigned int i, j;
5104     IDirect3D9 *d3d;
5105     ULONG refcount;
5106     HWND window;
5107     HRESULT hr;
5108
5109     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5110     {
5111         skip("Failed to create D3D object, skipping tests.\n");
5112         return;
5113     }
5114
5115     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5116             0, 0, 640, 480, 0, 0, 0, 0);
5117     if (!(device = create_device(d3d, window, window, TRUE)))
5118     {
5119         skip("Failed to create a D3D device, skipping tests.\n");
5120         IDirect3D9_Release(d3d);
5121         DestroyWindow(window);
5122         return;
5123     }
5124
5125     /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
5126     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
5127             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
5128     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5129
5130     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5131     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5132     ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
5133     /* Some applications also depend on the exact pitch, rather than just the
5134      * alignment. */
5135     ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
5136     hr = IDirect3DSurface9_UnlockRect(surface);
5137     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5138     IDirect3DSurface9_Release(surface);
5139
5140     for (i = 0; i < 5; ++i)
5141     {
5142         IDirect3DTexture9 *texture;
5143         unsigned int level_count;
5144         D3DSURFACE_DESC desc;
5145         int expected_pitch;
5146
5147         hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
5148                 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
5149         ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5150         if (FAILED(hr))
5151         {
5152             skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
5153             continue;
5154         }
5155
5156         level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
5157         for (j = 0; j < level_count; ++j)
5158         {
5159             IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
5160             hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
5161             ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
5162             hr = IDirect3DTexture9_UnlockRect(texture, j);
5163             ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
5164
5165             expected_pitch = ((desc.Width + 3) >> 2) << 3;
5166             if (i > 0)
5167                 expected_pitch <<= 1;
5168             ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
5169                     lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
5170         }
5171         IDirect3DTexture9_Release(texture);
5172     }
5173
5174     refcount = IDirect3DDevice9_Release(device);
5175     ok(!refcount, "Device has %u references left.\n", refcount);
5176     IDirect3D9_Release(d3d);
5177     DestroyWindow(window);
5178 }
5179
5180 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
5181  * different from regular formats. This test verifies we return the correct
5182  * memory offsets. */
5183 static void test_lockrect_offset(void)
5184 {
5185     static const struct
5186     {
5187         D3DFORMAT format;
5188         const char *name;
5189         unsigned int block_width;
5190         unsigned int block_height;
5191         unsigned int block_size;
5192     }
5193     dxt_formats[] =
5194     {
5195         {D3DFMT_DXT1,                 "D3DFMT_DXT1", 4, 4, 8},
5196         {D3DFMT_DXT2,                 "D3DFMT_DXT2", 4, 4, 16},
5197         {D3DFMT_DXT3,                 "D3DFMT_DXT3", 4, 4, 16},
5198         {D3DFMT_DXT4,                 "D3DFMT_DXT4", 4, 4, 16},
5199         {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, 16},
5200         {MAKEFOURCC('A','T','I','2'), "ATI2N",       1, 1,  1},
5201     };
5202     unsigned int expected_offset, offset, i;
5203     const RECT rect = {60, 60, 68, 68};
5204     IDirect3DSurface9 *surface;
5205     D3DLOCKED_RECT locked_rect;
5206     IDirect3DDevice9 *device;
5207     int expected_pitch;
5208     IDirect3D9 *d3d;
5209     ULONG refcount;
5210     HWND window;
5211     BYTE *base;
5212     HRESULT hr;
5213
5214     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5215     {
5216         skip("Failed to create D3D object, skipping tests.\n");
5217         return;
5218     }
5219
5220     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5221             0, 0, 640, 480, 0, 0, 0, 0);
5222     if (!(device = create_device(d3d, window, window, TRUE)))
5223     {
5224         skip("Failed to create a D3D device, skipping tests.\n");
5225         IDirect3D9_Release(d3d);
5226         DestroyWindow(window);
5227         return;
5228     }
5229
5230     for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
5231     {
5232         if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5233                 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
5234         {
5235             skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
5236             continue;
5237         }
5238
5239         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5240                 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
5241         ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5242
5243         hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5244         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5245
5246         base = locked_rect.pBits;
5247         expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
5248                 * dxt_formats[i].block_size;
5249         ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
5250                 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
5251
5252         hr = IDirect3DSurface9_UnlockRect(surface);
5253         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5254
5255         hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5256         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5257
5258         offset = (BYTE *)locked_rect.pBits - base;
5259         expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
5260                 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
5261         ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
5262                 offset, dxt_formats[i].name, expected_offset);
5263
5264         hr = IDirect3DSurface9_UnlockRect(surface);
5265         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5266
5267         IDirect3DSurface9_Release(surface);
5268     }
5269
5270     refcount = IDirect3DDevice9_Release(device);
5271     ok(!refcount, "Device has %u references left.\n", refcount);
5272     IDirect3D9_Release(d3d);
5273     DestroyWindow(window);
5274 }
5275
5276 static void test_lockrect_invalid(void)
5277 {
5278     static const struct
5279     {
5280         RECT rect;
5281         HRESULT win7_result;
5282     }
5283     test_data[] =
5284     {
5285         {{60, 60, 68, 68},      D3D_OK},                /* Valid */
5286         {{60, 60, 60, 68},      D3DERR_INVALIDCALL},    /* 0 height */
5287         {{60, 60, 68, 60},      D3DERR_INVALIDCALL},    /* 0 width */
5288         {{68, 60, 60, 68},      D3DERR_INVALIDCALL},    /* left > right */
5289         {{60, 68, 68, 60},      D3DERR_INVALIDCALL},    /* top > bottom */
5290         {{-8, 60,  0, 68},      D3DERR_INVALIDCALL},    /* left < surface */
5291         {{60, -8, 68,  0},      D3DERR_INVALIDCALL},    /* top < surface */
5292         {{-16, 60, -8, 68},     D3DERR_INVALIDCALL},    /* right < surface */
5293         {{60, -16, 68, -8},     D3DERR_INVALIDCALL},    /* bottom < surface */
5294         {{60, 60, 136, 68},     D3DERR_INVALIDCALL},    /* right > surface */
5295         {{60, 60, 68, 136},     D3DERR_INVALIDCALL},    /* bottom > surface */
5296         {{136, 60, 144, 68},    D3DERR_INVALIDCALL},    /* left > surface */
5297         {{60, 136, 68, 144},    D3DERR_INVALIDCALL},    /* top > surface */
5298     };
5299     static const RECT test_rect_2 = {0, 0, 8, 8};
5300     IDirect3DSurface9 *surface = NULL;
5301     D3DLOCKED_RECT locked_rect;
5302     IDirect3DDevice9 *device;
5303     IDirect3D9 *d3d;
5304     unsigned int i;
5305     ULONG refcount;
5306     HWND window;
5307     BYTE *base;
5308     HRESULT hr;
5309
5310     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5311     {
5312         skip("Failed to create D3D object, skipping tests.\n");
5313         return;
5314     }
5315
5316     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5317             0, 0, 640, 480, 0, 0, 0, 0);
5318     if (!(device = create_device(d3d, window, window, TRUE)))
5319     {
5320         skip("Failed to create a D3D device, skipping tests.\n");
5321         IDirect3D9_Release(d3d);
5322         DestroyWindow(window);
5323         return;
5324     }
5325
5326     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5327             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5328     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5329     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5330     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5331     base = locked_rect.pBits;
5332     hr = IDirect3DSurface9_UnlockRect(surface);
5333     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5334
5335     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5336     {
5337         unsigned int offset, expected_offset;
5338         const RECT *rect = &test_data[i].rect;
5339
5340         locked_rect.pBits = (BYTE *)0xdeadbeef;
5341         locked_rect.Pitch = 0xdeadbeef;
5342
5343         hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
5344         /* Windows XP accepts invalid locking rectangles, windows 7 rejects
5345          * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
5346          * one broken. */
5347         ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
5348                 "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
5349                 rect->left, rect->top, rect->right, rect->bottom, hr);
5350         if (FAILED(hr))
5351             continue;
5352
5353         offset = (BYTE *)locked_rect.pBits - base;
5354         expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5355         ok(offset == expected_offset,
5356                 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
5357                 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
5358
5359         hr = IDirect3DSurface9_UnlockRect(surface);
5360         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5361     }
5362
5363     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5364     ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
5365     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5366     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5367     hr = IDirect3DSurface9_UnlockRect(surface);
5368     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5369
5370     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
5371     ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5372             hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
5373     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
5374     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5375             hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
5376     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
5377     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5378             hr, test_rect_2.left, test_rect_2.top, test_rect_2.right, test_rect_2.bottom);
5379     hr = IDirect3DSurface9_UnlockRect(surface);
5380     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5381
5382     IDirect3DSurface9_Release(surface);
5383     refcount = IDirect3DDevice9_Release(device);
5384     ok(!refcount, "Device has %u references left.\n", refcount);
5385     IDirect3D9_Release(d3d);
5386     DestroyWindow(window);
5387 }
5388
5389 static void test_private_data(void)
5390 {
5391     ULONG refcount, expected_refcount;
5392     IDirect3DSurface9 *surface;
5393     IDirect3DDevice9 *device;
5394     IDirect3D9 *d3d;
5395     IUnknown *ptr;
5396     HWND window;
5397     HRESULT hr;
5398     DWORD size;
5399
5400     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5401     {
5402         skip("Failed to create D3D object, skipping tests.\n");
5403         return;
5404     }
5405
5406     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5407             0, 0, 640, 480, 0, 0, 0, 0);
5408     if (!(device = create_device(d3d, window, window, TRUE)))
5409     {
5410         skip("Failed to create a D3D device, skipping tests.\n");
5411         IDirect3D9_Release(d3d);
5412         DestroyWindow(window);
5413         return;
5414     }
5415
5416     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
5417             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5418     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5419
5420     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5421             device, 0, D3DSPD_IUNKNOWN);
5422     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5423     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5424             device, 5, D3DSPD_IUNKNOWN);
5425     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5426     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5427             device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
5428     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5429
5430     refcount = get_refcount((IUnknown *)device);
5431     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5432             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5433     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5434     expected_refcount = refcount + 1;
5435     refcount = get_refcount((IUnknown *)device);
5436     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5437     hr = IDirect3DSurface9_FreePrivateData(surface, &IID_IDirect3DSurface9);
5438     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5439     expected_refcount = refcount - 1;
5440     refcount = get_refcount((IUnknown *)device);
5441     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5442
5443     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5444             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5445     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5446     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5447             surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5448     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5449     refcount = get_refcount((IUnknown *)device);
5450     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5451
5452     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5453             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5454     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5455     size = sizeof(ptr);
5456     hr = IDirect3DSurface9_GetPrivateData(surface, &IID_IDirect3DSurface9, &ptr, &size);
5457     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5458     expected_refcount = refcount + 2;
5459     refcount = get_refcount((IUnknown *)device);
5460     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5461     ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
5462     IUnknown_Release(ptr);
5463
5464     /* Destroying the surface frees the held reference. */
5465     IDirect3DSurface9_Release(surface);
5466     expected_refcount = refcount - 3;
5467     refcount = get_refcount((IUnknown *)device);
5468     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5469
5470     refcount = IDirect3DDevice9_Release(device);
5471     ok(!refcount, "Device has %u references left.\n", refcount);
5472     IDirect3D9_Release(d3d);
5473     DestroyWindow(window);
5474 }
5475
5476 static void test_getdc(void)
5477 {
5478     static const struct
5479     {
5480         const char *name;
5481         D3DFORMAT format;
5482         BOOL getdc_supported;
5483     }
5484     testdata[] =
5485     {
5486         {"D3DFMT_A8R8G8B8",    D3DFMT_A8R8G8B8,    TRUE },
5487         {"D3DFMT_X8R8G8B8",    D3DFMT_X8R8G8B8,    TRUE },
5488         {"D3DFMT_R5G6B5",      D3DFMT_R5G6B5,      TRUE },
5489         {"D3DFMT_X1R5G5B5",    D3DFMT_X1R5G5B5,    TRUE },
5490         {"D3DFMT_A1R5G5B5",    D3DFMT_A1R5G5B5,    TRUE },
5491         {"D3DFMT_R8G8B8",      D3DFMT_R8G8B8,      TRUE },
5492         {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, FALSE}, /* Untested, card on windows didn't support it. */
5493         {"D3DFMT_V8U8",        D3DFMT_V8U8,        FALSE},
5494         {"D3DFMT_Q8W8V8U8",    D3DFMT_Q8W8V8U8,    FALSE},
5495         {"D3DFMT_A8B8G8R8",    D3DFMT_A8B8G8R8,    FALSE},
5496         {"D3DFMT_X8B8G8R8",    D3DFMT_A8B8G8R8,    FALSE},
5497         {"D3DFMT_R3G3B2",      D3DFMT_R3G3B2,      FALSE},
5498         {"D3DFMT_P8",          D3DFMT_P8,          FALSE},
5499         {"D3DFMT_L8",          D3DFMT_L8,          FALSE},
5500         {"D3DFMT_A8L8",        D3DFMT_A8L8,        FALSE},
5501         {"D3DFMT_DXT1",        D3DFMT_DXT1,        FALSE},
5502         {"D3DFMT_DXT2",        D3DFMT_DXT2,        FALSE},
5503         {"D3DFMT_DXT3",        D3DFMT_DXT3,        FALSE},
5504         {"D3DFMT_DXT4",        D3DFMT_DXT4,        FALSE},
5505         {"D3DFMT_DXT5",        D3DFMT_DXT5,        FALSE},
5506     };
5507     IDirect3DTexture9 *texture;
5508     IDirect3DSurface9 *surface;
5509     IDirect3DDevice9 *device;
5510     IDirect3D9 *d3d;
5511     unsigned int i;
5512     ULONG refcount;
5513     HWND window;
5514     HRESULT hr;
5515     HDC dc;
5516
5517     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5518     {
5519         skip("Failed to create D3D object, skipping tests.\n");
5520         return;
5521     }
5522
5523     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5524             0, 0, 640, 480, 0, 0, 0, 0);
5525     if (!(device = create_device(d3d, window, window, TRUE)))
5526     {
5527         skip("Failed to create a D3D device, skipping tests.\n");
5528         IDirect3D9_Release(d3d);
5529         DestroyWindow(window);
5530         return;
5531     }
5532
5533     for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
5534     {
5535         texture = NULL;
5536         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5537                 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
5538         if (FAILED(hr))
5539         {
5540             hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
5541                     testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
5542             if (FAILED(hr))
5543             {
5544                 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
5545                 continue;
5546             }
5547             hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5548             ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5549         }
5550
5551         dc = (void *)0x1234;
5552         hr = IDirect3DSurface9_GetDC(surface, &dc);
5553         if (testdata[i].getdc_supported)
5554             ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5555         else
5556             ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5557
5558         if (SUCCEEDED(hr))
5559         {
5560             hr = IDirect3DSurface9_ReleaseDC(surface, dc);
5561             ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
5562         }
5563         else
5564         {
5565             ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
5566         }
5567
5568         IDirect3DSurface9_Release(surface);
5569         if (texture)
5570             IDirect3DTexture9_Release(texture);
5571     }
5572
5573     refcount = IDirect3DDevice9_Release(device);
5574     ok(!refcount, "Device has %u references left.\n", refcount);
5575     IDirect3D9_Release(d3d);
5576     DestroyWindow(window);
5577 }
5578
5579 static void test_surface_dimensions(void)
5580 {
5581     IDirect3DSurface9 *surface;
5582     IDirect3DDevice9 *device;
5583     IDirect3D9 *d3d;
5584     ULONG refcount;
5585     HWND window;
5586     HRESULT hr;
5587
5588     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5589     {
5590         skip("Failed to create D3D object, skipping tests.\n");
5591         return;
5592     }
5593
5594     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5595             0, 0, 640, 480, 0, 0, 0, 0);
5596     if (!(device = create_device(d3d, window, window, TRUE)))
5597     {
5598         skip("Failed to create a D3D device, skipping tests.\n");
5599         IDirect3D9_Release(d3d);
5600         DestroyWindow(window);
5601         return;
5602     }
5603
5604     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
5605             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5606     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5607     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
5608             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5609     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5610
5611     refcount = IDirect3DDevice9_Release(device);
5612     ok(!refcount, "Device has %u references left.\n", refcount);
5613     IDirect3D9_Release(d3d);
5614     DestroyWindow(window);
5615 }
5616
5617 static void test_surface_format_null(void)
5618 {
5619     static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
5620     IDirect3DTexture9 *texture;
5621     IDirect3DSurface9 *surface;
5622     IDirect3DSurface9 *rt, *ds;
5623     D3DLOCKED_RECT locked_rect;
5624     IDirect3DDevice9 *device;
5625     D3DSURFACE_DESC desc;
5626     IDirect3D9 *d3d;
5627     ULONG refcount;
5628     HWND window;
5629     HRESULT hr;
5630
5631     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5632     {
5633         skip("Failed to create D3D object, skipping tests.\n");
5634         return;
5635     }
5636
5637     hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5638             D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
5639     if (hr != D3D_OK)
5640     {
5641         skip("No D3DFMT_NULL support, skipping test.\n");
5642         IDirect3D9_Release(d3d);
5643         return;
5644     }
5645
5646     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5647             0, 0, 640, 480, 0, 0, 0, 0);
5648     if (!(device = create_device(d3d, window, window, TRUE)))
5649     {
5650         skip("Failed to create a D3D device, skipping tests.\n");
5651         IDirect3D9_Release(d3d);
5652         DestroyWindow(window);
5653         return;
5654     }
5655
5656     hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5657             D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
5658     ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
5659
5660     hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5661             D3DFMT_NULL, D3DFMT_D24S8);
5662     ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
5663
5664     hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
5665             D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5666     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5667
5668     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
5669     ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
5670
5671     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
5672     ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
5673
5674     hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
5675     ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
5676
5677     hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
5678     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5679
5680     hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
5681     ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5682
5683     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
5684     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
5685
5686     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5687     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5688
5689     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
5690     ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5691
5692     IDirect3DSurface9_Release(rt);
5693     IDirect3DSurface9_Release(ds);
5694
5695     hr = IDirect3DSurface9_GetDesc(surface, &desc);
5696     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5697     ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
5698     ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
5699
5700     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5701     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5702     ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
5703     ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
5704
5705     hr = IDirect3DSurface9_UnlockRect(surface);
5706     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5707
5708     IDirect3DSurface9_Release(surface);
5709
5710     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
5711             D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
5712     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5713     IDirect3DTexture9_Release(texture);
5714
5715     refcount = IDirect3DDevice9_Release(device);
5716     ok(!refcount, "Device has %u references left.\n", refcount);
5717     IDirect3D9_Release(d3d);
5718     DestroyWindow(window);
5719 }
5720
5721 static void test_surface_double_unlock(void)
5722 {
5723     static const D3DPOOL pools[] =
5724     {
5725         D3DPOOL_DEFAULT,
5726         D3DPOOL_SCRATCH,
5727         D3DPOOL_SYSTEMMEM,
5728     };
5729     IDirect3DSurface9 *surface;
5730     IDirect3DDevice9 *device;
5731     D3DLOCKED_RECT lr;
5732     IDirect3D9 *d3d;
5733     unsigned int i;
5734     ULONG refcount;
5735     HWND window;
5736     HRESULT hr;
5737
5738     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5739     {
5740         skip("Failed to create D3D object, skipping tests.\n");
5741         return;
5742     }
5743
5744     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5745             0, 0, 640, 480, 0, 0, 0, 0);
5746     if (!(device = create_device(d3d, window, window, TRUE)))
5747     {
5748         skip("Failed to create a D3D device, skipping tests.\n");
5749         IDirect3D9_Release(d3d);
5750         DestroyWindow(window);
5751         return;
5752     }
5753
5754     for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
5755     {
5756         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5757                 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
5758         ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
5759
5760         hr = IDirect3DSurface9_UnlockRect(surface);
5761         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5762         hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5763         ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
5764         hr = IDirect3DSurface9_UnlockRect(surface);
5765         ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
5766         hr = IDirect3DSurface9_UnlockRect(surface);
5767         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5768
5769         IDirect3DSurface9_Release(surface);
5770     }
5771
5772     refcount = IDirect3DDevice9_Release(device);
5773     ok(!refcount, "Device has %u references left.\n", refcount);
5774     IDirect3D9_Release(d3d);
5775     DestroyWindow(window);
5776 }
5777
5778 static void test_surface_lockrect_blocks(void)
5779 {
5780     static const struct
5781     {
5782         D3DFORMAT fmt;
5783         const char *name;
5784         unsigned int block_width;
5785         unsigned int block_height;
5786         BOOL broken;
5787     }
5788     formats[] =
5789     {
5790         {D3DFMT_DXT1,                 "D3DFMT_DXT1", 4, 4, FALSE},
5791         {D3DFMT_DXT2,                 "D3DFMT_DXT2", 4, 4, FALSE},
5792         {D3DFMT_DXT3,                 "D3DFMT_DXT3", 4, 4, FALSE},
5793         {D3DFMT_DXT4,                 "D3DFMT_DXT4", 4, 4, FALSE},
5794         {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, FALSE},
5795         /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
5796          * which doesn't match the format spec. On newer Nvidia cards
5797          * it has the correct 4x4 block size */
5798         {MAKEFOURCC('A','T','I','2'), "ATI2N",       4, 4, TRUE},
5799         {D3DFMT_YUY2,                 "D3DFMT_YUY2", 2, 1, FALSE},
5800         {D3DFMT_UYVY,                 "D3DFMT_UYVY", 2, 1, FALSE},
5801     };
5802     static const struct
5803     {
5804         D3DPOOL pool;
5805         const char *name;
5806         /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
5807          * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
5808         BOOL success;
5809     }
5810     pools[] =
5811     {
5812         {D3DPOOL_DEFAULT,       "D3DPOOL_DEFAULT",  FALSE},
5813         {D3DPOOL_SCRATCH,       "D3DPOOL_SCRATCH",  TRUE},
5814         {D3DPOOL_SYSTEMMEM,     "D3DPOOL_SYSTEMMEM",TRUE},
5815         {D3DPOOL_MANAGED,       "D3DPOOL_MANAGED",  TRUE},
5816     };
5817     IDirect3DTexture9 *texture;
5818     IDirect3DSurface9 *surface;
5819     D3DLOCKED_RECT locked_rect;
5820     IDirect3DDevice9 *device;
5821     unsigned int i, j;
5822     BOOL surface_only;
5823     IDirect3D9 *d3d;
5824     ULONG refcount;
5825     HWND window;
5826     HRESULT hr;
5827     RECT rect;
5828
5829     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5830     {
5831         skip("Failed to create D3D object, skipping tests.\n");
5832         return;
5833     }
5834
5835     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5836             0, 0, 640, 480, 0, 0, 0, 0);
5837     if (!(device = create_device(d3d, window, window, TRUE)))
5838     {
5839         skip("Failed to create a D3D device, skipping tests.\n");
5840         IDirect3D9_Release(d3d);
5841         DestroyWindow(window);
5842         return;
5843     }
5844
5845     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
5846     {
5847         surface_only = FALSE;
5848         if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5849                 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt)))
5850         {
5851             if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5852                     0, D3DRTYPE_SURFACE, formats[i].fmt)))
5853             {
5854                 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
5855                 continue;
5856             }
5857             surface_only = TRUE;
5858         }
5859
5860         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5861         {
5862             switch (pools[j].pool)
5863             {
5864                 case D3DPOOL_SYSTEMMEM:
5865                 case D3DPOOL_MANAGED:
5866                     if (surface_only)
5867                         continue;
5868                     /* Fall through */
5869                 case D3DPOOL_DEFAULT:
5870                     if (surface_only)
5871                     {
5872                         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5873                                 formats[i].fmt, pools[j].pool, &surface, NULL);
5874                         ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5875                     }
5876                     else
5877                     {
5878                         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
5879                                 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
5880                                 formats[i].fmt, pools[j].pool, &texture, NULL);
5881                         ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5882                         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5883                         ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5884                         IDirect3DTexture9_Release(texture);
5885                     }
5886                     break;
5887
5888                 case D3DPOOL_SCRATCH:
5889                     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5890                             formats[i].fmt, pools[j].pool, &surface, NULL);
5891                     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5892                     break;
5893
5894                 default:
5895                     break;
5896             }
5897
5898             if (formats[i].block_width > 1)
5899             {
5900                 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
5901                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5902                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5903                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5904                         SUCCEEDED(hr) ? "succeeded" : "failed",
5905                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5906                 if (SUCCEEDED(hr))
5907                 {
5908                     hr = IDirect3DSurface9_UnlockRect(surface);
5909                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5910                 }
5911
5912                 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
5913                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5914                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5915                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5916                         SUCCEEDED(hr) ? "succeeded" : "failed",
5917                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5918                 if (SUCCEEDED(hr))
5919                 {
5920                     hr = IDirect3DSurface9_UnlockRect(surface);
5921                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5922                 }
5923             }
5924
5925             if (formats[i].block_height > 1)
5926             {
5927                 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
5928                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5929                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5930                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5931                         SUCCEEDED(hr) ? "succeeded" : "failed",
5932                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5933                 if (SUCCEEDED(hr))
5934                 {
5935                     hr = IDirect3DSurface9_UnlockRect(surface);
5936                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5937                 }
5938
5939                 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
5940                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5941                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5942                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5943                         SUCCEEDED(hr) ? "succeeded" : "failed",
5944                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5945                 if (SUCCEEDED(hr))
5946                 {
5947                     hr = IDirect3DSurface9_UnlockRect(surface);
5948                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5949                 }
5950             }
5951
5952             SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
5953             hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5954             ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
5955             hr = IDirect3DSurface9_UnlockRect(surface);
5956             ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5957
5958             IDirect3DSurface9_Release(surface);
5959         }
5960     }
5961
5962     refcount = IDirect3DDevice9_Release(device);
5963     ok(!refcount, "Device has %u references left.\n", refcount);
5964     IDirect3D9_Release(d3d);
5965     DestroyWindow(window);
5966 }
5967
5968 static void test_set_palette(void)
5969 {
5970     IDirect3DDevice9 *device;
5971     IDirect3D9 *d3d9;
5972     UINT refcount;
5973     HWND window;
5974     HRESULT hr;
5975     PALETTEENTRY pal[256];
5976     unsigned int i;
5977     D3DCAPS9 caps;
5978
5979     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
5980     {
5981         skip("Failed to create IDirect3D9 object, skipping tests.\n");
5982         return;
5983     }
5984
5985     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5986             0, 0, 640, 480, 0, 0, 0, 0);
5987     if (!(device = create_device(d3d9, window, window, TRUE)))
5988     {
5989         skip("Failed to create a D3D device, skipping tests.\n");
5990         DestroyWindow(window);
5991         return;
5992     }
5993
5994     for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
5995     {
5996         pal[i].peRed = i;
5997         pal[i].peGreen = i;
5998         pal[i].peBlue = i;
5999         pal[i].peFlags = 0xff;
6000     }
6001     hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6002     ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6003
6004     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6005     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6006     for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6007     {
6008         pal[i].peRed = i;
6009         pal[i].peGreen = i;
6010         pal[i].peBlue = i;
6011         pal[i].peFlags = i;
6012     }
6013     if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
6014     {
6015         hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6016         ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6017     }
6018     else
6019     {
6020         hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6021         ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
6022     }
6023
6024     refcount = IDirect3DDevice9_Release(device);
6025     ok(!refcount, "Device has %u references left.\n", refcount);
6026     IDirect3D9_Release(d3d9);
6027     DestroyWindow(window);
6028 }
6029
6030 static void test_swvp_buffer(void)
6031 {
6032     IDirect3DDevice9 *device;
6033     IDirect3D9 *d3d9;
6034     UINT refcount;
6035     HWND window;
6036     HRESULT hr;
6037     unsigned int i;
6038     IDirect3DVertexBuffer9 *buffer;
6039     static const unsigned int bufsize = 1024;
6040     D3DVERTEXBUFFER_DESC desc;
6041     D3DPRESENT_PARAMETERS present_parameters = {0};
6042     struct
6043     {
6044         float x, y, z;
6045     } *ptr, *ptr2;
6046
6047     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6048     {
6049         skip("Failed to create IDirect3D9 object, skipping tests.\n");
6050         return;
6051     }
6052
6053     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6054             0, 0, 640, 480, 0, 0, 0, 0);
6055
6056     present_parameters.Windowed = TRUE;
6057     present_parameters.hDeviceWindow = window;
6058     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
6059     present_parameters.BackBufferWidth = screen_width;
6060     present_parameters.BackBufferHeight = screen_height;
6061     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
6062     present_parameters.EnableAutoDepthStencil = FALSE;
6063     if (FAILED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
6064             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
6065     {
6066         skip("Failed to create a D3D device, skipping tests.\n");
6067         DestroyWindow(window);
6068         IDirect3D9_Release(d3d9);
6069         return;
6070     }
6071
6072     hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
6073             D3DPOOL_DEFAULT, &buffer, NULL);
6074     ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6075     hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
6076     ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6077     ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
6078     ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
6079             "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
6080
6081     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
6082     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6083     for (i = 0; i < bufsize; i++)
6084     {
6085         ptr[i].x = i * 1.0f;
6086         ptr[i].y = i * 2.0f;
6087         ptr[i].z = i * 3.0f;
6088     }
6089     hr = IDirect3DVertexBuffer9_Unlock(buffer);
6090     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6091
6092     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6093     ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6094     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
6095     ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6096     hr = IDirect3DDevice9_BeginScene(device);
6097     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6098     hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6099     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6100     hr = IDirect3DDevice9_EndScene(device);
6101     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6102
6103     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
6104     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6105     ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
6106     for (i = 0; i < bufsize; i++)
6107     {
6108         if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6109         {
6110             ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
6111                     ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6112             break;
6113         }
6114     }
6115     hr = IDirect3DVertexBuffer9_Unlock(buffer);
6116     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6117
6118     IDirect3DVertexBuffer9_Release(buffer);
6119     refcount = IDirect3DDevice9_Release(device);
6120     ok(!refcount, "Device has %u references left.\n", refcount);
6121     IDirect3D9_Release(d3d9);
6122     DestroyWindow(window);
6123 }
6124
6125 static void test_rtpatch(void)
6126 {
6127     IDirect3DDevice9 *device;
6128     IDirect3D9 *d3d9;
6129     UINT refcount;
6130     HWND window;
6131     HRESULT hr;
6132     IDirect3DVertexBuffer9 *buffer;
6133     IDirect3DVertexDeclaration9 *decl;
6134     static const unsigned int bufsize = 16;
6135     struct
6136     {
6137         float x, y, z;
6138     } *data;
6139     D3DRECTPATCH_INFO patch;
6140     static const float num_segs[] = {1.0f, 1.0f, 1.0f, 1.0f};
6141     UINT handle = 0x1234;
6142     D3DCAPS9 caps;
6143
6144     /* Position input, this generates tesselated positions, but do not generate normals
6145      *  or texture coordinates. The d3d documentation isn't clear on how to do this */
6146     static const D3DVERTEXELEMENT9 decl_elements[] = {
6147         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
6148         D3DDECL_END()
6149     };
6150
6151     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6152     {
6153         skip("Failed to create IDirect3D9 object, skipping tests.\n");
6154         return;
6155     }
6156
6157     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6158             0, 0, 640, 480, 0, 0, 0, 0);
6159     if (!(device = create_device(d3d9, window, window, TRUE)))
6160     {
6161         skip("Failed to create a D3D device, skipping tests.\n");
6162         IDirect3D9_Release(d3d9);
6163         DestroyWindow(window);
6164         return;
6165     }
6166
6167     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6168     ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6169     if (caps.DevCaps & D3DDEVCAPS_RTPATCHES)
6170     {
6171         /* The draw methods return the same values, but the patch handle support
6172          * is different on the refrast, which is the only d3d implementation
6173          * known to support tri/rect patches */
6174         skip("Device supports patches, skipping unsupported patch test\n");
6175         IDirect3DDevice9_Release(device);
6176         IDirect3D9_Release(d3d9);
6177         DestroyWindow(window);
6178         return;
6179     }
6180
6181     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
6182     ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
6183     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
6184     ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
6185
6186     hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*data), D3DUSAGE_RTPATCHES, 0,
6187             D3DPOOL_MANAGED, &buffer, NULL);
6188     ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6189     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, (void **)&data, 0);
6190     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6191     memset(data, 0, bufsize * sizeof(*data));
6192     hr = IDirect3DVertexBuffer9_Unlock(buffer);
6193     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6194
6195     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*data));
6196     ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6197     hr = IDirect3DDevice9_BeginScene(device);
6198     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6199
6200     patch.StartVertexOffsetWidth = 0;
6201     patch.StartVertexOffsetHeight = 0;
6202     patch.Width = 4;
6203     patch.Height = 4;
6204     patch.Stride = 4;
6205     patch.Basis = D3DBASIS_BEZIER;
6206     patch.Degree = D3DDEGREE_CUBIC;
6207     hr = IDirect3DDevice9_DrawRectPatch(device, handle, num_segs, NULL);
6208     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
6209     hr = IDirect3DDevice9_DrawRectPatch(device, handle, num_segs, &patch);
6210     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
6211     hr = IDirect3DDevice9_DrawRectPatch(device, handle, num_segs, NULL);
6212     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
6213     hr = IDirect3DDevice9_DrawRectPatch(device, 0, num_segs, NULL);
6214     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
6215
6216     hr = IDirect3DDevice9_EndScene(device);
6217     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6218
6219     hr = IDirect3DDevice9_DrawRectPatch(device, 0, num_segs, &patch);
6220     ok(SUCCEEDED(hr), "Failed to draw rect patch outside scene, hr %#x.\n", hr);
6221
6222     hr = IDirect3DDevice9_DeletePatch(device, handle);
6223     ok(hr == D3DERR_INVALIDCALL, "DeletePatch returned hr %#x.\n", hr);
6224     hr = IDirect3DDevice9_DeletePatch(device, 0);
6225     ok(hr == D3DERR_INVALIDCALL, "DeletePatch returned hr %#x.\n", hr);
6226     hr = IDirect3DDevice9_DeletePatch(device, 0x1235);
6227     ok(hr == D3DERR_INVALIDCALL, "DeletePatch returned hr %#x.\n", hr);
6228
6229     IDirect3DVertexDeclaration9_Release(decl);
6230     IDirect3DVertexBuffer9_Release(buffer);
6231     refcount = IDirect3DDevice9_Release(device);
6232     ok(!refcount, "Device has %u references left.\n", refcount);
6233     IDirect3D9_Release(d3d9);
6234     DestroyWindow(window);
6235 }
6236
6237 START_TEST(device)
6238 {
6239     HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
6240     WNDCLASS wc = {0};
6241
6242     wc.lpfnWndProc = DefWindowProc;
6243     wc.lpszClassName = "d3d9_test_wc";
6244     RegisterClass(&wc);
6245
6246     if (!d3d9_handle)
6247     {
6248         skip("Could not load d3d9.dll\n");
6249         goto out;
6250     }
6251
6252     pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
6253     ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
6254     if (pDirect3DCreate9)
6255     {
6256         IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
6257         if(!d3d9)
6258         {
6259             skip("could not create D3D9 object\n");
6260             goto out;
6261         }
6262         IDirect3D9_Release(d3d9);
6263
6264         screen_width = GetSystemMetrics(SM_CXSCREEN);
6265         screen_height = GetSystemMetrics(SM_CYSCREEN);
6266
6267         test_fpu_setup();
6268         test_multi_device();
6269         test_display_formats();
6270         test_display_modes();
6271         test_swapchain();
6272         test_refcount();
6273         test_mipmap_levels();
6274         test_checkdevicemultisampletype();
6275         test_cursor();
6276         test_cursor_pos();
6277         test_reset_fullscreen();
6278         test_reset();
6279         test_scene();
6280         test_limits();
6281         test_depthstenciltest();
6282         test_get_rt();
6283         test_draw_indexed();
6284         test_null_stream();
6285         test_lights();
6286         test_set_stream_source();
6287         test_scissor_size();
6288         test_wndproc();
6289         test_wndproc_windowed();
6290         test_window_style();
6291         test_mode_change();
6292         test_device_window_reset();
6293         test_reset_resources();
6294         test_set_rt_vp_scissor();
6295         test_volume_get_container();
6296         test_volume_resource();
6297         test_vb_lock_flags();
6298         test_vertex_buffer_alignment();
6299         test_query_support();
6300         test_occlusion_query_states();
6301         test_get_set_vertex_shader();
6302         test_vertex_shader_constant();
6303         test_get_set_pixel_shader();
6304         test_pixel_shader_constant();
6305         test_wrong_shader();
6306         test_texture_stage_states();
6307         test_cube_textures();
6308         test_mipmap_gen();
6309         test_filter();
6310         test_get_texture();
6311         test_lod();
6312         test_surface_get_container();
6313         test_surface_alignment();
6314         test_lockrect_offset();
6315         test_lockrect_invalid();
6316         test_private_data();
6317         test_getdc();
6318         test_surface_dimensions();
6319         test_surface_format_null();
6320         test_surface_double_unlock();
6321         test_surface_lockrect_blocks();
6322         test_set_palette();
6323         test_swvp_buffer();
6324         test_rtpatch();
6325     }
6326
6327 out:
6328     UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));
6329 }