Various background processes must be launched detached from current console (if any).
[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_CreateTexture(device, 128, 128, 1, D3DUSAGE_DEPTHSTENCIL,
3527             D3DFMT_D24S8, D3DPOOL_DEFAULT, &texture, NULL);
3528     ok(SUCCEEDED(hr), "Failed to create depth/stencil texture, hr %#x.\n", hr);
3529     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3530     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3531     IDirect3DTexture9_Release(texture);
3532     hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
3533     ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
3534     IDirect3DSurface9_Release(surface);
3535
3536     for (i = 0; i < caps.NumSimultaneousRTs; ++i)
3537     {
3538         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3539                 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
3540         ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
3541         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3542         ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
3543         IDirect3DTexture9_Release(texture);
3544         hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
3545         ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
3546         IDirect3DSurface9_Release(surface);
3547     }
3548
3549     hr = reset_device(device, device_window, TRUE);
3550     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3551
3552     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3553     ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3554     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
3555     ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3556     ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3557     IDirect3DSurface9_Release(surface);
3558     IDirect3DSurface9_Release(rt);
3559
3560     for (i = 1; i < caps.NumSimultaneousRTs; ++i)
3561     {
3562         hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
3563         ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
3564     }
3565
3566     ref = IDirect3DDevice9_Release(device);
3567     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3568
3569 done:
3570     IDirect3D9_Release(d3d9);
3571     DestroyWindow(window);
3572 }
3573
3574 static void test_set_rt_vp_scissor(void)
3575 {
3576     IDirect3DStateBlock9 *stateblock;
3577     IDirect3DDevice9 *device;
3578     IDirect3DSurface9 *rt;
3579     IDirect3D9 *d3d9;
3580     D3DVIEWPORT9 vp;
3581     UINT refcount;
3582     HWND window;
3583     HRESULT hr;
3584     RECT rect;
3585
3586     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3587     {
3588         skip("Failed to create IDirect3D9 object, skipping tests.\n");
3589         return;
3590     }
3591
3592     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3593             0, 0, 640, 480, 0, 0, 0, 0);
3594     if (!(device = create_device(d3d9, window, window, TRUE)))
3595     {
3596         skip("Failed to create a D3D device, skipping tests.\n");
3597         DestroyWindow(window);
3598         return;
3599     }
3600
3601     hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3602             D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
3603     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3604
3605     hr = IDirect3DDevice9_GetViewport(device, &vp);
3606     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3607     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3608     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3609     ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3610     ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3611     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3612     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3613
3614     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3615     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3616     ok(rect.left == 0 && rect.top == 0 && rect.right == screen_width && rect.bottom == screen_height,
3617             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3618             rect.left, rect.top, rect.right, rect.bottom);
3619
3620     hr = IDirect3DDevice9_BeginStateBlock(device);
3621     ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3622
3623     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3624     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3625
3626     hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
3627     ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3628     IDirect3DStateBlock9_Release(stateblock);
3629
3630     hr = IDirect3DDevice9_GetViewport(device, &vp);
3631     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3632     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3633     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3634     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3635     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3636     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3637     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3638
3639     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3640     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3641     ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3642             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3643             rect.left, rect.top, rect.right, rect.bottom);
3644
3645     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3646     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3647
3648     vp.X = 10;
3649     vp.Y = 20;
3650     vp.Width = 30;
3651     vp.Height = 40;
3652     vp.MinZ = 0.25f;
3653     vp.MaxZ = 0.75f;
3654     hr = IDirect3DDevice9_SetViewport(device, &vp);
3655     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3656
3657     SetRect(&rect, 50, 60, 70, 80);
3658     hr = IDirect3DDevice9_SetScissorRect(device, &rect);
3659     ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
3660
3661     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3662     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3663
3664     hr = IDirect3DDevice9_GetViewport(device, &vp);
3665     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3666     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3667     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3668     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3669     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3670     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3671     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3672
3673     hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3674     ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3675     ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3676             "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3677             rect.left, rect.top, rect.right, rect.bottom);
3678
3679     IDirect3DSurface9_Release(rt);
3680     refcount = IDirect3DDevice9_Release(device);
3681     ok(!refcount, "Device has %u references left.\n", refcount);
3682     IDirect3D9_Release(d3d9);
3683     DestroyWindow(window);
3684 }
3685
3686 static void test_volume_get_container(void)
3687 {
3688     IDirect3DVolumeTexture9 *texture = NULL;
3689     IDirect3DVolume9 *volume = NULL;
3690     IDirect3DDevice9 *device;
3691     IUnknown *container;
3692     IDirect3D9 *d3d9;
3693     ULONG refcount;
3694     D3DCAPS9 caps;
3695     HWND window;
3696     HRESULT hr;
3697
3698     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3699     {
3700         skip("Failed to create d3d9 object, skipping tests.\n");
3701         return;
3702     }
3703
3704     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3705             0, 0, 640, 480, 0, 0, 0, 0);
3706     if (!(device = create_device(d3d9, window, window, TRUE)))
3707     {
3708         skip("Failed to create a D3D device, skipping tests.\n");
3709         IDirect3D9_Release(d3d9);
3710         DestroyWindow(window);
3711         return;
3712     }
3713
3714     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3715     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3716     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3717     {
3718         skip("No volume texture support, skipping tests.\n");
3719         IDirect3DDevice9_Release(device);
3720         IDirect3D9_Release(d3d9);
3721         DestroyWindow(window);
3722         return;
3723     }
3724
3725     hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3726             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3727     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3728     ok(!!texture, "Got unexpected texture %p.\n", texture);
3729
3730     hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3731     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3732     ok(!!volume, "Got unexpected volume %p.\n", volume);
3733
3734     /* These should work... */
3735     container = NULL;
3736     hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
3737     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3738     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3739     IUnknown_Release(container);
3740
3741     container = NULL;
3742     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
3743     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3744     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3745     IUnknown_Release(container);
3746
3747     container = NULL;
3748     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
3749     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3750     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3751     IUnknown_Release(container);
3752
3753     container = NULL;
3754     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
3755     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3756     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3757     IUnknown_Release(container);
3758
3759     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3760     hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
3761     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3762     ok(!container, "Got unexpected container %p.\n", container);
3763
3764     IDirect3DVolume9_Release(volume);
3765     IDirect3DVolumeTexture9_Release(texture);
3766     refcount = IDirect3DDevice9_Release(device);
3767     ok(!refcount, "Device has %u references left.\n", refcount);
3768     IDirect3D9_Release(d3d9);
3769     DestroyWindow(window);
3770 }
3771
3772 static void test_volume_resource(void)
3773 {
3774     IDirect3DVolumeTexture9 *texture;
3775     IDirect3DResource9 *resource;
3776     IDirect3DVolume9 *volume;
3777     IDirect3DDevice9 *device;
3778     IDirect3D9 *d3d9;
3779     ULONG refcount;
3780     D3DCAPS9 caps;
3781     HWND window;
3782     HRESULT hr;
3783
3784     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3785     {
3786         skip("Failed to create d3d9 object, skipping tests.\n");
3787         return;
3788     }
3789
3790     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3791             0, 0, 640, 480, 0, 0, 0, 0);
3792     if (!(device = create_device(d3d9, window, window, TRUE)))
3793     {
3794         skip("Failed to create a D3D device, skipping tests.\n");
3795         IDirect3D9_Release(d3d9);
3796         DestroyWindow(window);
3797         return;
3798     }
3799
3800     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3801     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3802     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3803     {
3804         skip("No volume texture support, skipping tests.\n");
3805         IDirect3DDevice9_Release(device);
3806         IDirect3D9_Release(d3d9);
3807         DestroyWindow(window);
3808         return;
3809     }
3810
3811     hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3812             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3813     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3814     hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3815     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3816     IDirect3DVolumeTexture9_Release(texture);
3817
3818     hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
3819     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3820
3821     IDirect3DVolume9_Release(volume);
3822     refcount = IDirect3DDevice9_Release(device);
3823     ok(!refcount, "Device has %u references left.\n", refcount);
3824     IDirect3D9_Release(d3d9);
3825     DestroyWindow(window);
3826 }
3827
3828 static void test_vb_lock_flags(void)
3829 {
3830     static const struct
3831     {
3832         DWORD flags;
3833         const char *debug_string;
3834         HRESULT win7_result;
3835     }
3836     test_data[] =
3837     {
3838         {D3DLOCK_READONLY,                          "D3DLOCK_READONLY",                         D3D_OK            },
3839         {D3DLOCK_DISCARD,                           "D3DLOCK_DISCARD",                          D3D_OK            },
3840         {D3DLOCK_NOOVERWRITE,                       "D3DLOCK_NOOVERWRITE",                      D3D_OK            },
3841         {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD,     "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD",    D3D_OK            },
3842         {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY,    "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY",   D3D_OK            },
3843         {D3DLOCK_READONLY | D3DLOCK_DISCARD,        "D3DLOCK_READONLY | D3DLOCK_DISCARD",       D3DERR_INVALIDCALL},
3844         /* Completely bogus flags aren't an error. */
3845         {0xdeadbeef,                                "0xdeadbeef",                               D3DERR_INVALIDCALL},
3846     };
3847     IDirect3DVertexBuffer9 *buffer;
3848     IDirect3DDevice9 *device;
3849     IDirect3D9 *d3d9;
3850     unsigned int i;
3851     ULONG refcount;
3852     HWND window;
3853     HRESULT hr;
3854     void *data;
3855
3856     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3857     {
3858         skip("Failed to create d3d9 object, skipping tests.\n");
3859         return;
3860     }
3861
3862     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3863             0, 0, 640, 480, 0, 0, 0, 0);
3864     if (!(device = create_device(d3d9, window, window, TRUE)))
3865     {
3866         skip("Failed to create a D3D device, skipping tests.\n");
3867         IDirect3D9_Release(d3d9);
3868         DestroyWindow(window);
3869         return;
3870     }
3871
3872     hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
3873     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3874
3875     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
3876     {
3877         hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
3878         /* Windows XP always returns D3D_OK even with flags that don't make
3879          * sense. Windows 7 returns an error. At least one game (Shaiya)
3880          * depends on the Windows XP result, so mark the Windows 7 behavior as
3881          * broken. */
3882         ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
3883                 hr, test_data[i].debug_string);
3884         if (SUCCEEDED(hr))
3885         {
3886             ok(!!data, "Got unexpected data %p.\n", data);
3887             hr = IDirect3DVertexBuffer9_Unlock(buffer);
3888             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3889         }
3890     }
3891
3892     IDirect3DVertexBuffer9_Release(buffer);
3893     refcount = IDirect3DDevice9_Release(device);
3894     ok(!refcount, "Device has %u references left.\n", refcount);
3895     IDirect3D9_Release(d3d9);
3896     DestroyWindow(window);
3897 }
3898
3899 static const char *debug_d3dpool(D3DPOOL pool)
3900 {
3901     switch (pool)
3902     {
3903         case D3DPOOL_DEFAULT:
3904             return "D3DPOOL_DEFAULT";
3905         case D3DPOOL_SYSTEMMEM:
3906             return "D3DPOOL_SYSTEMMEM";
3907         case D3DPOOL_SCRATCH:
3908             return "D3DPOOL_SCRATCH";
3909         case D3DPOOL_MANAGED:
3910             return "D3DPOOL_MANAGED";
3911         default:
3912             return "unknown pool";
3913     }
3914 }
3915
3916 static void test_vertex_buffer_alignment(void)
3917 {
3918     static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
3919     static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
3920     IDirect3DVertexBuffer9 *buffer = NULL;
3921     const unsigned int align = 16;
3922     IDirect3DDevice9 *device;
3923     unsigned int i, j;
3924     IDirect3D9 *d3d9;
3925     ULONG refcount;
3926     HWND window;
3927     HRESULT hr;
3928     void *data;
3929
3930     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3931     {
3932         skip("Failed to create d3d9 object, skipping tests.\n");
3933         return;
3934     }
3935
3936     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3937             0, 0, 640, 480, 0, 0, 0, 0);
3938     if (!(device = create_device(d3d9, window, window, TRUE)))
3939     {
3940         skip("Failed to create a D3D device, skipping tests.\n");
3941         IDirect3D9_Release(d3d9);
3942         DestroyWindow(window);
3943         return;
3944     }
3945
3946     for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
3947     {
3948         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
3949         {
3950             hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
3951             if (pools[j] == D3DPOOL_SCRATCH)
3952                 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
3953             else
3954                 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
3955                         debug_d3dpool(pools[j]), sizes[i], hr);
3956             if (FAILED(hr))
3957                 continue;
3958
3959             hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
3960             ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3961             ok(!((DWORD_PTR)data & (align - 1)),
3962                     "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
3963                     data, align, sizes[i], debug_d3dpool(pools[j]));
3964             hr = IDirect3DVertexBuffer9_Unlock(buffer);
3965             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3966             IDirect3DVertexBuffer9_Release(buffer);
3967         }
3968     }
3969
3970     refcount = IDirect3DDevice9_Release(device);
3971     ok(!refcount, "Device has %u references left.\n", refcount);
3972     IDirect3D9_Release(d3d9);
3973     DestroyWindow(window);
3974 }
3975
3976 static void test_query_support(void)
3977 {
3978     static const D3DQUERYTYPE queries[] =
3979     {
3980         D3DQUERYTYPE_VCACHE,
3981         D3DQUERYTYPE_RESOURCEMANAGER,
3982         D3DQUERYTYPE_VERTEXSTATS,
3983         D3DQUERYTYPE_EVENT,
3984         D3DQUERYTYPE_OCCLUSION,
3985         D3DQUERYTYPE_TIMESTAMP,
3986         D3DQUERYTYPE_TIMESTAMPDISJOINT,
3987         D3DQUERYTYPE_TIMESTAMPFREQ,
3988         D3DQUERYTYPE_PIPELINETIMINGS,
3989         D3DQUERYTYPE_INTERFACETIMINGS,
3990         D3DQUERYTYPE_VERTEXTIMINGS,
3991         D3DQUERYTYPE_PIXELTIMINGS,
3992         D3DQUERYTYPE_BANDWIDTHTIMINGS,
3993         D3DQUERYTYPE_CACHEUTILIZATION,
3994     };
3995     IDirect3DQuery9 *query = NULL;
3996     IDirect3DDevice9 *device;
3997     IDirect3D9 *d3d9;
3998     unsigned int i;
3999     ULONG refcount;
4000     BOOL supported;
4001     HWND window;
4002     HRESULT hr;
4003
4004     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4005     {
4006         skip("Failed to create d3d9 object, skipping tests.\n");
4007         return;
4008     }
4009
4010     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4011             0, 0, 640, 480, 0, 0, 0, 0);
4012     if (!(device = create_device(d3d9, window, window, TRUE)))
4013     {
4014         skip("Failed to create a D3D device, skipping tests.\n");
4015         IDirect3D9_Release(d3d9);
4016         DestroyWindow(window);
4017         return;
4018     }
4019
4020     for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
4021     {
4022         hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
4023         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4024
4025         supported = hr == D3D_OK;
4026
4027         hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
4028         ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4029
4030         ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
4031         ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
4032
4033         if (query)
4034         {
4035             IDirect3DQuery9_Release(query);
4036             query = NULL;
4037         }
4038     }
4039
4040     refcount = IDirect3DDevice9_Release(device);
4041     ok(!refcount, "Device has %u references left.\n", refcount);
4042     IDirect3D9_Release(d3d9);
4043     DestroyWindow(window);
4044 }
4045
4046 static void test_occlusion_query_states(void)
4047 {
4048     static const float point[3] = {0.0, 0.0, 0.0};
4049     IDirect3DQuery9 *query = NULL;
4050     unsigned int data_size, i;
4051     IDirect3DDevice9 *device;
4052     IDirect3D9 *d3d9;
4053     ULONG refcount;
4054     HWND window;
4055     HRESULT hr;
4056     BYTE *data;
4057
4058     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4059     {
4060         skip("Failed to create d3d9 object, skipping tests.\n");
4061         return;
4062     }
4063
4064     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4065             0, 0, 640, 480, 0, 0, 0, 0);
4066     if (!(device = create_device(d3d9, window, window, TRUE)))
4067     {
4068         skip("Failed to create a D3D device, skipping tests.\n");
4069         IDirect3D9_Release(d3d9);
4070         DestroyWindow(window);
4071         return;
4072     }
4073
4074     hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
4075     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
4076     if (!query)
4077     {
4078         skip("Occlusion queries are not supported, skipping tests.\n");
4079         IDirect3DDevice9_Release(device);
4080         IDirect3D9_Release(d3d9);
4081         DestroyWindow(window);
4082         return;
4083     }
4084
4085     data_size = IDirect3DQuery9_GetDataSize(query);
4086     data = HeapAlloc(GetProcessHeap(), 0, data_size);
4087
4088     hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4089     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4090     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4091     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4092
4093     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4094     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4095     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4096     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4097     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4098     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4099
4100     *((DWORD *)data) = 0x12345678;
4101     hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4102     ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4103     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4104     ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4105     if (hr == D3D_OK)
4106         ok(!*(DWORD *)data, "Got unexpected query result %u.\n", *(DWORD *)data);
4107
4108     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4109     ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
4110     hr = IDirect3DDevice9_BeginScene(device);
4111     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4112     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
4113     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4114     hr = IDirect3DDevice9_EndScene(device);
4115     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4116
4117     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4118     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4119     for (i = 0; i < 500; ++i)
4120     {
4121         if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4122             break;
4123         Sleep(10);
4124     }
4125     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4126
4127     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4128     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4129     hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4130     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4131
4132     hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4133     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4134     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4135     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4136     hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4137     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4138
4139     HeapFree(GetProcessHeap(), 0, data);
4140     IDirect3DQuery9_Release(query);
4141     refcount = IDirect3DDevice9_Release(device);
4142     ok(!refcount, "Device has %u references left.\n", refcount);
4143     IDirect3D9_Release(d3d9);
4144     DestroyWindow(window);
4145 }
4146
4147 static void test_get_set_vertex_shader(void)
4148 {
4149     IDirect3DVertexShader9 *current_shader = NULL;
4150     IDirect3DVertexShader9 *shader = NULL;
4151     IDirect3DDevice9 *device;
4152     ULONG refcount, i;
4153     IDirect3D9 *d3d;
4154     D3DCAPS9 caps;
4155     HWND window;
4156     HRESULT hr;
4157
4158     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4159     {
4160         skip("Failed to create D3D object, skipping tests.\n");
4161         return;
4162     }
4163
4164     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4165             0, 0, 640, 480, 0, 0, 0, 0);
4166     if (!(device = create_device(d3d, window, window, TRUE)))
4167     {
4168         skip("Failed to create a D3D device, skipping tests.\n");
4169         IDirect3D9_Release(d3d);
4170         DestroyWindow(window);
4171         return;
4172     }
4173
4174     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4175     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4176     if (!(caps.VertexShaderVersion & 0xffff))
4177     {
4178         skip("No vertex shader support, skipping tests.\n");
4179         IDirect3DDevice9_Release(device);
4180         IDirect3D9_Release(d3d);
4181         DestroyWindow(window);
4182         return;
4183     }
4184
4185     hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
4186     ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4187     ok(!!shader, "Got unexpected shader %p.\n", shader);
4188
4189     /* SetVertexShader() should not touch the shader's refcount. */
4190     i = get_refcount((IUnknown *)shader);
4191     hr = IDirect3DDevice9_SetVertexShader(device, shader);
4192     refcount = get_refcount((IUnknown *)shader);
4193     ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
4194     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4195
4196     /* GetVertexShader() should increase the shader's refcount by one. */
4197     i = refcount + 1;
4198     hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
4199     refcount = get_refcount((IUnknown *)shader);
4200     ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
4201     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4202     ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4203     IDirect3DVertexShader9_Release(current_shader);
4204
4205     IDirect3DVertexShader9_Release(shader);
4206     refcount = IDirect3DDevice9_Release(device);
4207     ok(!refcount, "Device has %u references left.\n", refcount);
4208     IDirect3D9_Release(d3d);
4209     DestroyWindow(window);
4210 }
4211
4212 static void test_vertex_shader_constant(void)
4213 {
4214     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};
4215     static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4216     IDirect3DDevice9 *device;
4217     IDirect3D9 *d3d;
4218     ULONG refcount;
4219     D3DCAPS9 caps;
4220     DWORD consts;
4221     HWND window;
4222     HRESULT hr;
4223
4224     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4225     {
4226         skip("Failed to create D3D object, skipping tests.\n");
4227         return;
4228     }
4229
4230     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4231             0, 0, 640, 480, 0, 0, 0, 0);
4232     if (!(device = create_device(d3d, window, window, TRUE)))
4233     {
4234         skip("Failed to create a D3D device, skipping tests.\n");
4235         IDirect3D9_Release(d3d);
4236         DestroyWindow(window);
4237         return;
4238     }
4239
4240     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4241     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4242     if (!(caps.VertexShaderVersion & 0xffff))
4243     {
4244         skip("No vertex shader support, skipping tests.\n");
4245         IDirect3DDevice9_Release(device);
4246         IDirect3D9_Release(d3d);
4247         DestroyWindow(window);
4248         return;
4249     }
4250     consts = caps.MaxVertexShaderConst;
4251
4252     /* A simple check that the stuff works at all. */
4253     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
4254     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4255
4256     /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
4257      * consts from MAX - 1. */
4258     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
4259     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4260     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
4261     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4262     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
4263     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4264     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
4265     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4266
4267     /* Constant -1. */
4268     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
4269     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4270
4271     refcount = IDirect3DDevice9_Release(device);
4272     ok(!refcount, "Device has %u references left.\n", refcount);
4273     IDirect3D9_Release(d3d);
4274     DestroyWindow(window);
4275 }
4276
4277 static void test_get_set_pixel_shader(void)
4278 {
4279     IDirect3DPixelShader9 *current_shader = NULL;
4280     IDirect3DPixelShader9 *shader = NULL;
4281     IDirect3DDevice9 *device;
4282     ULONG refcount, i;
4283     IDirect3D9 *d3d;
4284     D3DCAPS9 caps;
4285     HWND window;
4286     HRESULT hr;
4287
4288     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4289     {
4290         skip("Failed to create D3D object, skipping tests.\n");
4291         return;
4292     }
4293
4294     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4295             0, 0, 640, 480, 0, 0, 0, 0);
4296     if (!(device = create_device(d3d, window, window, TRUE)))
4297     {
4298         skip("Failed to create a D3D device, skipping tests.\n");
4299         IDirect3D9_Release(d3d);
4300         DestroyWindow(window);
4301         return;
4302     }
4303
4304     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4305     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4306     if (!(caps.PixelShaderVersion & 0xffff))
4307     {
4308         skip("No pixel shader support, skipping tests.\n");
4309         IDirect3DDevice9_Release(device);
4310         IDirect3D9_Release(d3d);
4311         DestroyWindow(window);
4312         return;
4313     }
4314
4315     hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
4316     ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4317     ok(!!shader, "Got unexpected shader %p.\n", shader);
4318
4319     /* SetPixelShader() should not touch the shader's refcount. */
4320     i = get_refcount((IUnknown *)shader);
4321     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4322     refcount = get_refcount((IUnknown *)shader);
4323     ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
4324     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4325
4326     /* GetPixelShader() should increase the shader's refcount by one. */
4327     i = refcount + 1;
4328     hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
4329     refcount = get_refcount((IUnknown *)shader);
4330     ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
4331     ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4332     ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4333     IDirect3DPixelShader9_Release(current_shader);
4334
4335     IDirect3DPixelShader9_Release(shader);
4336     refcount = IDirect3DDevice9_Release(device);
4337     ok(!refcount, "Device has %u references left.\n", refcount);
4338     IDirect3D9_Release(d3d);
4339     DestroyWindow(window);
4340 }
4341
4342 static void test_pixel_shader_constant(void)
4343 {
4344     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};
4345     static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4346     IDirect3DDevice9 *device;
4347     DWORD consts = 0;
4348     IDirect3D9 *d3d;
4349     ULONG refcount;
4350     D3DCAPS9 caps;
4351     HWND window;
4352     HRESULT hr;
4353
4354     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4355     {
4356         skip("Failed to create D3D object, skipping tests.\n");
4357         return;
4358     }
4359
4360     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4361             0, 0, 640, 480, 0, 0, 0, 0);
4362     if (!(device = create_device(d3d, window, window, TRUE)))
4363     {
4364         skip("Failed to create a D3D device, skipping tests.\n");
4365         IDirect3D9_Release(d3d);
4366         DestroyWindow(window);
4367         return;
4368     }
4369
4370     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4371     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4372     if (!(caps.PixelShaderVersion & 0xffff))
4373     {
4374         skip("No pixel shader support, skipping tests.\n");
4375         IDirect3DDevice9_Release(device);
4376         IDirect3D9_Release(d3d);
4377         DestroyWindow(window);
4378         return;
4379     }
4380
4381     /* A simple check that the stuff works at all. */
4382     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
4383     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4384
4385     /* Is there really no max pixel shader constant value??? Test how far I can go. */
4386     while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
4387     consts = consts - 1;
4388     trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
4389
4390     /* Test corner cases: Write 4 consts from MAX - 1, everything else is
4391      * pointless given the way the constant limit was determined. */
4392     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
4393     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4394
4395     /* Constant -1. */
4396     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
4397     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4398
4399     refcount = IDirect3DDevice9_Release(device);
4400     ok(!refcount, "Device has %u references left.\n", refcount);
4401     IDirect3D9_Release(d3d);
4402     DestroyWindow(window);
4403 }
4404
4405 static void test_wrong_shader(void)
4406 {
4407     static const DWORD vs_3_0[] =
4408     {
4409         0xfffe0300,                             /* vs_3_0               */
4410         0x0200001f, 0x80000000, 0x900f0000,     /* dcl_position v0      */
4411         0x0200001f, 0x80000000, 0xe00f0000,     /* dcl_position o0      */
4412         0x02000001, 0xe00f0000, 0x90e40000,     /* mov o0, v0           */
4413         0x0000ffff,                             /* end                  */
4414     };
4415
4416 #if 0
4417 float4 main(const float4 color : COLOR) : SV_TARGET
4418 {
4419     float4 o;
4420
4421     o = color;
4422
4423     return o;
4424 }
4425 #endif
4426     static const DWORD ps_4_0[] =
4427     {
4428         0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
4429         0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
4430         0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
4431         0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
4432         0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
4433         0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
4434         0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
4435         0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
4436         0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
4437         0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
4438         0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
4439         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4440         0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4441         0x00000000, 0x00000000, 0x00000000,
4442     };
4443
4444     IDirect3DVertexShader9 *vs = NULL;
4445     IDirect3DPixelShader9 *ps = NULL;
4446     IDirect3DDevice9 *device;
4447     IDirect3D9 * d3d;
4448     ULONG refcount;
4449     D3DCAPS9 caps;
4450     HWND window;
4451     HRESULT hr;
4452
4453     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4454     {
4455         skip("Failed to create D3D object, skipping tests.\n");
4456         return;
4457     }
4458
4459     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4460             0, 0, 640, 480, 0, 0, 0, 0);
4461     if (!(device = create_device(d3d, window, window, TRUE)))
4462     {
4463         skip("Failed to create a D3D device, skipping tests.\n");
4464         IDirect3D9_Release(d3d);
4465         DestroyWindow(window);
4466         return;
4467     }
4468
4469     /* These should always fail, regardless of supported shader version. */
4470     hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
4471     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4472     hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
4473     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4474     hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
4475     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4476
4477     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4478     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4479     if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
4480     {
4481         hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
4482         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4483     }
4484     else
4485         skip("This GPU supports SM3, skipping unsupported shader test.\n");
4486
4487     refcount = IDirect3DDevice9_Release(device);
4488     ok(!refcount, "Device has %u references left.\n", refcount);
4489     IDirect3D9_Release(d3d);
4490     DestroyWindow(window);
4491 }
4492
4493 /* Test the default texture stage state values */
4494 static void test_texture_stage_states(void)
4495 {
4496     IDirect3DDevice9 *device;
4497     IDirect3D9 *d3d;
4498     unsigned int i;
4499     ULONG refcount;
4500     D3DCAPS9 caps;
4501     DWORD value;
4502     HWND window;
4503     HRESULT hr;
4504
4505     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4506     {
4507         skip("Failed to create D3D object, skipping tests.\n");
4508         return;
4509     }
4510
4511     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4512             0, 0, 640, 480, 0, 0, 0, 0);
4513     if (!(device = create_device(d3d, window, window, TRUE)))
4514     {
4515         skip("Failed to create a D3D device, skipping tests.\n");
4516         IDirect3D9_Release(d3d);
4517         DestroyWindow(window);
4518         return;
4519     }
4520
4521     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4522     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4523
4524     for (i = 0; i < caps.MaxTextureBlendStages; ++i)
4525     {
4526         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
4527         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4528         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
4529                 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
4530         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
4531         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4532         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
4533         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
4534         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4535         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
4536         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
4537         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4538         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
4539                 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
4540         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
4541         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4542         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
4543         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
4544         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4545         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
4546         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
4547         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4548         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
4549         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
4550         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4551         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
4552         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
4553         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4554         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
4555         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
4556         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4557         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
4558         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
4559         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4560         ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
4561         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
4562         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4563         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
4564         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
4565         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4566         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
4567         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
4568         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4569         ok(value == D3DTTFF_DISABLE,
4570                 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
4571         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &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_COLORARG0, stage %u.\n", value, i);
4574         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &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_ALPHAARG0, stage %u.\n", value, i);
4577         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
4578         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4579         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
4580         hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
4581         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4582         ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
4583     }
4584
4585     refcount = IDirect3DDevice9_Release(device);
4586     ok(!refcount, "Device has %u references left.\n", refcount);
4587     IDirect3D9_Release(d3d);
4588     DestroyWindow(window);
4589 }
4590
4591 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
4592 {
4593     IDirect3DCubeTexture9 *texture;
4594     IDirect3D9 *d3d;
4595     HRESULT hr;
4596
4597     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
4598     ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
4599     hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4600             D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
4601     IDirect3D9_Release(d3d);
4602     if (FAILED(hr))
4603     {
4604         skip("No cube mipmap generation support, skipping tests.\n");
4605         return;
4606     }
4607
4608     hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4609             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4610     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4611     IDirect3DCubeTexture9_Release(texture);
4612
4613     hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4614             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4615     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4616     IDirect3DCubeTexture9_Release(texture);
4617 }
4618
4619 static void test_cube_texture_levels(IDirect3DDevice9 *device)
4620 {
4621     IDirect3DCubeTexture9 *texture;
4622     IDirect3DSurface9 *surface;
4623     D3DSURFACE_DESC desc;
4624     DWORD levels;
4625     HRESULT hr;
4626
4627     if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
4628             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
4629     {
4630         skip("Failed to create cube texture, skipping tests.\n");
4631         return;
4632     }
4633
4634     levels = IDirect3DCubeTexture9_GetLevelCount(texture);
4635     ok(levels == 7, "Got unexpected levels %u.\n", levels);
4636
4637     hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
4638     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4639     hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
4640     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4641     hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
4642     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4643
4644     hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
4645     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4646     IDirect3DSurface9_Release(surface);
4647     hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
4648     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4649     hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
4650     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4651
4652     IDirect3DCubeTexture9_Release(texture);
4653 }
4654
4655 static void test_cube_textures(void)
4656 {
4657     IDirect3DCubeTexture9 *texture;
4658     IDirect3DDevice9 *device;
4659     IDirect3D9 *d3d;
4660     ULONG refcount;
4661     D3DCAPS9 caps;
4662     HWND window;
4663     HRESULT hr;
4664
4665     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4666     {
4667         skip("Failed to create D3D object, skipping tests.\n");
4668         return;
4669     }
4670
4671     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4672             0, 0, 640, 480, 0, 0, 0, 0);
4673     if (!(device = create_device(d3d, window, window, TRUE)))
4674     {
4675         skip("Failed to create a D3D device, skipping tests.\n");
4676         IDirect3D9_Release(d3d);
4677         DestroyWindow(window);
4678         return;
4679     }
4680
4681     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4682     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4683
4684     if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
4685     {
4686         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4687         ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
4688         IDirect3DCubeTexture9_Release(texture);
4689         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4690         ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
4691         IDirect3DCubeTexture9_Release(texture);
4692         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4693         ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
4694         IDirect3DCubeTexture9_Release(texture);
4695     }
4696     else
4697     {
4698         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4699         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
4700         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4701         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
4702         hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4703         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
4704     }
4705     hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
4706     ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
4707     IDirect3DCubeTexture9_Release(texture);
4708
4709     test_cube_texture_mipmap_gen(device);
4710     test_cube_texture_levels(device);
4711
4712     refcount = IDirect3DDevice9_Release(device);
4713     ok(!refcount, "Device has %u references left.\n", refcount);
4714     IDirect3D9_Release(d3d);
4715     DestroyWindow(window);
4716 }
4717
4718 static void test_mipmap_gen(void)
4719 {
4720     D3DTEXTUREFILTERTYPE filter_type;
4721     IDirect3DTexture9 *texture;
4722     IDirect3DSurface9 *surface;
4723     IDirect3DDevice9 *device;
4724     D3DSURFACE_DESC desc;
4725     D3DLOCKED_RECT lr;
4726     IDirect3D9 *d3d;
4727     ULONG refcount;
4728     unsigned int i;
4729     DWORD levels;
4730     HWND window;
4731     HRESULT hr;
4732
4733     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4734     {
4735         skip("Failed to create D3D object, skipping tests.\n");
4736         return;
4737     }
4738
4739     if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4740             D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
4741     {
4742         skip("No mipmap generation support, skipping tests.\n");
4743         IDirect3D9_Release(d3d);
4744         return;
4745     }
4746
4747     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4748             0, 0, 640, 480, 0, 0, 0, 0);
4749     if (!(device = create_device(d3d, window, window, TRUE)))
4750     {
4751         skip("Failed to create a D3D device, skipping tests.\n");
4752         IDirect3D9_Release(d3d);
4753         DestroyWindow(window);
4754         return;
4755     }
4756
4757     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4758             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4759     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4760     IDirect3DTexture9_Release(texture);
4761
4762     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4763             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4764     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4765
4766     filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4767     ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
4768             "Got unexpected filter_type %#x.\n", filter_type);
4769     hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
4770     todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4771     hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
4772     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4773     filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4774     ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
4775     hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
4776     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4777
4778     levels = IDirect3DTexture9_GetLevelCount(texture);
4779     ok(levels == 1, "Got unexpected levels %u.\n", levels);
4780
4781     for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
4782     {
4783         surface = NULL;
4784         hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
4785         ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4786         if (surface)
4787             IDirect3DSurface9_Release(surface);
4788
4789         hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
4790         ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4791
4792         hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
4793         ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4794         if (SUCCEEDED(hr))
4795         {
4796             hr = IDirect3DTexture9_UnlockRect(texture, i);
4797             ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
4798         }
4799     }
4800     IDirect3DTexture9_Release(texture);
4801
4802     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
4803             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4804     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4805     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
4806             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4807     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4808
4809     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
4810             D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4811     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4812     levels = IDirect3DTexture9_GetLevelCount(texture);
4813     ok(levels == 1, "Got unexpected levels %u.\n", levels);
4814     IDirect3DTexture9_Release(texture);
4815
4816     refcount = IDirect3DDevice9_Release(device);
4817     ok(!refcount, "Device has %u references left.\n", refcount);
4818     IDirect3D9_Release(d3d);
4819     DestroyWindow(window);
4820 }
4821
4822 static void test_filter(void)
4823 {
4824     static const struct
4825     {
4826         DWORD magfilter, minfilter, mipfilter;
4827         BOOL has_texture;
4828         HRESULT result;
4829     }
4830     tests[] =
4831     {
4832         {D3DTEXF_NONE,   D3DTEXF_NONE,   D3DTEXF_NONE,   FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4833         {D3DTEXF_POINT,  D3DTEXF_NONE,   D3DTEXF_NONE,   FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4834         {D3DTEXF_NONE,   D3DTEXF_POINT,  D3DTEXF_NONE,   FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4835         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_NONE,   FALSE, D3D_OK                         },
4836         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_POINT,  FALSE, D3D_OK                         },
4837
4838         {D3DTEXF_NONE,   D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4839         {D3DTEXF_POINT,  D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4840         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_NONE,   TRUE,  D3D_OK                         },
4841         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_POINT,  TRUE,  D3D_OK                         },
4842
4843         {D3DTEXF_NONE,   D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4844         {D3DTEXF_LINEAR, D3DTEXF_NONE,   D3DTEXF_NONE,   TRUE,  D3DERR_UNSUPPORTEDTEXTUREFILTER},
4845         {D3DTEXF_LINEAR, D3DTEXF_POINT,  D3DTEXF_NONE,   TRUE,  E_FAIL                         },
4846         {D3DTEXF_POINT,  D3DTEXF_LINEAR, D3DTEXF_NONE,   TRUE,  E_FAIL                         },
4847         {D3DTEXF_POINT,  D3DTEXF_POINT,  D3DTEXF_LINEAR, TRUE,  E_FAIL                         },
4848     };
4849     IDirect3DTexture9 *texture;
4850     IDirect3DDevice9 *device;
4851     IDirect3D9 *d3d;
4852     unsigned int i;
4853     ULONG refcount;
4854     DWORD passes;
4855     HWND window;
4856     HRESULT hr;
4857
4858     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4859     {
4860         skip("Failed to create D3D object, skipping tests.\n");
4861         return;
4862     }
4863
4864     if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4865             0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4866     {
4867         skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
4868         IDirect3D9_Release(d3d);
4869         return;
4870     }
4871
4872     if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4873             D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4874     {
4875         skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
4876         IDirect3D9_Release(d3d);
4877         return;
4878     }
4879
4880     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4881             0, 0, 640, 480, 0, 0, 0, 0);
4882     if (!(device = create_device(d3d, window, window, TRUE)))
4883     {
4884         skip("Failed to create a D3D device, skipping tests.\n");
4885         IDirect3D9_Release(d3d);
4886         DestroyWindow(window);
4887         return;
4888     }
4889
4890     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
4891             D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
4892     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4893
4894     /* Needed for ValidateDevice(). */
4895     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4896     ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
4897
4898     for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
4899     {
4900         if (tests[i].has_texture)
4901         {
4902             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
4903             ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4904         }
4905         else
4906         {
4907             hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4908             ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4909         }
4910
4911         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
4912         ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4913         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
4914         ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4915         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
4916         ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4917
4918         passes = 0xdeadbeef;
4919         hr = IDirect3DDevice9_ValidateDevice(device, &passes);
4920         ok(hr == tests[i].result,
4921                 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
4922                 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
4923                 tests[i].mipfilter, tests[i].has_texture);
4924         if (SUCCEEDED(hr))
4925             ok(!!passes, "Got unexpected passes %#x.\n", passes);
4926         else
4927             ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
4928     }
4929
4930     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4931     ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4932     IDirect3DTexture9_Release(texture);
4933
4934     refcount = IDirect3DDevice9_Release(device);
4935     ok(!refcount, "Device has %u references left.\n", refcount);
4936     IDirect3D9_Release(d3d);
4937     DestroyWindow(window);
4938 }
4939
4940 static void test_get_texture(void)
4941 {
4942     IDirect3DBaseTexture9 *texture;
4943     IDirect3DDevice9 *device;
4944     IDirect3D9 *d3d;
4945     ULONG refcount;
4946     HWND window;
4947     HRESULT hr;
4948
4949     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4950     {
4951         skip("Failed to create D3D object, skipping tests.\n");
4952         return;
4953     }
4954
4955     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4956             0, 0, 640, 480, 0, 0, 0, 0);
4957     if (!(device = create_device(d3d, window, window, TRUE)))
4958     {
4959         skip("Failed to create a D3D device, skipping tests.\n");
4960         IDirect3D9_Release(d3d);
4961         DestroyWindow(window);
4962         return;
4963     }
4964
4965     texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
4966     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4967     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4968     hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
4969     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4970     ok(!texture, "Got unexpected texture %p.\n", texture);
4971
4972     refcount = IDirect3DDevice9_Release(device);
4973     ok(!refcount, "Device has %u references left.\n", refcount);
4974     IDirect3D9_Release(d3d);
4975     DestroyWindow(window);
4976 }
4977
4978 static void test_lod(void)
4979 {
4980     IDirect3DTexture9 *texture;
4981     IDirect3DDevice9 *device;
4982     IDirect3D9 *d3d;
4983     ULONG refcount;
4984     HWND window;
4985     HRESULT hr;
4986     DWORD ret;
4987
4988     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4989     {
4990         skip("Failed to create D3D object, skipping tests.\n");
4991         return;
4992     }
4993
4994     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4995             0, 0, 640, 480, 0, 0, 0, 0);
4996     if (!(device = create_device(d3d, window, window, TRUE)))
4997     {
4998         skip("Failed to create a D3D device, skipping tests.\n");
4999         IDirect3D9_Release(d3d);
5000         DestroyWindow(window);
5001         return;
5002     }
5003
5004     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
5005             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5006     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5007
5008     /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
5009      * return a HRESULT, so it can't return a normal error. Instead, the call
5010      * is simply ignored. */
5011     ret = IDirect3DTexture9_SetLOD(texture, 0);
5012     ok(!ret, "Got unexpected ret %u.\n", ret);
5013     ret = IDirect3DTexture9_SetLOD(texture, 1);
5014     ok(!ret, "Got unexpected ret %u.\n", ret);
5015     ret = IDirect3DTexture9_SetLOD(texture, 2);
5016     ok(!ret, "Got unexpected ret %u.\n", ret);
5017     ret = IDirect3DTexture9_GetLOD(texture);
5018     ok(!ret, "Got unexpected ret %u.\n", ret);
5019
5020     IDirect3DTexture9_Release(texture);
5021     refcount = IDirect3DDevice9_Release(device);
5022     ok(!refcount, "Device has %u references left.\n", refcount);
5023     IDirect3D9_Release(d3d);
5024     DestroyWindow(window);
5025 }
5026
5027 static void test_surface_get_container(void)
5028 {
5029     IDirect3DTexture9 *texture = NULL;
5030     IDirect3DSurface9 *surface = NULL;
5031     IDirect3DDevice9 *device;
5032     IUnknown *container;
5033     IDirect3D9 *d3d;
5034     ULONG refcount;
5035     HWND window;
5036     HRESULT hr;
5037
5038     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5039     {
5040         skip("Failed to create D3D object, skipping tests.\n");
5041         return;
5042     }
5043
5044     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5045             0, 0, 640, 480, 0, 0, 0, 0);
5046     if (!(device = create_device(d3d, window, window, TRUE)))
5047     {
5048         skip("Failed to create a D3D device, skipping tests.\n");
5049         IDirect3D9_Release(d3d);
5050         DestroyWindow(window);
5051         return;
5052     }
5053
5054     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
5055             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5056     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5057     ok(!!texture, "Got unexpected texture %p.\n", texture);
5058
5059     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5060     ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5061     ok(!!surface, "Got unexpected surface %p.\n", surface);
5062
5063     /* These should work... */
5064     container = NULL;
5065     hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
5066     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5067     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5068     IUnknown_Release(container);
5069
5070     container = NULL;
5071     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
5072     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5073     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5074     IUnknown_Release(container);
5075
5076     container = NULL;
5077     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
5078     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5079     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5080     IUnknown_Release(container);
5081
5082     container = NULL;
5083     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
5084     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5085     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5086     IUnknown_Release(container);
5087
5088     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5089     hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
5090     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5091     ok(!container, "Got unexpected container %p.\n", container);
5092
5093     IDirect3DSurface9_Release(surface);
5094     IDirect3DTexture9_Release(texture);
5095     refcount = IDirect3DDevice9_Release(device);
5096     ok(!refcount, "Device has %u references left.\n", refcount);
5097     IDirect3D9_Release(d3d);
5098     DestroyWindow(window);
5099 }
5100
5101 static void test_surface_alignment(void)
5102 {
5103     IDirect3DSurface9 *surface;
5104     IDirect3DDevice9 *device;
5105     D3DLOCKED_RECT lr;
5106     unsigned int i, j;
5107     IDirect3D9 *d3d;
5108     ULONG refcount;
5109     HWND window;
5110     HRESULT hr;
5111
5112     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5113     {
5114         skip("Failed to create D3D object, skipping tests.\n");
5115         return;
5116     }
5117
5118     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5119             0, 0, 640, 480, 0, 0, 0, 0);
5120     if (!(device = create_device(d3d, window, window, TRUE)))
5121     {
5122         skip("Failed to create a D3D device, skipping tests.\n");
5123         IDirect3D9_Release(d3d);
5124         DestroyWindow(window);
5125         return;
5126     }
5127
5128     /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
5129     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
5130             D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
5131     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5132
5133     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5134     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5135     ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
5136     /* Some applications also depend on the exact pitch, rather than just the
5137      * alignment. */
5138     ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
5139     hr = IDirect3DSurface9_UnlockRect(surface);
5140     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5141     IDirect3DSurface9_Release(surface);
5142
5143     for (i = 0; i < 5; ++i)
5144     {
5145         IDirect3DTexture9 *texture;
5146         unsigned int level_count;
5147         D3DSURFACE_DESC desc;
5148         int expected_pitch;
5149
5150         hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
5151                 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
5152         ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5153         if (FAILED(hr))
5154         {
5155             skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
5156             continue;
5157         }
5158
5159         level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
5160         for (j = 0; j < level_count; ++j)
5161         {
5162             IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
5163             hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
5164             ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
5165             hr = IDirect3DTexture9_UnlockRect(texture, j);
5166             ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
5167
5168             expected_pitch = ((desc.Width + 3) >> 2) << 3;
5169             if (i > 0)
5170                 expected_pitch <<= 1;
5171             ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
5172                     lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
5173         }
5174         IDirect3DTexture9_Release(texture);
5175     }
5176
5177     refcount = IDirect3DDevice9_Release(device);
5178     ok(!refcount, "Device has %u references left.\n", refcount);
5179     IDirect3D9_Release(d3d);
5180     DestroyWindow(window);
5181 }
5182
5183 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
5184  * different from regular formats. This test verifies we return the correct
5185  * memory offsets. */
5186 static void test_lockrect_offset(void)
5187 {
5188     static const struct
5189     {
5190         D3DFORMAT format;
5191         const char *name;
5192         unsigned int block_width;
5193         unsigned int block_height;
5194         unsigned int block_size;
5195     }
5196     dxt_formats[] =
5197     {
5198         {D3DFMT_DXT1,                 "D3DFMT_DXT1", 4, 4, 8},
5199         {D3DFMT_DXT2,                 "D3DFMT_DXT2", 4, 4, 16},
5200         {D3DFMT_DXT3,                 "D3DFMT_DXT3", 4, 4, 16},
5201         {D3DFMT_DXT4,                 "D3DFMT_DXT4", 4, 4, 16},
5202         {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, 16},
5203         {MAKEFOURCC('A','T','I','2'), "ATI2N",       1, 1,  1},
5204     };
5205     unsigned int expected_offset, offset, i;
5206     const RECT rect = {60, 60, 68, 68};
5207     IDirect3DSurface9 *surface;
5208     D3DLOCKED_RECT locked_rect;
5209     IDirect3DDevice9 *device;
5210     int expected_pitch;
5211     IDirect3D9 *d3d;
5212     ULONG refcount;
5213     HWND window;
5214     BYTE *base;
5215     HRESULT hr;
5216
5217     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5218     {
5219         skip("Failed to create D3D object, skipping tests.\n");
5220         return;
5221     }
5222
5223     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5224             0, 0, 640, 480, 0, 0, 0, 0);
5225     if (!(device = create_device(d3d, window, window, TRUE)))
5226     {
5227         skip("Failed to create a D3D device, skipping tests.\n");
5228         IDirect3D9_Release(d3d);
5229         DestroyWindow(window);
5230         return;
5231     }
5232
5233     for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
5234     {
5235         if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5236                 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
5237         {
5238             skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
5239             continue;
5240         }
5241
5242         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5243                 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
5244         ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5245
5246         hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5247         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5248
5249         base = locked_rect.pBits;
5250         expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
5251                 * dxt_formats[i].block_size;
5252         ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
5253                 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
5254
5255         hr = IDirect3DSurface9_UnlockRect(surface);
5256         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5257
5258         hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5259         ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5260
5261         offset = (BYTE *)locked_rect.pBits - base;
5262         expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
5263                 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
5264         ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
5265                 offset, dxt_formats[i].name, expected_offset);
5266
5267         hr = IDirect3DSurface9_UnlockRect(surface);
5268         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5269
5270         IDirect3DSurface9_Release(surface);
5271     }
5272
5273     refcount = IDirect3DDevice9_Release(device);
5274     ok(!refcount, "Device has %u references left.\n", refcount);
5275     IDirect3D9_Release(d3d);
5276     DestroyWindow(window);
5277 }
5278
5279 static void test_lockrect_invalid(void)
5280 {
5281     static const struct
5282     {
5283         RECT rect;
5284         HRESULT win7_result;
5285     }
5286     test_data[] =
5287     {
5288         {{60, 60, 68, 68},      D3D_OK},                /* Valid */
5289         {{60, 60, 60, 68},      D3DERR_INVALIDCALL},    /* 0 height */
5290         {{60, 60, 68, 60},      D3DERR_INVALIDCALL},    /* 0 width */
5291         {{68, 60, 60, 68},      D3DERR_INVALIDCALL},    /* left > right */
5292         {{60, 68, 68, 60},      D3DERR_INVALIDCALL},    /* top > bottom */
5293         {{-8, 60,  0, 68},      D3DERR_INVALIDCALL},    /* left < surface */
5294         {{60, -8, 68,  0},      D3DERR_INVALIDCALL},    /* top < surface */
5295         {{-16, 60, -8, 68},     D3DERR_INVALIDCALL},    /* right < surface */
5296         {{60, -16, 68, -8},     D3DERR_INVALIDCALL},    /* bottom < surface */
5297         {{60, 60, 136, 68},     D3DERR_INVALIDCALL},    /* right > surface */
5298         {{60, 60, 68, 136},     D3DERR_INVALIDCALL},    /* bottom > surface */
5299         {{136, 60, 144, 68},    D3DERR_INVALIDCALL},    /* left > surface */
5300         {{60, 136, 68, 144},    D3DERR_INVALIDCALL},    /* top > surface */
5301     };
5302     static const RECT test_rect_2 = {0, 0, 8, 8};
5303     IDirect3DSurface9 *surface = NULL;
5304     D3DLOCKED_RECT locked_rect;
5305     IDirect3DDevice9 *device;
5306     IDirect3D9 *d3d;
5307     unsigned int i;
5308     ULONG refcount;
5309     HWND window;
5310     BYTE *base;
5311     HRESULT hr;
5312
5313     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5314     {
5315         skip("Failed to create D3D object, skipping tests.\n");
5316         return;
5317     }
5318
5319     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5320             0, 0, 640, 480, 0, 0, 0, 0);
5321     if (!(device = create_device(d3d, window, window, TRUE)))
5322     {
5323         skip("Failed to create a D3D device, skipping tests.\n");
5324         IDirect3D9_Release(d3d);
5325         DestroyWindow(window);
5326         return;
5327     }
5328
5329     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5330             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5331     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5332     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5333     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5334     base = locked_rect.pBits;
5335     hr = IDirect3DSurface9_UnlockRect(surface);
5336     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5337
5338     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5339     {
5340         unsigned int offset, expected_offset;
5341         const RECT *rect = &test_data[i].rect;
5342
5343         locked_rect.pBits = (BYTE *)0xdeadbeef;
5344         locked_rect.Pitch = 0xdeadbeef;
5345
5346         hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
5347         /* Windows XP accepts invalid locking rectangles, windows 7 rejects
5348          * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
5349          * one broken. */
5350         ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
5351                 "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
5352                 rect->left, rect->top, rect->right, rect->bottom, hr);
5353         if (FAILED(hr))
5354             continue;
5355
5356         offset = (BYTE *)locked_rect.pBits - base;
5357         expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5358         ok(offset == expected_offset,
5359                 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
5360                 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
5361
5362         hr = IDirect3DSurface9_UnlockRect(surface);
5363         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5364     }
5365
5366     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5367     ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
5368     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5369     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5370     hr = IDirect3DSurface9_UnlockRect(surface);
5371     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5372
5373     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
5374     ok(hr == D3D_OK, "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_data[0].rect, 0);
5377     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5378             hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
5379     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
5380     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5381             hr, test_rect_2.left, test_rect_2.top, test_rect_2.right, test_rect_2.bottom);
5382     hr = IDirect3DSurface9_UnlockRect(surface);
5383     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5384
5385     IDirect3DSurface9_Release(surface);
5386     refcount = IDirect3DDevice9_Release(device);
5387     ok(!refcount, "Device has %u references left.\n", refcount);
5388     IDirect3D9_Release(d3d);
5389     DestroyWindow(window);
5390 }
5391
5392 static void test_private_data(void)
5393 {
5394     ULONG refcount, expected_refcount;
5395     IDirect3DSurface9 *surface;
5396     IDirect3DDevice9 *device;
5397     IDirect3D9 *d3d;
5398     IUnknown *ptr;
5399     HWND window;
5400     HRESULT hr;
5401     DWORD size;
5402
5403     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5404     {
5405         skip("Failed to create D3D object, skipping tests.\n");
5406         return;
5407     }
5408
5409     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5410             0, 0, 640, 480, 0, 0, 0, 0);
5411     if (!(device = create_device(d3d, window, window, TRUE)))
5412     {
5413         skip("Failed to create a D3D device, skipping tests.\n");
5414         IDirect3D9_Release(d3d);
5415         DestroyWindow(window);
5416         return;
5417     }
5418
5419     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
5420             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5421     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5422
5423     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5424             device, 0, 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, 5, D3DSPD_IUNKNOWN);
5428     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5429     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5430             device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
5431     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5432
5433     refcount = get_refcount((IUnknown *)device);
5434     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5435             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5436     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5437     expected_refcount = refcount + 1;
5438     refcount = get_refcount((IUnknown *)device);
5439     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5440     hr = IDirect3DSurface9_FreePrivateData(surface, &IID_IDirect3DSurface9);
5441     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5442     expected_refcount = refcount - 1;
5443     refcount = get_refcount((IUnknown *)device);
5444     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5445
5446     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5447             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5448     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5449     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5450             surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5451     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5452     refcount = get_refcount((IUnknown *)device);
5453     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5454
5455     hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5456             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5457     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5458     size = sizeof(ptr);
5459     hr = IDirect3DSurface9_GetPrivateData(surface, &IID_IDirect3DSurface9, &ptr, &size);
5460     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5461     expected_refcount = refcount + 2;
5462     refcount = get_refcount((IUnknown *)device);
5463     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5464     ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
5465     IUnknown_Release(ptr);
5466
5467     /* Destroying the surface frees the held reference. */
5468     IDirect3DSurface9_Release(surface);
5469     expected_refcount = refcount - 3;
5470     refcount = get_refcount((IUnknown *)device);
5471     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5472
5473     refcount = IDirect3DDevice9_Release(device);
5474     ok(!refcount, "Device has %u references left.\n", refcount);
5475     IDirect3D9_Release(d3d);
5476     DestroyWindow(window);
5477 }
5478
5479 static void test_getdc(void)
5480 {
5481     static const struct
5482     {
5483         const char *name;
5484         D3DFORMAT format;
5485         BOOL getdc_supported;
5486     }
5487     testdata[] =
5488     {
5489         {"D3DFMT_A8R8G8B8",    D3DFMT_A8R8G8B8,    TRUE },
5490         {"D3DFMT_X8R8G8B8",    D3DFMT_X8R8G8B8,    TRUE },
5491         {"D3DFMT_R5G6B5",      D3DFMT_R5G6B5,      TRUE },
5492         {"D3DFMT_X1R5G5B5",    D3DFMT_X1R5G5B5,    TRUE },
5493         {"D3DFMT_A1R5G5B5",    D3DFMT_A1R5G5B5,    TRUE },
5494         {"D3DFMT_R8G8B8",      D3DFMT_R8G8B8,      TRUE },
5495         {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, FALSE}, /* Untested, card on windows didn't support it. */
5496         {"D3DFMT_V8U8",        D3DFMT_V8U8,        FALSE},
5497         {"D3DFMT_Q8W8V8U8",    D3DFMT_Q8W8V8U8,    FALSE},
5498         {"D3DFMT_A8B8G8R8",    D3DFMT_A8B8G8R8,    FALSE},
5499         {"D3DFMT_X8B8G8R8",    D3DFMT_A8B8G8R8,    FALSE},
5500         {"D3DFMT_R3G3B2",      D3DFMT_R3G3B2,      FALSE},
5501         {"D3DFMT_P8",          D3DFMT_P8,          FALSE},
5502         {"D3DFMT_L8",          D3DFMT_L8,          FALSE},
5503         {"D3DFMT_A8L8",        D3DFMT_A8L8,        FALSE},
5504         {"D3DFMT_DXT1",        D3DFMT_DXT1,        FALSE},
5505         {"D3DFMT_DXT2",        D3DFMT_DXT2,        FALSE},
5506         {"D3DFMT_DXT3",        D3DFMT_DXT3,        FALSE},
5507         {"D3DFMT_DXT4",        D3DFMT_DXT4,        FALSE},
5508         {"D3DFMT_DXT5",        D3DFMT_DXT5,        FALSE},
5509     };
5510     IDirect3DTexture9 *texture;
5511     IDirect3DSurface9 *surface;
5512     IDirect3DDevice9 *device;
5513     IDirect3D9 *d3d;
5514     unsigned int i;
5515     ULONG refcount;
5516     HWND window;
5517     HRESULT hr;
5518     HDC dc;
5519
5520     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5521     {
5522         skip("Failed to create D3D object, skipping tests.\n");
5523         return;
5524     }
5525
5526     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5527             0, 0, 640, 480, 0, 0, 0, 0);
5528     if (!(device = create_device(d3d, window, window, TRUE)))
5529     {
5530         skip("Failed to create a D3D device, skipping tests.\n");
5531         IDirect3D9_Release(d3d);
5532         DestroyWindow(window);
5533         return;
5534     }
5535
5536     for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
5537     {
5538         texture = NULL;
5539         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5540                 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
5541         if (FAILED(hr))
5542         {
5543             hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
5544                     testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
5545             if (FAILED(hr))
5546             {
5547                 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
5548                 continue;
5549             }
5550             hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5551             ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5552         }
5553
5554         dc = (void *)0x1234;
5555         hr = IDirect3DSurface9_GetDC(surface, &dc);
5556         if (testdata[i].getdc_supported)
5557             ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5558         else
5559             ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5560
5561         if (SUCCEEDED(hr))
5562         {
5563             hr = IDirect3DSurface9_ReleaseDC(surface, dc);
5564             ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
5565         }
5566         else
5567         {
5568             ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
5569         }
5570
5571         IDirect3DSurface9_Release(surface);
5572         if (texture)
5573             IDirect3DTexture9_Release(texture);
5574     }
5575
5576     refcount = IDirect3DDevice9_Release(device);
5577     ok(!refcount, "Device has %u references left.\n", refcount);
5578     IDirect3D9_Release(d3d);
5579     DestroyWindow(window);
5580 }
5581
5582 static void test_surface_dimensions(void)
5583 {
5584     IDirect3DSurface9 *surface;
5585     IDirect3DDevice9 *device;
5586     IDirect3D9 *d3d;
5587     ULONG refcount;
5588     HWND window;
5589     HRESULT hr;
5590
5591     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5592     {
5593         skip("Failed to create D3D object, skipping tests.\n");
5594         return;
5595     }
5596
5597     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5598             0, 0, 640, 480, 0, 0, 0, 0);
5599     if (!(device = create_device(d3d, window, window, TRUE)))
5600     {
5601         skip("Failed to create a D3D device, skipping tests.\n");
5602         IDirect3D9_Release(d3d);
5603         DestroyWindow(window);
5604         return;
5605     }
5606
5607     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
5608             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5609     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5610     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
5611             D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5612     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5613
5614     refcount = IDirect3DDevice9_Release(device);
5615     ok(!refcount, "Device has %u references left.\n", refcount);
5616     IDirect3D9_Release(d3d);
5617     DestroyWindow(window);
5618 }
5619
5620 static void test_surface_format_null(void)
5621 {
5622     static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
5623     IDirect3DTexture9 *texture;
5624     IDirect3DSurface9 *surface;
5625     IDirect3DSurface9 *rt, *ds;
5626     D3DLOCKED_RECT locked_rect;
5627     IDirect3DDevice9 *device;
5628     D3DSURFACE_DESC desc;
5629     IDirect3D9 *d3d;
5630     ULONG refcount;
5631     HWND window;
5632     HRESULT hr;
5633
5634     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5635     {
5636         skip("Failed to create D3D object, skipping tests.\n");
5637         return;
5638     }
5639
5640     hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5641             D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
5642     if (hr != D3D_OK)
5643     {
5644         skip("No D3DFMT_NULL support, skipping test.\n");
5645         IDirect3D9_Release(d3d);
5646         return;
5647     }
5648
5649     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5650             0, 0, 640, 480, 0, 0, 0, 0);
5651     if (!(device = create_device(d3d, window, window, TRUE)))
5652     {
5653         skip("Failed to create a D3D device, skipping tests.\n");
5654         IDirect3D9_Release(d3d);
5655         DestroyWindow(window);
5656         return;
5657     }
5658
5659     hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5660             D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
5661     ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
5662
5663     hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5664             D3DFMT_NULL, D3DFMT_D24S8);
5665     ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
5666
5667     hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
5668             D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5669     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5670
5671     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
5672     ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
5673
5674     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
5675     ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
5676
5677     hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
5678     ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
5679
5680     hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
5681     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5682
5683     hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
5684     ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5685
5686     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
5687     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
5688
5689     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5690     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5691
5692     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
5693     ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5694
5695     IDirect3DSurface9_Release(rt);
5696     IDirect3DSurface9_Release(ds);
5697
5698     hr = IDirect3DSurface9_GetDesc(surface, &desc);
5699     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5700     ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
5701     ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
5702
5703     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5704     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5705     ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
5706     ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
5707
5708     hr = IDirect3DSurface9_UnlockRect(surface);
5709     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5710
5711     IDirect3DSurface9_Release(surface);
5712
5713     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
5714             D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
5715     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5716     IDirect3DTexture9_Release(texture);
5717
5718     refcount = IDirect3DDevice9_Release(device);
5719     ok(!refcount, "Device has %u references left.\n", refcount);
5720     IDirect3D9_Release(d3d);
5721     DestroyWindow(window);
5722 }
5723
5724 static void test_surface_double_unlock(void)
5725 {
5726     static const D3DPOOL pools[] =
5727     {
5728         D3DPOOL_DEFAULT,
5729         D3DPOOL_SCRATCH,
5730         D3DPOOL_SYSTEMMEM,
5731     };
5732     IDirect3DSurface9 *surface;
5733     IDirect3DDevice9 *device;
5734     D3DLOCKED_RECT lr;
5735     IDirect3D9 *d3d;
5736     unsigned int i;
5737     ULONG refcount;
5738     HWND window;
5739     HRESULT hr;
5740
5741     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5742     {
5743         skip("Failed to create D3D object, skipping tests.\n");
5744         return;
5745     }
5746
5747     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5748             0, 0, 640, 480, 0, 0, 0, 0);
5749     if (!(device = create_device(d3d, window, window, TRUE)))
5750     {
5751         skip("Failed to create a D3D device, skipping tests.\n");
5752         IDirect3D9_Release(d3d);
5753         DestroyWindow(window);
5754         return;
5755     }
5756
5757     for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
5758     {
5759         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5760                 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
5761         ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
5762
5763         hr = IDirect3DSurface9_UnlockRect(surface);
5764         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5765         hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5766         ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
5767         hr = IDirect3DSurface9_UnlockRect(surface);
5768         ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
5769         hr = IDirect3DSurface9_UnlockRect(surface);
5770         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5771
5772         IDirect3DSurface9_Release(surface);
5773     }
5774
5775     refcount = IDirect3DDevice9_Release(device);
5776     ok(!refcount, "Device has %u references left.\n", refcount);
5777     IDirect3D9_Release(d3d);
5778     DestroyWindow(window);
5779 }
5780
5781 static void test_surface_lockrect_blocks(void)
5782 {
5783     static const struct
5784     {
5785         D3DFORMAT fmt;
5786         const char *name;
5787         unsigned int block_width;
5788         unsigned int block_height;
5789         BOOL broken;
5790     }
5791     formats[] =
5792     {
5793         {D3DFMT_DXT1,                 "D3DFMT_DXT1", 4, 4, FALSE},
5794         {D3DFMT_DXT2,                 "D3DFMT_DXT2", 4, 4, FALSE},
5795         {D3DFMT_DXT3,                 "D3DFMT_DXT3", 4, 4, FALSE},
5796         {D3DFMT_DXT4,                 "D3DFMT_DXT4", 4, 4, FALSE},
5797         {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, FALSE},
5798         /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
5799          * which doesn't match the format spec. On newer Nvidia cards
5800          * it has the correct 4x4 block size */
5801         {MAKEFOURCC('A','T','I','2'), "ATI2N",       4, 4, TRUE},
5802         {D3DFMT_YUY2,                 "D3DFMT_YUY2", 2, 1, FALSE},
5803         {D3DFMT_UYVY,                 "D3DFMT_UYVY", 2, 1, FALSE},
5804     };
5805     static const struct
5806     {
5807         D3DPOOL pool;
5808         const char *name;
5809         /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
5810          * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
5811         BOOL success;
5812     }
5813     pools[] =
5814     {
5815         {D3DPOOL_DEFAULT,       "D3DPOOL_DEFAULT",  FALSE},
5816         {D3DPOOL_SCRATCH,       "D3DPOOL_SCRATCH",  TRUE},
5817         {D3DPOOL_SYSTEMMEM,     "D3DPOOL_SYSTEMMEM",TRUE},
5818         {D3DPOOL_MANAGED,       "D3DPOOL_MANAGED",  TRUE},
5819     };
5820     IDirect3DTexture9 *texture;
5821     IDirect3DSurface9 *surface;
5822     D3DLOCKED_RECT locked_rect;
5823     IDirect3DDevice9 *device;
5824     unsigned int i, j;
5825     BOOL surface_only;
5826     IDirect3D9 *d3d;
5827     ULONG refcount;
5828     HWND window;
5829     HRESULT hr;
5830     RECT rect;
5831
5832     if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5833     {
5834         skip("Failed to create D3D object, skipping tests.\n");
5835         return;
5836     }
5837
5838     window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5839             0, 0, 640, 480, 0, 0, 0, 0);
5840     if (!(device = create_device(d3d, window, window, TRUE)))
5841     {
5842         skip("Failed to create a D3D device, skipping tests.\n");
5843         IDirect3D9_Release(d3d);
5844         DestroyWindow(window);
5845         return;
5846     }
5847
5848     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
5849     {
5850         surface_only = FALSE;
5851         if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5852                 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt)))
5853         {
5854             if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5855                     0, D3DRTYPE_SURFACE, formats[i].fmt)))
5856             {
5857                 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
5858                 continue;
5859             }
5860             surface_only = TRUE;
5861         }
5862
5863         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5864         {
5865             switch (pools[j].pool)
5866             {
5867                 case D3DPOOL_SYSTEMMEM:
5868                 case D3DPOOL_MANAGED:
5869                     if (surface_only)
5870                         continue;
5871                     /* Fall through */
5872                 case D3DPOOL_DEFAULT:
5873                     if (surface_only)
5874                     {
5875                         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5876                                 formats[i].fmt, pools[j].pool, &surface, NULL);
5877                         ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5878                     }
5879                     else
5880                     {
5881                         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
5882                                 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
5883                                 formats[i].fmt, pools[j].pool, &texture, NULL);
5884                         ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5885                         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5886                         ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5887                         IDirect3DTexture9_Release(texture);
5888                     }
5889                     break;
5890
5891                 case D3DPOOL_SCRATCH:
5892                     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5893                             formats[i].fmt, pools[j].pool, &surface, NULL);
5894                     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5895                     break;
5896
5897                 default:
5898                     break;
5899             }
5900
5901             if (formats[i].block_width > 1)
5902             {
5903                 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
5904                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5905                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5906                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5907                         SUCCEEDED(hr) ? "succeeded" : "failed",
5908                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5909                 if (SUCCEEDED(hr))
5910                 {
5911                     hr = IDirect3DSurface9_UnlockRect(surface);
5912                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5913                 }
5914
5915                 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
5916                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5917                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5918                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5919                         SUCCEEDED(hr) ? "succeeded" : "failed",
5920                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5921                 if (SUCCEEDED(hr))
5922                 {
5923                     hr = IDirect3DSurface9_UnlockRect(surface);
5924                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5925                 }
5926             }
5927
5928             if (formats[i].block_height > 1)
5929             {
5930                 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
5931                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5932                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5933                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5934                         SUCCEEDED(hr) ? "succeeded" : "failed",
5935                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5936                 if (SUCCEEDED(hr))
5937                 {
5938                     hr = IDirect3DSurface9_UnlockRect(surface);
5939                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5940                 }
5941
5942                 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
5943                 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5944                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5945                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
5946                         SUCCEEDED(hr) ? "succeeded" : "failed",
5947                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5948                 if (SUCCEEDED(hr))
5949                 {
5950                     hr = IDirect3DSurface9_UnlockRect(surface);
5951                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5952                 }
5953             }
5954
5955             SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
5956             hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5957             ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
5958             hr = IDirect3DSurface9_UnlockRect(surface);
5959             ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5960
5961             IDirect3DSurface9_Release(surface);
5962         }
5963     }
5964
5965     refcount = IDirect3DDevice9_Release(device);
5966     ok(!refcount, "Device has %u references left.\n", refcount);
5967     IDirect3D9_Release(d3d);
5968     DestroyWindow(window);
5969 }
5970
5971 static void test_set_palette(void)
5972 {
5973     IDirect3DDevice9 *device;
5974     IDirect3D9 *d3d9;
5975     UINT refcount;
5976     HWND window;
5977     HRESULT hr;
5978     PALETTEENTRY pal[256];
5979     unsigned int i;
5980     D3DCAPS9 caps;
5981
5982     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
5983     {
5984         skip("Failed to create IDirect3D9 object, skipping tests.\n");
5985         return;
5986     }
5987
5988     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5989             0, 0, 640, 480, 0, 0, 0, 0);
5990     if (!(device = create_device(d3d9, window, window, TRUE)))
5991     {
5992         skip("Failed to create a D3D device, skipping tests.\n");
5993         DestroyWindow(window);
5994         return;
5995     }
5996
5997     for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
5998     {
5999         pal[i].peRed = i;
6000         pal[i].peGreen = i;
6001         pal[i].peBlue = i;
6002         pal[i].peFlags = 0xff;
6003     }
6004     hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6005     ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6006
6007     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6008     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6009     for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6010     {
6011         pal[i].peRed = i;
6012         pal[i].peGreen = i;
6013         pal[i].peBlue = i;
6014         pal[i].peFlags = i;
6015     }
6016     if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
6017     {
6018         hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6019         ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6020     }
6021     else
6022     {
6023         hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6024         ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
6025     }
6026
6027     refcount = IDirect3DDevice9_Release(device);
6028     ok(!refcount, "Device has %u references left.\n", refcount);
6029     IDirect3D9_Release(d3d9);
6030     DestroyWindow(window);
6031 }
6032
6033 static void test_swvp_buffer(void)
6034 {
6035     IDirect3DDevice9 *device;
6036     IDirect3D9 *d3d9;
6037     UINT refcount;
6038     HWND window;
6039     HRESULT hr;
6040     unsigned int i;
6041     IDirect3DVertexBuffer9 *buffer;
6042     static const unsigned int bufsize = 1024;
6043     D3DVERTEXBUFFER_DESC desc;
6044     D3DPRESENT_PARAMETERS present_parameters = {0};
6045     struct
6046     {
6047         float x, y, z;
6048     } *ptr, *ptr2;
6049
6050     if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6051     {
6052         skip("Failed to create IDirect3D9 object, skipping tests.\n");
6053         return;
6054     }
6055
6056     window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6057             0, 0, 640, 480, 0, 0, 0, 0);
6058
6059     present_parameters.Windowed = TRUE;
6060     present_parameters.hDeviceWindow = window;
6061     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
6062     present_parameters.BackBufferWidth = screen_width;
6063     present_parameters.BackBufferHeight = screen_height;
6064     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
6065     present_parameters.EnableAutoDepthStencil = FALSE;
6066     if (FAILED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
6067             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
6068     {
6069         skip("Failed to create a D3D device, skipping tests.\n");
6070         DestroyWindow(window);
6071         IDirect3D9_Release(d3d9);
6072         return;
6073     }
6074
6075     hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
6076             D3DPOOL_DEFAULT, &buffer, NULL);
6077     ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6078     hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
6079     ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6080     ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
6081     ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
6082             "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
6083
6084     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
6085     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6086     for (i = 0; i < bufsize; i++)
6087     {
6088         ptr[i].x = i * 1.0f;
6089         ptr[i].y = i * 2.0f;
6090         ptr[i].z = i * 3.0f;
6091     }
6092     hr = IDirect3DVertexBuffer9_Unlock(buffer);
6093     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6094
6095     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6096     ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6097     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
6098     ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6099     hr = IDirect3DDevice9_BeginScene(device);
6100     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6101     hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6102     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6103     hr = IDirect3DDevice9_EndScene(device);
6104     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6105
6106     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
6107     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6108     ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
6109     for (i = 0; i < bufsize; i++)
6110     {
6111         if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6112         {
6113             ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
6114                     ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6115             break;
6116         }
6117     }
6118     hr = IDirect3DVertexBuffer9_Unlock(buffer);
6119     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6120
6121     IDirect3DVertexBuffer9_Release(buffer);
6122     refcount = IDirect3DDevice9_Release(device);
6123     ok(!refcount, "Device has %u references left.\n", refcount);
6124     IDirect3D9_Release(d3d9);
6125     DestroyWindow(window);
6126 }
6127
6128 START_TEST(device)
6129 {
6130     HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
6131     WNDCLASS wc = {0};
6132
6133     wc.lpfnWndProc = DefWindowProc;
6134     wc.lpszClassName = "d3d9_test_wc";
6135     RegisterClass(&wc);
6136
6137     if (!d3d9_handle)
6138     {
6139         skip("Could not load d3d9.dll\n");
6140         goto out;
6141     }
6142
6143     pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
6144     ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
6145     if (pDirect3DCreate9)
6146     {
6147         IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
6148         if(!d3d9)
6149         {
6150             skip("could not create D3D9 object\n");
6151             goto out;
6152         }
6153         IDirect3D9_Release(d3d9);
6154
6155         screen_width = GetSystemMetrics(SM_CXSCREEN);
6156         screen_height = GetSystemMetrics(SM_CYSCREEN);
6157
6158         test_fpu_setup();
6159         test_multi_device();
6160         test_display_formats();
6161         test_display_modes();
6162         test_swapchain();
6163         test_refcount();
6164         test_mipmap_levels();
6165         test_checkdevicemultisampletype();
6166         test_cursor();
6167         test_cursor_pos();
6168         test_reset_fullscreen();
6169         test_reset();
6170         test_scene();
6171         test_limits();
6172         test_depthstenciltest();
6173         test_get_rt();
6174         test_draw_indexed();
6175         test_null_stream();
6176         test_lights();
6177         test_set_stream_source();
6178         test_scissor_size();
6179         test_wndproc();
6180         test_wndproc_windowed();
6181         test_window_style();
6182         test_mode_change();
6183         test_device_window_reset();
6184         test_reset_resources();
6185         test_set_rt_vp_scissor();
6186         test_volume_get_container();
6187         test_volume_resource();
6188         test_vb_lock_flags();
6189         test_vertex_buffer_alignment();
6190         test_query_support();
6191         test_occlusion_query_states();
6192         test_get_set_vertex_shader();
6193         test_vertex_shader_constant();
6194         test_get_set_pixel_shader();
6195         test_pixel_shader_constant();
6196         test_wrong_shader();
6197         test_texture_stage_states();
6198         test_cube_textures();
6199         test_mipmap_gen();
6200         test_filter();
6201         test_get_texture();
6202         test_lod();
6203         test_surface_get_container();
6204         test_surface_alignment();
6205         test_lockrect_offset();
6206         test_lockrect_invalid();
6207         test_private_data();
6208         test_getdc();
6209         test_surface_dimensions();
6210         test_surface_format_null();
6211         test_surface_double_unlock();
6212         test_surface_lockrect_blocks();
6213         test_set_palette();
6214         test_swvp_buffer();
6215     }
6216
6217 out:
6218     UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));
6219 }