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