mshtml: Properly report history update for location.replace call.
[wine] / dlls / d3d8 / tests / device.c
1 /*
2  * Copyright (C) 2006 Vitaliy Margolen
3  * Copyright (C) 2006 Chris Robinson
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #define COBJMACROS
21 #include <windowsx.h>
22 #include <initguid.h>
23 #include <d3d8.h>
24 #include "wine/test.h"
25
26 static INT screen_width;
27 static INT screen_height;
28
29 static IDirect3D8 *(WINAPI *pDirect3DCreate8)(UINT);
30
31 static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
32
33 static const DWORD simple_vs[] = {0xFFFE0101,       /* vs_1_1               */
34     0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0   */
35     0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1   */
36     0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2   */
37     0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3   */
38     0x0000FFFF};                                    /* END                  */
39 static const DWORD simple_ps[] = {0xFFFF0101,                               /* ps_1_1                       */
40     0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
41     0x00000042, 0xB00F0000,                                                 /* tex t0                       */
42     0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000,                         /* dp3 r0, c1, c0               */
43     0x00000005, 0x800F0000, 0x90E40000, 0x80E40000,                         /* mul r0, v0, r0               */
44     0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000,                         /* mul r0, t0, r0               */
45     0x0000FFFF};                                                            /* END                          */
46
47 static int get_refcount(IUnknown *object)
48 {
49     IUnknown_AddRef( object );
50     return IUnknown_Release( object );
51 }
52
53 /* try to make sure pending X events have been processed before continuing */
54 static void flush_events(void)
55 {
56     MSG msg;
57     int diff = 200;
58     int min_timeout = 100;
59     DWORD time = GetTickCount() + diff;
60
61     while (diff > 0)
62     {
63         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
64         while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
65         diff = time - GetTickCount();
66     }
67 }
68
69 static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND device_window, HWND focus_window, BOOL windowed)
70 {
71     D3DPRESENT_PARAMETERS present_parameters = {0};
72     IDirect3DDevice8 *device;
73
74     present_parameters.Windowed = windowed;
75     present_parameters.hDeviceWindow = device_window;
76     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
77     present_parameters.BackBufferWidth = screen_width;
78     present_parameters.BackBufferHeight = screen_height;
79     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
80     present_parameters.EnableAutoDepthStencil = TRUE;
81     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
82
83     if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
84             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
85
86     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
87     if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
88             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
89
90     if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
91             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
92
93     return NULL;
94 }
95
96 static HRESULT reset_device(IDirect3DDevice8 *device, HWND device_window, BOOL windowed)
97 {
98     D3DPRESENT_PARAMETERS present_parameters = {0};
99
100     present_parameters.Windowed = windowed;
101     present_parameters.hDeviceWindow = device_window;
102     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
103     present_parameters.BackBufferWidth = screen_width;
104     present_parameters.BackBufferHeight = screen_height;
105     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
106     present_parameters.EnableAutoDepthStencil = TRUE;
107     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
108
109     return IDirect3DDevice8_Reset(device, &present_parameters);
110 }
111
112 #define CHECK_CALL(r,c,d,rc) \
113     if (SUCCEEDED(r)) {\
114         int tmp1 = get_refcount( (IUnknown *)d ); \
115         int rc_new = rc; \
116         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
117     } else {\
118         trace("%s failed: %#08x\n", c, r); \
119     }
120
121 #define CHECK_RELEASE(obj,d,rc) \
122     if (obj) { \
123         int tmp1, rc_new = rc; \
124         IUnknown_Release( (IUnknown*)obj ); \
125         tmp1 = get_refcount( (IUnknown *)d ); \
126         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
127     }
128
129 #define CHECK_REFCOUNT(obj,rc) \
130     { \
131         int rc_new = rc; \
132         int count = get_refcount( (IUnknown *)obj ); \
133         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
134     }
135
136 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
137     { \
138         int rc_new = rc; \
139         int count = IUnknown_Release( (IUnknown *)obj ); \
140         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
141     }
142
143 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
144     { \
145         int rc_new = rc; \
146         int count = IUnknown_AddRef( (IUnknown *)obj ); \
147         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
148     }
149
150 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
151     { \
152         void *container_ptr = (void *)0x1337c0d3; \
153         hr = IDirect3DSurface8_GetContainer(obj, &iid, &container_ptr); \
154         ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#08x, container_ptr %p. " \
155             "Expected hr %#08x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
156         if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
157     }
158
159 static void check_mipmap_levels(IDirect3DDevice8 *device, UINT width, UINT height, UINT count)
160 {
161     IDirect3DBaseTexture8* texture = NULL;
162     HRESULT hr = IDirect3DDevice8_CreateTexture( device, width, height, 0, 0,
163             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture8**) &texture );
164
165     if (SUCCEEDED(hr)) {
166         DWORD levels = IDirect3DBaseTexture8_GetLevelCount(texture);
167         ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
168     } else
169         trace("CreateTexture failed: %#08x\n", hr);
170
171     if (texture) IDirect3DBaseTexture8_Release( texture );
172 }
173
174 static void test_mipmap_levels(void)
175 {
176
177     HRESULT               hr;
178     HWND                  hwnd = NULL;
179
180     IDirect3D8            *pD3d = NULL;
181     IDirect3DDevice8      *pDevice = NULL;
182     D3DPRESENT_PARAMETERS d3dpp;
183     D3DDISPLAYMODE        d3ddm;
184
185     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
186     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
187     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
188     ok(hwnd != NULL, "Failed to create window\n");
189     if (!pD3d || !hwnd) goto cleanup;
190
191     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
192     ZeroMemory( &d3dpp, sizeof(d3dpp) );
193     d3dpp.Windowed         = TRUE;
194     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
195     d3dpp.BackBufferFormat = d3ddm.Format;
196
197     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
198                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
199     if(FAILED(hr))
200     {
201         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
202         goto cleanup;
203     }
204
205     check_mipmap_levels(pDevice, 32, 32, 6);
206     check_mipmap_levels(pDevice, 256, 1, 9);
207     check_mipmap_levels(pDevice, 1, 256, 9);
208     check_mipmap_levels(pDevice, 1, 1, 1);
209
210 cleanup:
211     if (pDevice)
212     {
213         UINT refcount = IDirect3DDevice8_Release( pDevice );
214         ok(!refcount, "Device has %u references left.\n", refcount);
215     }
216     if (pD3d) IDirect3D8_Release( pD3d );
217     DestroyWindow( hwnd );
218 }
219
220 static void test_swapchain(void)
221 {
222     HRESULT                      hr;
223     HWND                         hwnd               = NULL;
224     IDirect3D8                  *pD3d               = NULL;
225     IDirect3DDevice8            *pDevice            = NULL;
226     IDirect3DSwapChain8         *swapchain1         = NULL;
227     IDirect3DSwapChain8         *swapchain2         = NULL;
228     IDirect3DSwapChain8         *swapchain3         = NULL;
229     IDirect3DSurface8           *backbuffer         = NULL;
230     D3DPRESENT_PARAMETERS        d3dpp;
231     D3DDISPLAYMODE               d3ddm;
232
233     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
234     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
235     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
236     ok(hwnd != NULL, "Failed to create window\n");
237     if (!pD3d || !hwnd) goto cleanup;
238
239     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
240     ZeroMemory( &d3dpp, sizeof(d3dpp) );
241     d3dpp.Windowed         = TRUE;
242     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
243     d3dpp.BackBufferFormat = d3ddm.Format;
244     d3dpp.BackBufferCount  = 0;
245
246     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
247                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
248     if(FAILED(hr))
249     {
250         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
251         goto cleanup;
252     }
253
254     /* Check if the back buffer count was modified */
255     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
256
257     /* Create a bunch of swapchains */
258     d3dpp.BackBufferCount = 0;
259     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
260     ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
261     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
262
263     d3dpp.BackBufferCount  = 1;
264     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
265     ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
266
267     d3dpp.BackBufferCount  = 2;
268     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
269     ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
270     if(SUCCEEDED(hr)) {
271         /* Swapchain 3, created with backbuffercount 2 */
272         backbuffer = (void *) 0xdeadbeef;
273         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
274         ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%#08x)\n", hr);
275         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
276         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
277
278         backbuffer = (void *) 0xdeadbeef;
279         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
280         ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%#08x)\n", hr);
281         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
282         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
283
284         backbuffer = (void *) 0xdeadbeef;
285         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
286         ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
287         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
288         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
289
290         backbuffer = (void *) 0xdeadbeef;
291         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
292         ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
293         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
294         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
295     }
296
297     /* Check the back buffers of the swapchains */
298     /* Swapchain 1, created with backbuffercount 0 */
299     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
300     ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
301     ok(backbuffer != NULL, "The back buffer is NULL (%#08x)\n", hr);
302     if(backbuffer) IDirect3DSurface8_Release(backbuffer);
303
304     backbuffer = (void *) 0xdeadbeef;
305     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
306     ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
307     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
308     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
309
310     /* Swapchain 2 - created with backbuffercount 1 */
311     backbuffer = (void *) 0xdeadbeef;
312     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
313     ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
314     ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
315     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
316
317     backbuffer = (void *) 0xdeadbeef;
318     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
319     ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
320     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
321     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
322
323     backbuffer = (void *) 0xdeadbeef;
324     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
325     ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
326     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
327     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
328
329 cleanup:
330     if(swapchain1) IDirect3DSwapChain8_Release(swapchain1);
331     if(swapchain2) IDirect3DSwapChain8_Release(swapchain2);
332     if(swapchain3) IDirect3DSwapChain8_Release(swapchain3);
333     if (pDevice)
334     {
335         UINT refcount = IDirect3DDevice8_Release(pDevice);
336         ok(!refcount, "Device has %u references left.\n", refcount);
337     }
338     if (pD3d) IDirect3D8_Release(pD3d);
339     DestroyWindow( hwnd );
340 }
341
342 static void test_refcount(void)
343 {
344     HRESULT                      hr;
345     HWND                         hwnd               = NULL;
346     IDirect3D8                  *pD3d               = NULL;
347     IDirect3D8                  *pD3d2              = NULL;
348     IDirect3DDevice8            *pDevice            = NULL;
349     IDirect3DVertexBuffer8      *pVertexBuffer      = NULL;
350     IDirect3DIndexBuffer8       *pIndexBuffer       = NULL;
351     DWORD                       dVertexShader       = -1;
352     DWORD                       dPixelShader        = -1;
353     IDirect3DCubeTexture8       *pCubeTexture       = NULL;
354     IDirect3DTexture8           *pTexture           = NULL;
355     IDirect3DVolumeTexture8     *pVolumeTexture     = NULL;
356     IDirect3DVolume8            *pVolumeLevel       = NULL;
357     IDirect3DSurface8           *pStencilSurface    = NULL;
358     IDirect3DSurface8           *pImageSurface      = NULL;
359     IDirect3DSurface8           *pRenderTarget      = NULL;
360     IDirect3DSurface8           *pRenderTarget2     = NULL;
361     IDirect3DSurface8           *pRenderTarget3     = NULL;
362     IDirect3DSurface8           *pTextureLevel      = NULL;
363     IDirect3DSurface8           *pBackBuffer        = NULL;
364     DWORD                       dStateBlock         = -1;
365     IDirect3DSwapChain8         *pSwapChain         = NULL;
366     D3DCAPS8                    caps;
367
368     D3DPRESENT_PARAMETERS        d3dpp;
369     D3DDISPLAYMODE               d3ddm;
370     int                          refcount = 0, tmp;
371
372     DWORD decl[] =
373     {
374         D3DVSD_STREAM(0),
375         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
376         D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
377         D3DVSD_END()
378     };
379
380     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
381     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
382     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
383     ok(hwnd != NULL, "Failed to create window\n");
384     if (!pD3d || !hwnd) goto cleanup;
385
386     CHECK_REFCOUNT( pD3d, 1 );
387
388     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
389     ZeroMemory( &d3dpp, sizeof(d3dpp) );
390     d3dpp.Windowed         = TRUE;
391     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
392     d3dpp.BackBufferFormat = d3ddm.Format;
393     d3dpp.EnableAutoDepthStencil = TRUE;
394     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
395
396     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
397                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
398     if(FAILED(hr))
399     {
400         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
401         goto cleanup;
402     }
403     IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
404
405     refcount = get_refcount( (IUnknown *)pDevice );
406     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
407
408     CHECK_REFCOUNT( pD3d, 2 );
409
410     hr = IDirect3DDevice8_GetDirect3D(pDevice, &pD3d2);
411     CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
412
413     ok(pD3d2 == pD3d, "Expected IDirect3D8 pointers to be equal\n");
414     CHECK_REFCOUNT( pD3d, 3 );
415     CHECK_RELEASE_REFCOUNT( pD3d, 2 );
416
417     /**
418      * Check refcount of implicit surfaces. Findings:
419      *   - the container is the device
420      *   - they hold a reference to the device
421      *   - they are created with a refcount of 0 (Get/Release returns original refcount)
422      *   - they are not freed if refcount reaches 0.
423      *   - the refcount is not forwarded to the container.
424      */
425     hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
426     CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
427     if(pRenderTarget)
428     {
429         CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DDevice8, pDevice);
430         CHECK_REFCOUNT( pRenderTarget, 1);
431
432         CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
433         CHECK_REFCOUNT(pDevice, refcount);
434         CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
435         CHECK_REFCOUNT(pDevice, refcount);
436
437         hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
438         CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
439         CHECK_REFCOUNT( pRenderTarget, 2);
440         CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
441         CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
442         CHECK_REFCOUNT( pDevice, --refcount);
443
444         /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
445         CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
446         CHECK_REFCOUNT(pDevice, ++refcount);
447         CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
448         CHECK_REFCOUNT(pDevice, --refcount);
449     }
450
451     /* Render target and back buffer are identical. */
452     hr = IDirect3DDevice8_GetBackBuffer(pDevice, 0, 0, &pBackBuffer);
453     CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
454     if(pBackBuffer)
455     {
456         CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
457         ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
458            pRenderTarget, pBackBuffer);
459         pBackBuffer = NULL;
460     }
461     CHECK_REFCOUNT( pDevice, --refcount);
462
463     hr = IDirect3DDevice8_GetDepthStencilSurface(pDevice, &pStencilSurface);
464     CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
465     if(pStencilSurface)
466     {
467         CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice8, pDevice);
468         CHECK_REFCOUNT( pStencilSurface, 1);
469
470         CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
471         CHECK_REFCOUNT(pDevice, refcount);
472         CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
473         CHECK_REFCOUNT(pDevice, refcount);
474
475         CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
476         CHECK_REFCOUNT( pDevice, --refcount);
477
478         /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
479         CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
480         CHECK_REFCOUNT(pDevice, ++refcount);
481         CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
482         CHECK_REFCOUNT(pDevice, --refcount);
483         pStencilSurface = NULL;
484     }
485
486     /* Buffers */
487     hr = IDirect3DDevice8_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer );
488     CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
489     if(pIndexBuffer)
490     {
491         tmp = get_refcount( (IUnknown *)pIndexBuffer );
492
493         hr = IDirect3DDevice8_SetIndices(pDevice, pIndexBuffer, 0);
494         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
495         hr = IDirect3DDevice8_SetIndices(pDevice, NULL, 0);
496         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
497     }
498
499     hr = IDirect3DDevice8_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer );
500     CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
501     if(pVertexBuffer)
502     {
503         IDirect3DVertexBuffer8 *pVBuf = (void*)~0;
504         UINT stride = ~0;
505
506         tmp = get_refcount( (IUnknown *)pVertexBuffer );
507
508         hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, pVertexBuffer, 3 * sizeof(float));
509         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
510         hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, NULL, 0);
511         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
512
513         hr = IDirect3DDevice8_GetStreamSource(pDevice, 0, &pVBuf, &stride);
514         ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
515         ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
516         ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
517     }
518
519     /* Shaders */
520     hr = IDirect3DDevice8_CreateVertexShader( pDevice, decl, simple_vs, &dVertexShader, 0 );
521     CHECK_CALL( hr, "CreateVertexShader", pDevice, refcount );
522     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
523     {
524         hr = IDirect3DDevice8_CreatePixelShader( pDevice, simple_ps, &dPixelShader );
525         CHECK_CALL( hr, "CreatePixelShader", pDevice, refcount );
526     }
527     /* Textures */
528     hr = IDirect3DDevice8_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture );
529     CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
530     if (pTexture)
531     {
532         tmp = get_refcount( (IUnknown *)pTexture );
533
534         /* SetTexture should not increase refcounts */
535         hr = IDirect3DDevice8_SetTexture(pDevice, 0, (IDirect3DBaseTexture8 *) pTexture);
536         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
537         hr = IDirect3DDevice8_SetTexture(pDevice, 0, NULL);
538         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
539
540         /* This should not increment device refcount */
541         hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
542         CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
543         /* But should increment texture's refcount */
544         CHECK_REFCOUNT( pTexture, tmp+1 );
545         /* Because the texture and surface refcount are identical */
546         if (pTextureLevel)
547         {
548             CHECK_REFCOUNT        ( pTextureLevel, tmp+1 );
549             CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
550             CHECK_REFCOUNT        ( pTexture     , tmp+2 );
551             CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
552             CHECK_REFCOUNT        ( pTexture     , tmp+1 );
553             CHECK_RELEASE_REFCOUNT( pTexture     , tmp   );
554             CHECK_REFCOUNT        ( pTextureLevel, tmp   );
555         }
556     }
557     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
558     {
559         hr = IDirect3DDevice8_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture );
560         CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
561     }
562     else
563     {
564         skip("Cube textures not supported\n");
565     }
566     if(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
567     {
568         hr = IDirect3DDevice8_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture );
569         CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
570     }
571     else
572     {
573         skip("Volume textures not supported\n");
574     }
575
576     if (pVolumeTexture)
577     {
578         tmp = get_refcount( (IUnknown *)pVolumeTexture );
579
580         /* This should not increment device refcount */
581         hr = IDirect3DVolumeTexture8_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
582         CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
583         /* But should increment volume texture's refcount */
584         CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
585         /* Because the volume texture and volume refcount are identical */
586         if (pVolumeLevel)
587         {
588             CHECK_REFCOUNT        ( pVolumeLevel  , tmp+1 );
589             CHECK_ADDREF_REFCOUNT ( pVolumeLevel  , tmp+2 );
590             CHECK_REFCOUNT        ( pVolumeTexture, tmp+2 );
591             CHECK_RELEASE_REFCOUNT( pVolumeLevel  , tmp+1 );
592             CHECK_REFCOUNT        ( pVolumeTexture, tmp+1 );
593             CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp   );
594             CHECK_REFCOUNT        ( pVolumeLevel  , tmp   );
595         }
596     }
597     /* Surfaces */
598     hr = IDirect3DDevice8_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D16, D3DMULTISAMPLE_NONE, &pStencilSurface );
599     CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
600     CHECK_REFCOUNT( pStencilSurface, 1);
601     hr = IDirect3DDevice8_CreateImageSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, &pImageSurface );
602     CHECK_CALL( hr, "CreateImageSurface", pDevice, ++refcount );
603     CHECK_REFCOUNT( pImageSurface, 1);
604     hr = IDirect3DDevice8_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget3 );
605     CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
606     CHECK_REFCOUNT( pRenderTarget3, 1);
607     /* Misc */
608     hr = IDirect3DDevice8_CreateStateBlock( pDevice, D3DSBT_ALL, &dStateBlock );
609     CHECK_CALL( hr, "CreateStateBlock", pDevice, refcount );
610     hr = IDirect3DDevice8_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
611     CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
612     if(pSwapChain)
613     {
614         /* check implicit back buffer */
615         hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
616         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
617         CHECK_REFCOUNT( pSwapChain, 1);
618         if(pBackBuffer)
619         {
620             CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DDevice8, pDevice);
621             CHECK_REFCOUNT( pBackBuffer, 1);
622             CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
623             CHECK_REFCOUNT( pDevice, --refcount);
624
625             /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
626             CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
627             CHECK_REFCOUNT(pDevice, ++refcount);
628             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
629             CHECK_REFCOUNT(pDevice, --refcount);
630             pBackBuffer = NULL;
631         }
632         CHECK_REFCOUNT( pSwapChain, 1);
633     }
634
635     if(pVertexBuffer)
636     {
637         BYTE *data;
638         /* Vertex buffers can be locked multiple times */
639         hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
640         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
641         hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
642         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
643         hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
644         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
645         hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
646         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
647     }
648
649     /* The implicit render target is not freed if refcount reaches 0.
650      * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
651     hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget2);
652     CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
653     if(pRenderTarget2)
654     {
655         CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
656         ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
657            pRenderTarget, pRenderTarget2);
658         CHECK_REFCOUNT( pDevice, --refcount);
659         pRenderTarget2 = NULL;
660     }
661     pRenderTarget = NULL;
662
663 cleanup:
664     CHECK_RELEASE(pDevice,              pDevice, --refcount);
665
666     /* Buffers */
667     CHECK_RELEASE(pVertexBuffer,        pDevice, --refcount);
668     CHECK_RELEASE(pIndexBuffer,         pDevice, --refcount);
669     /* Shaders */
670     if (dVertexShader != ~0U) IDirect3DDevice8_DeleteVertexShader( pDevice, dVertexShader );
671     if (dPixelShader != ~0U) IDirect3DDevice8_DeletePixelShader( pDevice, dPixelShader );
672     /* Textures */
673     CHECK_RELEASE(pTexture,             pDevice, --refcount);
674     CHECK_RELEASE(pCubeTexture,         pDevice, --refcount);
675     CHECK_RELEASE(pVolumeTexture,       pDevice, --refcount);
676     /* Surfaces */
677     CHECK_RELEASE(pStencilSurface,      pDevice, --refcount);
678     CHECK_RELEASE(pImageSurface,        pDevice, --refcount);
679     CHECK_RELEASE(pRenderTarget3,       pDevice, --refcount);
680     /* Misc */
681     if (dStateBlock != ~0U) IDirect3DDevice8_DeleteStateBlock( pDevice, dStateBlock );
682     /* This will destroy device - cannot check the refcount here */
683     if (pSwapChain)           CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
684
685     if (pD3d)                 CHECK_RELEASE_REFCOUNT( pD3d, 0);
686
687     DestroyWindow( hwnd );
688 }
689
690 static void test_cursor(void)
691 {
692     HRESULT                      hr;
693     HWND                         hwnd               = NULL;
694     IDirect3D8                  *pD3d               = NULL;
695     IDirect3DDevice8            *pDevice            = NULL;
696     D3DPRESENT_PARAMETERS        d3dpp;
697     D3DDISPLAYMODE               d3ddm;
698     CURSORINFO                   info;
699     IDirect3DSurface8 *cursor = NULL;
700     HCURSOR cur;
701     HMODULE user32_handle = GetModuleHandleA("user32.dll");
702
703     pGetCursorInfo = (void *)GetProcAddress(user32_handle, "GetCursorInfo");
704     if (!pGetCursorInfo)
705     {
706         win_skip("GetCursorInfo is not available\n");
707         return;
708     }
709
710     memset(&info, 0, sizeof(info));
711     info.cbSize = sizeof(info);
712     ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
713     cur = info.hCursor;
714
715     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
716     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
717     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
718     ok(hwnd != NULL, "Failed to create window\n");
719     if (!pD3d || !hwnd) goto cleanup;
720
721     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
722     ZeroMemory( &d3dpp, sizeof(d3dpp) );
723     d3dpp.Windowed         = TRUE;
724     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
725     d3dpp.BackBufferFormat = d3ddm.Format;
726
727     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
728                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
729     if(FAILED(hr))
730     {
731         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
732         goto cleanup;
733     }
734
735     IDirect3DDevice8_CreateImageSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, &cursor);
736     ok(cursor != NULL, "IDirect3DDevice8_CreateOffscreenPlainSurface failed with %#08x\n", hr);
737
738     /* Initially hidden */
739     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
740     ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
741
742     /* Not enabled without a surface*/
743     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
744     ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
745
746     /* Fails */
747     hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, NULL);
748     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
749
750     hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, cursor);
751     ok(hr == D3D_OK, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
752
753     IDirect3DSurface8_Release(cursor);
754
755     memset(&info, 0, sizeof(info));
756     info.cbSize = sizeof(info);
757     ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
758     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
759     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
760
761     /* Still hidden */
762     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
763     ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
764
765     /* Enabled now*/
766     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
767     ok(hr == TRUE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
768
769     /* GDI cursor unchanged */
770     memset(&info, 0, sizeof(info));
771     info.cbSize = sizeof(info);
772     ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
773     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
774     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
775
776 cleanup:
777     if (pDevice)
778     {
779         UINT refcount = IDirect3DDevice8_Release(pDevice);
780         ok(!refcount, "Device has %u references left.\n", refcount);
781     }
782     if (pD3d) IDirect3D8_Release(pD3d);
783     DestroyWindow(hwnd);
784 }
785
786 static const POINT *expect_pos;
787
788 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
789 {
790     if (message == WM_MOUSEMOVE)
791     {
792         if (expect_pos && expect_pos->x && expect_pos->y)
793         {
794             POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
795
796             ClientToScreen(window, &p);
797             if (expect_pos->x == p.x && expect_pos->y == p.y)
798                 ++expect_pos;
799         }
800     }
801
802     return DefWindowProcA(window, message, wparam, lparam);
803 }
804
805 static void test_cursor_pos(void)
806 {
807     IDirect3DSurface8 *cursor;
808     IDirect3DDevice8 *device;
809     WNDCLASSA wc = {0};
810     IDirect3D8 *d3d8;
811     UINT refcount;
812     HWND window;
813     HRESULT hr;
814     BOOL ret;
815
816     /* Note that we don't check for movement we're not supposed to receive.
817      * That's because it's hard to distinguish from the user accidentally
818      * moving the mouse. */
819     static const POINT points[] =
820     {
821         {50, 50},
822         {75, 75},
823         {100, 100},
824         {125, 125},
825         {150, 150},
826         {125, 125},
827         {150, 150},
828         {150, 150},
829         {0, 0},
830     };
831
832     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
833     {
834         skip("Failed to create IDirect3D8 object, skipping cursor tests.\n");
835         return;
836     }
837
838     wc.lpfnWndProc = test_cursor_proc;
839     wc.lpszClassName = "d3d8_test_cursor_wc";
840     ok(RegisterClassA(&wc), "Failed to register window class.\n");
841     window = CreateWindow("d3d8_test_cursor_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
842             0, 0, 320, 240, NULL, NULL, NULL, NULL);
843     ShowWindow(window, SW_SHOW);
844
845     device = create_device(d3d8, window, window, TRUE);
846     if (!device)
847     {
848         skip("Failed to create a D3D device, skipping tests.\n");
849         goto done;
850     }
851
852     hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
853     ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
854     hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
855     ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
856     IDirect3DSurface8_Release(cursor);
857     ret = IDirect3DDevice8_ShowCursor(device, TRUE);
858     ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
859
860     flush_events();
861     expect_pos = points;
862
863     ret = SetCursorPos(50, 50);
864     ok(ret, "Failed to set cursor position.\n");
865     flush_events();
866
867     IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
868     flush_events();
869     /* SetCursorPosition() eats duplicates. */
870     IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
871     flush_events();
872
873     ret = SetCursorPos(100, 100);
874     ok(ret, "Failed to set cursor position.\n");
875     flush_events();
876     /* Even if the position was set with SetCursorPos(). */
877     IDirect3DDevice8_SetCursorPosition(device, 100, 100, 0);
878     flush_events();
879
880     IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
881     flush_events();
882     ret = SetCursorPos(150, 150);
883     ok(ret, "Failed to set cursor position.\n");
884     flush_events();
885     IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
886     flush_events();
887
888     IDirect3DDevice8_SetCursorPosition(device, 150, 150, 0);
889     flush_events();
890     /* SetCursorPos() doesn't. */
891     ret = SetCursorPos(150, 150);
892     ok(ret, "Failed to set cursor position.\n");
893     flush_events();
894
895     ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
896        (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
897
898     refcount = IDirect3DDevice8_Release(device);
899     ok(!refcount, "Device has %u references left.\n", refcount);
900 done:
901     DestroyWindow(window);
902     UnregisterClassA("d3d8_test_cursor_wc", GetModuleHandleA(NULL));
903     if (d3d8)
904         IDirect3D8_Release(d3d8);
905 }
906
907 static void test_states(void)
908 {
909     HRESULT                      hr;
910     HWND                         hwnd               = NULL;
911     IDirect3D8                  *pD3d               = NULL;
912     IDirect3DDevice8            *pDevice            = NULL;
913     D3DPRESENT_PARAMETERS        d3dpp;
914     D3DDISPLAYMODE               d3ddm;
915
916     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
917     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
918     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
919     ok(hwnd != NULL, "Failed to create window\n");
920     if (!pD3d || !hwnd) goto cleanup;
921
922     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
923     ZeroMemory( &d3dpp, sizeof(d3dpp) );
924     d3dpp.Windowed         = TRUE;
925     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
926     d3dpp.BackBufferWidth  = screen_width;
927     d3dpp.BackBufferHeight = screen_height;
928     d3dpp.BackBufferFormat = d3ddm.Format;
929
930     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
931                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
932     if(FAILED(hr))
933     {
934         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
935         goto cleanup;
936     }
937
938     hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, TRUE);
939     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, TRUE) returned %#08x\n", hr);
940     hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, FALSE);
941     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, FALSE) returned %#08x\n", hr);
942
943 cleanup:
944     if (pDevice)
945     {
946         UINT refcount = IDirect3DDevice8_Release(pDevice);
947         ok(!refcount, "Device has %u references left.\n", refcount);
948     }
949     if (pD3d) IDirect3D8_Release(pD3d);
950     DestroyWindow(hwnd);
951 }
952
953 static void test_shader_versions(void)
954 {
955     HRESULT                      hr;
956     IDirect3D8                  *pD3d               = NULL;
957     D3DCAPS8                     d3dcaps;
958
959     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
960     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
961     if (pD3d != NULL) {
962         hr = IDirect3D8_GetDeviceCaps(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);
963         ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to get D3D8 caps (%#08x)\n", hr);
964         if (SUCCEEDED(hr)) {
965             ok(d3dcaps.VertexShaderVersion <= D3DVS_VERSION(1,1), "Unexpected VertexShaderVersion (%#x > %#x)\n", d3dcaps.VertexShaderVersion, D3DVS_VERSION(1,1));
966             ok(d3dcaps.PixelShaderVersion <= D3DPS_VERSION(1,4), "Unexpected PixelShaderVersion (%#x > %#x)\n", d3dcaps.PixelShaderVersion, D3DPS_VERSION(1,4));
967         } else {
968             skip("No Direct3D support\n");
969         }
970         IDirect3D8_Release(pD3d);
971     }
972 }
973
974
975 /* Test adapter display modes */
976 static void test_display_modes(void)
977 {
978     UINT max_modes, i;
979     D3DDISPLAYMODE dmode;
980     HRESULT res;
981     IDirect3D8 *pD3d;
982
983     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
984     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
985     if(!pD3d) return;
986
987     max_modes = IDirect3D8_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT);
988     ok(max_modes > 0 ||
989        broken(max_modes == 0), /* VMware */
990        "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
991
992     for(i=0; i<max_modes;i++) {
993         res = IDirect3D8_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, i, &dmode);
994         ok(res==D3D_OK, "EnumAdapterModes returned %#08x for mode %u!\n", res, i);
995         if(res != D3D_OK)
996             continue;
997
998         ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
999            "Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
1000     }
1001
1002     IDirect3D8_Release(pD3d);
1003 }
1004
1005 static void test_reset(void)
1006 {
1007     UINT width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1008     UINT height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1009     IDirect3DDevice8 *device1 = NULL;
1010     IDirect3DDevice8 *device2 = NULL;
1011     D3DDISPLAYMODE d3ddm, d3ddm2;
1012     D3DSURFACE_DESC surface_desc;
1013     D3DPRESENT_PARAMETERS d3dpp;
1014     IDirect3DSurface8 *surface;
1015     IDirect3DTexture8 *texture;
1016     UINT adapter_mode_count;
1017     D3DLOCKED_RECT lockrect;
1018     IDirect3D8 *d3d8 = NULL;
1019     UINT mode_count = 0;
1020     HWND window = NULL;
1021     RECT winrect;
1022     D3DVIEWPORT8 vp;
1023     D3DCAPS8 caps;
1024     DWORD shader;
1025     HRESULT hr;
1026     UINT i;
1027
1028     static const DWORD decl[] =
1029     {
1030         D3DVSD_STREAM(0),
1031         D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT4),
1032         D3DVSD_END(),
1033     };
1034
1035     struct
1036     {
1037         UINT w;
1038         UINT h;
1039     } *modes = NULL;
1040
1041     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
1042     ok(!!d3d8, "Failed to create IDirect3D8 object.\n");
1043     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1044             100, 100, 160, 160, NULL, NULL, NULL, NULL);
1045     ok(!!window, "Failed to create window.\n");
1046     if (!d3d8 || !window)
1047         goto cleanup;
1048
1049     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1050     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1051     adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
1052     modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1053     for (i = 0; i < adapter_mode_count; ++i)
1054     {
1055         UINT j;
1056
1057         memset(&d3ddm2, 0, sizeof(d3ddm2));
1058         hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm2);
1059         ok(SUCCEEDED(hr), "EnumAdapterModes failed, hr %#x.\n", hr);
1060
1061         if (d3ddm2.Format != d3ddm.Format)
1062             continue;
1063
1064         for (j = 0; j < mode_count; ++j)
1065         {
1066             if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1067                 break;
1068         }
1069         if (j == mode_count)
1070         {
1071             modes[j].w = d3ddm2.Width;
1072             modes[j].h = d3ddm2.Height;
1073             ++mode_count;
1074         }
1075
1076         /* We use them as invalid modes. */
1077         if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
1078                 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
1079         {
1080             skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
1081                     d3ddm2.Width, d3ddm2.Height);
1082             goto cleanup;
1083         }
1084     }
1085
1086     if (mode_count < 2)
1087     {
1088         skip("Less than 2 modes supported, skipping mode tests.\n");
1089         goto cleanup;
1090     }
1091
1092     i = 0;
1093     if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1094
1095     memset(&d3dpp, 0, sizeof(d3dpp));
1096     d3dpp.Windowed = FALSE;
1097     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1098     d3dpp.BackBufferWidth = modes[i].w;
1099     d3dpp.BackBufferHeight = modes[i].h;
1100     d3dpp.BackBufferFormat = d3ddm.Format;
1101     d3dpp.EnableAutoDepthStencil = TRUE;
1102     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1103
1104     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1105             window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
1106     if (FAILED(hr))
1107     {
1108         skip("Failed to create device, hr %#x.\n", hr);
1109         goto cleanup;
1110     }
1111     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1112     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1113
1114     hr = IDirect3DDevice8_GetDeviceCaps(device1, &caps);
1115     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1116
1117     width = GetSystemMetrics(SM_CXSCREEN);
1118     height = GetSystemMetrics(SM_CYSCREEN);
1119     ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1120     ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1121
1122     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1123     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1124     if (SUCCEEDED(hr))
1125     {
1126         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1127         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1128         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1129         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1130         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1131         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1132     }
1133
1134     i = 1;
1135     vp.X = 10;
1136     vp.Y = 20;
1137     vp.Width = modes[i].w  / 2;
1138     vp.Height = modes[i].h / 2;
1139     vp.MinZ = 0.2f;
1140     vp.MaxZ = 0.3f;
1141     hr = IDirect3DDevice8_SetViewport(device1, &vp);
1142     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1143
1144     memset(&d3dpp, 0, sizeof(d3dpp));
1145     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1146     d3dpp.Windowed = FALSE;
1147     d3dpp.BackBufferWidth = modes[i].w;
1148     d3dpp.BackBufferHeight = modes[i].h;
1149     d3dpp.BackBufferFormat = d3ddm.Format;
1150     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1151     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1152     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1153     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1154
1155     memset(&vp, 0, sizeof(vp));
1156     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1157     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1158     if (SUCCEEDED(hr))
1159     {
1160         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1161         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1162         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1163         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1164         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1165         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1166     }
1167
1168     width = GetSystemMetrics(SM_CXSCREEN);
1169     height = GetSystemMetrics(SM_CYSCREEN);
1170     ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1171     ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1172
1173     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1174     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1175     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1176     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1177     ok(surface_desc.Width == modes[i].w, "Back buffer width is %u, expected %u.\n",
1178             surface_desc.Width, modes[i].w);
1179     ok(surface_desc.Height == modes[i].h, "Back buffer height is %u, expected %u.\n",
1180             surface_desc.Height, modes[i].h);
1181     IDirect3DSurface8_Release(surface);
1182
1183     memset(&d3dpp, 0, sizeof(d3dpp));
1184     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1185     d3dpp.Windowed = TRUE;
1186     d3dpp.BackBufferWidth = 400;
1187     d3dpp.BackBufferHeight = 300;
1188     d3dpp.BackBufferFormat = d3ddm.Format;
1189     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1190     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1191     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1192     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1193
1194     memset(&vp, 0, sizeof(vp));
1195     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1196     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1197     if (SUCCEEDED(hr))
1198     {
1199         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1200         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1201         ok(vp.Width == 400, "D3DVIEWPORT->Width = %u, expected 400.\n", vp.Width);
1202         ok(vp.Height == 300, "D3DVIEWPORT->Height = %u, expected 300.\n", vp.Height);
1203         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1204         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1205     }
1206
1207     width = GetSystemMetrics(SM_CXSCREEN);
1208     height = GetSystemMetrics(SM_CYSCREEN);
1209     ok(width == orig_width, "Screen width is %u, expected %u.\n", width, orig_width);
1210     ok(height == orig_height, "Screen height is %u, expected %u.\n", height, orig_height);
1211
1212     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1213     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1214     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1215     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1216     ok(surface_desc.Width == 400, "Back buffer width is %u, expected 400.\n",
1217             surface_desc.Width);
1218     ok(surface_desc.Height == 300, "Back buffer height is %u, expected 300.\n",
1219             surface_desc.Height);
1220     IDirect3DSurface8_Release(surface);
1221
1222     winrect.left = 0;
1223     winrect.top = 0;
1224     winrect.right = 200;
1225     winrect.bottom = 150;
1226     ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1227     ok(SetWindowPos(window, NULL, 0, 0,
1228                     winrect.right-winrect.left,
1229                     winrect.bottom-winrect.top,
1230                     SWP_NOMOVE|SWP_NOZORDER),
1231        "SetWindowPos failed\n");
1232
1233     memset(&d3dpp, 0, sizeof(d3dpp));
1234     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1235     d3dpp.Windowed = TRUE;
1236     d3dpp.BackBufferWidth = 0;
1237     d3dpp.BackBufferHeight = 0;
1238     d3dpp.BackBufferFormat = d3ddm.Format;
1239     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1240     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1241     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1242     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1243
1244     memset(&vp, 0, sizeof(vp));
1245     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1246     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1247     if (SUCCEEDED(hr))
1248     {
1249         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1250         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1251         todo_wine ok(vp.Width == 200, "D3DVIEWPORT->Width = %u, expected 200.\n", vp.Width);
1252         todo_wine ok(vp.Height == 150, "D3DVIEWPORT->Height = %u, expected 150.\n", vp.Height);
1253         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1254         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1255     }
1256
1257     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1258     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1259     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1260     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1261     todo_wine ok(surface_desc.Width == 200, "Back buffer width is %u, expected 200.\n",
1262                  surface_desc.Width);
1263     todo_wine ok(surface_desc.Height == 150, "Back buffer height is %u, expected 150.\n",
1264                  surface_desc.Height);
1265     IDirect3DSurface8_Release(surface);
1266
1267     memset(&d3dpp, 0, sizeof(d3dpp));
1268     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1269     d3dpp.Windowed = TRUE;
1270     d3dpp.BackBufferWidth = 400;
1271     d3dpp.BackBufferHeight = 300;
1272     d3dpp.BackBufferFormat = d3ddm.Format;
1273
1274     /* Reset fails if there is a resource in the default pool. */
1275     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texture);
1276     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1277     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1278     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1279     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1280     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1281     IDirect3DTexture8_Release(texture);
1282     /* Reset again to get the device out of the lost state. */
1283     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1284     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1285     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1286     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1287
1288     if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1289     {
1290         IDirect3DVolumeTexture8 *volume_texture;
1291
1292         hr = IDirect3DDevice8_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1293                 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture);
1294         ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1295         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1296         ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1297         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1298         ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1299                 hr, D3DERR_DEVICENOTRESET);
1300         IDirect3DVolumeTexture8_Release(volume_texture);
1301         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1302         ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1303         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1304         ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1305     }
1306     else
1307     {
1308         skip("Volume textures not supported.\n");
1309     }
1310
1311     /* Scratch, sysmem and managed pool resources are fine. */
1312     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1313     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1314     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1315     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1316     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1317     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1318     IDirect3DTexture8_Release(texture);
1319
1320     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1321     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1322     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1323     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1324     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1325     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1326     IDirect3DTexture8_Release(texture);
1327
1328     /* The depth stencil should get reset to the auto depth stencil when present. */
1329     hr = IDirect3DDevice8_SetRenderTarget(device1, NULL, NULL);
1330     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1331
1332     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1333     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1334     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1335
1336     d3dpp.EnableAutoDepthStencil = TRUE;
1337     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1338     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1339     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1340
1341     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1342     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1343     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1344     if (surface) IDirect3DSurface8_Release(surface);
1345
1346     d3dpp.EnableAutoDepthStencil = FALSE;
1347     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1348     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1349
1350     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1351     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1352     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1353
1354     /* Will a sysmem or scratch resource survive while locked? */
1355     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1356     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1357     hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1358     ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1359     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1360     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1361     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1362     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1363     IDirect3DTexture8_UnlockRect(texture, 0);
1364     IDirect3DTexture8_Release(texture);
1365
1366     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1367     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1368     hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1369     ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1370     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1371     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1372     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1373     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1374     IDirect3DTexture8_UnlockRect(texture, 0);
1375     IDirect3DTexture8_Release(texture);
1376
1377     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture);
1378     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1379     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1380     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1381     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1382     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1383     IDirect3DTexture8_Release(texture);
1384
1385     /* A reference held to an implicit surface causes failures as well. */
1386     hr = IDirect3DDevice8_GetBackBuffer(device1, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1387     ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
1388     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1389     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1390     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1391     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1392     IDirect3DSurface8_Release(surface);
1393     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1394     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1395     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1396     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1397
1398     /* Shaders are fine as well. */
1399     hr = IDirect3DDevice8_CreateVertexShader(device1, decl, simple_vs, &shader, 0);
1400     ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
1401     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1402     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1403     hr = IDirect3DDevice8_DeleteVertexShader(device1, shader);
1404     ok(SUCCEEDED(hr), "DeleteVertexShader failed, hr %#x.\n", hr);
1405
1406     /* Try setting invalid modes. */
1407     memset(&d3dpp, 0, sizeof(d3dpp));
1408     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1409     d3dpp.Windowed = FALSE;
1410     d3dpp.BackBufferWidth = 32;
1411     d3dpp.BackBufferHeight = 32;
1412     d3dpp.BackBufferFormat = d3ddm.Format;
1413     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1414     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1415     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1416     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1417
1418     memset(&d3dpp, 0, sizeof(d3dpp));
1419     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1420     d3dpp.Windowed = FALSE;
1421     d3dpp.BackBufferWidth = 801;
1422     d3dpp.BackBufferHeight = 600;
1423     d3dpp.BackBufferFormat = d3ddm.Format;
1424     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1425     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1426     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1427     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1428
1429     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1430     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1431
1432     memset(&d3dpp, 0, sizeof(d3dpp));
1433     d3dpp.Windowed = TRUE;
1434     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1435     d3dpp.BackBufferFormat = d3ddm.Format;
1436     d3dpp.EnableAutoDepthStencil = FALSE;
1437     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1438
1439     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1440             window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1441     if (FAILED(hr))
1442     {
1443         skip("Failed to create device, hr %#x.\n", hr);
1444         goto cleanup;
1445     }
1446
1447     hr = IDirect3DDevice8_TestCooperativeLevel(device2);
1448     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1449
1450     d3dpp.Windowed = TRUE;
1451     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1452     d3dpp.BackBufferWidth = 400;
1453     d3dpp.BackBufferHeight = 300;
1454     d3dpp.BackBufferFormat = d3ddm.Format;
1455     d3dpp.EnableAutoDepthStencil = TRUE;
1456     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1457
1458     hr = IDirect3DDevice8_Reset(device2, &d3dpp);
1459     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1460     if (FAILED(hr))
1461         goto cleanup;
1462
1463     hr = IDirect3DDevice8_GetDepthStencilSurface(device2, &surface);
1464     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1465     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1466     if (surface)
1467         IDirect3DSurface8_Release(surface);
1468
1469 cleanup:
1470     HeapFree(GetProcessHeap(), 0, modes);
1471     if (device2)
1472         IDirect3DDevice8_Release(device2);
1473     if (device1)
1474         IDirect3DDevice8_Release(device1);
1475     if (d3d8)
1476         IDirect3D8_Release(d3d8);
1477     if (window)
1478         DestroyWindow(window);
1479 }
1480
1481 static void test_scene(void)
1482 {
1483     HRESULT                      hr;
1484     HWND                         hwnd               = NULL;
1485     IDirect3D8                  *pD3d               = NULL;
1486     IDirect3DDevice8            *pDevice            = NULL;
1487     D3DPRESENT_PARAMETERS        d3dpp;
1488     D3DDISPLAYMODE               d3ddm;
1489
1490     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1491     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1492     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1493     ok(hwnd != NULL, "Failed to create window\n");
1494     if (!pD3d || !hwnd) goto cleanup;
1495
1496     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1497     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1498     d3dpp.Windowed         = TRUE;
1499     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1500     d3dpp.BackBufferWidth  = 800;
1501     d3dpp.BackBufferHeight = 600;
1502     d3dpp.BackBufferFormat = d3ddm.Format;
1503
1504
1505     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1506                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1507     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1508     if(!pDevice)
1509     {
1510         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1511         goto cleanup;
1512     }
1513
1514     /* Test an EndScene without BeginScene. Should return an error */
1515     hr = IDirect3DDevice8_EndScene(pDevice);
1516     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1517
1518     /* Test a normal BeginScene / EndScene pair, this should work */
1519     hr = IDirect3DDevice8_BeginScene(pDevice);
1520     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1521     if(SUCCEEDED(hr))
1522     {
1523         hr = IDirect3DDevice8_EndScene(pDevice);
1524         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1525     }
1526
1527     /* Test another EndScene without having begun a new scene. Should return an error */
1528     hr = IDirect3DDevice8_EndScene(pDevice);
1529     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1530
1531     /* Two nested BeginScene and EndScene calls */
1532     hr = IDirect3DDevice8_BeginScene(pDevice);
1533     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1534     hr = IDirect3DDevice8_BeginScene(pDevice);
1535     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1536     hr = IDirect3DDevice8_EndScene(pDevice);
1537     ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1538     hr = IDirect3DDevice8_EndScene(pDevice);
1539     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1540
1541     /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
1542
1543 cleanup:
1544     if (pDevice)
1545     {
1546         UINT refcount = IDirect3DDevice8_Release(pDevice);
1547         ok(!refcount, "Device has %u references left.\n", refcount);
1548     }
1549     if (pD3d) IDirect3D8_Release(pD3d);
1550     DestroyWindow(hwnd);
1551 }
1552
1553 static void test_shader(void)
1554 {
1555     HRESULT                      hr;
1556     HWND                         hwnd               = NULL;
1557     IDirect3D8                  *pD3d               = NULL;
1558     IDirect3DDevice8            *pDevice            = NULL;
1559     D3DPRESENT_PARAMETERS        d3dpp;
1560     D3DDISPLAYMODE               d3ddm;
1561     DWORD                        hPixelShader = 0, hVertexShader = 0;
1562     DWORD                        hPixelShader2 = 0, hVertexShader2 = 0;
1563     DWORD                        hTempHandle;
1564     D3DCAPS8                     caps;
1565     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
1566     DWORD data_size;
1567     void *data;
1568
1569     static DWORD dwVertexDecl[] =
1570     {
1571         D3DVSD_STREAM(0),
1572         D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT3),
1573         D3DVSD_END()
1574     };
1575     DWORD decl_normal_float2[] =
1576     {
1577         D3DVSD_STREAM(0),
1578         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1579         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT2),  /* D3DVSDE_NORMAL,   Register v1 */
1580         D3DVSD_END()
1581     };
1582     DWORD decl_normal_float4[] =
1583     {
1584         D3DVSD_STREAM(0),
1585         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1586         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT4),  /* D3DVSDE_NORMAL,   Register v1 */
1587         D3DVSD_END()
1588     };
1589     DWORD decl_normal_d3dcolor[] =
1590     {
1591         D3DVSD_STREAM(0),
1592         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1593         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL,   Register v1 */
1594         D3DVSD_END()
1595     };
1596     const DWORD vertex_decl_size = sizeof(dwVertexDecl);
1597     const DWORD simple_vs_size = sizeof(simple_vs);
1598     const DWORD simple_ps_size = sizeof(simple_ps);
1599
1600     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1601     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1602     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1603     ok(hwnd != NULL, "Failed to create window\n");
1604     if (!pD3d || !hwnd) goto cleanup;
1605
1606     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1607     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1608     d3dpp.Windowed         = TRUE;
1609     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1610     d3dpp.BackBufferWidth  = 800;
1611     d3dpp.BackBufferHeight = 600;
1612     d3dpp.BackBufferFormat = d3ddm.Format;
1613
1614
1615     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1616                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1617     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1618     if(!pDevice)
1619     {
1620         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1621         goto cleanup;
1622     }
1623     IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
1624
1625     /* Test setting and retrieving a FVF */
1626     hr = IDirect3DDevice8_SetVertexShader(pDevice, fvf);
1627     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1628     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1629     ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1630     ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
1631
1632     /* First create a vertex shader */
1633     hr = IDirect3DDevice8_SetVertexShader(pDevice, 0);
1634     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1635     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, simple_vs, &hVertexShader, 0);
1636     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1637     /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
1638     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1639     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1640     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1641     /* Assign the shader, then verify that GetVertexShader works */
1642     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1643     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1644     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1645     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1646     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1647     /* Verify that we can retrieve the declaration */
1648     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, NULL, &data_size);
1649     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1650     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1651     data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
1652     data_size = 1;
1653     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1654     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
1655             "expected D3DERR_INVALIDCALL\n", hr);
1656     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1657     data_size = vertex_decl_size;
1658     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1659     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1660     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1661     ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
1662     HeapFree(GetProcessHeap(), 0, data);
1663     /* Verify that we can retrieve the shader function */
1664     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, NULL, &data_size);
1665     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1666     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1667     data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
1668     data_size = 1;
1669     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1670     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
1671             "expected D3DERR_INVALIDCALL\n", hr);
1672     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1673     data_size = simple_vs_size;
1674     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1675     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1676     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1677     ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
1678     HeapFree(GetProcessHeap(), 0, data);
1679     /* Delete the assigned shader. This is supposed to work */
1680     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1681     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1682     /* The shader should be unset now */
1683     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1684     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1685     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1686
1687     /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
1688      * First try the fixed function shader function, then a custom one
1689      */
1690     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, 0, &hVertexShader, 0);
1691     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1692     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1693     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float4, 0, &hVertexShader, 0);
1694     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1695     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1696     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_d3dcolor, 0, &hVertexShader, 0);
1697     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1698     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1699
1700     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, simple_vs, &hVertexShader, 0);
1701     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1702     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1703
1704     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
1705     {
1706         /* The same with a pixel shader */
1707         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1708         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1709         /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
1710         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1711         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1712         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1713         /* Assign the shader, then verify that GetPixelShader works */
1714         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1715         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1716         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1717         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1718         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1719         /* Verify that we can retrieve the shader function */
1720         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, NULL, &data_size);
1721         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1722         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1723         data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
1724         data_size = 1;
1725         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1726         ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
1727                 "expected D3DERR_INVALIDCALL\n", hr);
1728         ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1729         data_size = simple_ps_size;
1730         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1731         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1732         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1733         ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
1734         HeapFree(GetProcessHeap(), 0, data);
1735         /* Delete the assigned shader. This is supposed to work */
1736         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1737         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1738         /* The shader should be unset now */
1739         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1740         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1741         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1742
1743         /* What happens if a non-bound shader is deleted? */
1744         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1745         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1746         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader2);
1747         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1748
1749         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1750         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1751         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1752         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1753         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1754         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1755         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1756         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1757         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1758
1759         /* Check for double delete. */
1760         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1761         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1762         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1763         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1764     }
1765     else
1766     {
1767         skip("Pixel shaders not supported\n");
1768     }
1769
1770     /* What happens if a non-bound shader is deleted? */
1771     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader, 0);
1772     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1773     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader2, 0);
1774     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1775
1776     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1777     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1778     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1779     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1780     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1781     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1782     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1783     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1784     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1785
1786     /* Check for double delete. */
1787     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1788     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1789     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1790     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1791
1792 cleanup:
1793     if (pDevice)
1794     {
1795         UINT refcount = IDirect3DDevice8_Release(pDevice);
1796         ok(!refcount, "Device has %u references left.\n", refcount);
1797     }
1798     if (pD3d) IDirect3D8_Release(pD3d);
1799     DestroyWindow(hwnd);
1800 }
1801
1802 static void test_limits(void)
1803 {
1804     HRESULT                      hr;
1805     HWND                         hwnd               = NULL;
1806     IDirect3D8                  *pD3d               = NULL;
1807     IDirect3DDevice8            *pDevice            = NULL;
1808     D3DPRESENT_PARAMETERS        d3dpp;
1809     D3DDISPLAYMODE               d3ddm;
1810     IDirect3DTexture8           *pTexture           = NULL;
1811     int i;
1812
1813     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1814     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1815     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1816     ok(hwnd != NULL, "Failed to create window\n");
1817     if (!pD3d || !hwnd) goto cleanup;
1818
1819     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1820     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1821     d3dpp.Windowed         = TRUE;
1822     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1823     d3dpp.BackBufferWidth  = 800;
1824     d3dpp.BackBufferHeight = 600;
1825     d3dpp.BackBufferFormat = d3ddm.Format;
1826     d3dpp.EnableAutoDepthStencil = TRUE;
1827     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1828
1829     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1830                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1831     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1832     if(!pDevice)
1833     {
1834         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1835         goto cleanup;
1836     }
1837
1838     hr = IDirect3DDevice8_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture);
1839     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
1840     if(!pTexture) goto cleanup;
1841
1842     /* There are 8 texture stages. We should be able to access all of them */
1843     for(i = 0; i < 8; i++) {
1844         hr = IDirect3DDevice8_SetTexture(pDevice, i, (IDirect3DBaseTexture8 *) pTexture);
1845         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1846         hr = IDirect3DDevice8_SetTexture(pDevice, i, NULL);
1847         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1848         hr = IDirect3DDevice8_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1849         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
1850     }
1851
1852     /* Investigations show that accessing higher textures stage states does not return an error either. Writing
1853      * to too high texture stages(approximately texture 40) causes memory corruption in windows, so there is no
1854      * bounds checking but how do I test that?
1855      */
1856
1857 cleanup:
1858     if(pTexture) IDirect3DTexture8_Release(pTexture);
1859     if (pDevice)
1860     {
1861         UINT refcount = IDirect3DDevice8_Release(pDevice);
1862         ok(!refcount, "Device has %u references left.\n", refcount);
1863     }
1864     if (pD3d) IDirect3D8_Release(pD3d);
1865     DestroyWindow(hwnd);
1866 }
1867
1868 static void test_lights(void)
1869 {
1870     D3DPRESENT_PARAMETERS d3dpp;
1871     IDirect3DDevice8 *device = NULL;
1872     IDirect3D8 *d3d8;
1873     HWND hwnd;
1874     HRESULT hr;
1875     unsigned int i;
1876     BOOL enabled;
1877     D3DCAPS8 caps;
1878     D3DDISPLAYMODE               d3ddm;
1879
1880     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1881     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1882     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1883     ok(hwnd != NULL, "Failed to create window\n");
1884     if (!d3d8 || !hwnd) goto cleanup;
1885
1886     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1887     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1888     d3dpp.Windowed         = TRUE;
1889     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1890     d3dpp.BackBufferWidth  = 800;
1891     d3dpp.BackBufferHeight = 600;
1892     d3dpp.BackBufferFormat = d3ddm.Format;
1893     d3dpp.EnableAutoDepthStencil = TRUE;
1894     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1895
1896     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1897                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
1898     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1899        "IDirect3D8_CreateDevice failed with %08x\n", hr);
1900     if(!device)
1901     {
1902         skip("Failed to create a d3d device\n");
1903         goto cleanup;
1904     }
1905
1906     memset(&caps, 0, sizeof(caps));
1907     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1908     ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
1909
1910     for(i = 1; i <= caps.MaxActiveLights; i++) {
1911         hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
1912         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1913         hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
1914         ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
1915             "GetLightEnable on light %u failed with %08x\n", i, hr);
1916         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1917     }
1918
1919     /* TODO: Test the rendering results in this situation */
1920     hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
1921     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
1922     hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
1923     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1924     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1925     hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
1926     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1927
1928     for(i = 1; i <= caps.MaxActiveLights; i++) {
1929         hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
1930         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
1931     }
1932
1933 cleanup:
1934     if (device)
1935     {
1936         UINT refcount = IDirect3DDevice8_Release(device);
1937         ok(!refcount, "Device has %u references left.\n", refcount);
1938     }
1939     if (d3d8) IDirect3D8_Release(d3d8);
1940     DestroyWindow(hwnd);
1941 }
1942
1943 static void test_render_zero_triangles(void)
1944 {
1945     D3DPRESENT_PARAMETERS d3dpp;
1946     IDirect3DDevice8 *device = NULL;
1947     IDirect3D8 *d3d8;
1948     HWND hwnd;
1949     HRESULT hr;
1950     D3DDISPLAYMODE               d3ddm;
1951
1952     struct nvertex
1953     {
1954         float x, y, z;
1955         float nx, ny, nz;
1956         DWORD diffuse;
1957     }  quad[] =
1958     {
1959         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1960         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1961         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1962         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1963     };
1964
1965     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1966     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1967     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1968     ok(hwnd != NULL, "Failed to create window\n");
1969     if (!d3d8 || !hwnd) goto cleanup;
1970
1971     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1972     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1973     d3dpp.Windowed         = TRUE;
1974     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1975     d3dpp.BackBufferWidth  = 800;
1976     d3dpp.BackBufferHeight = 600;
1977     d3dpp.BackBufferFormat = d3ddm.Format;
1978     d3dpp.EnableAutoDepthStencil = TRUE;
1979     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1980
1981     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1982                                   D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
1983     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1984        "IDirect3D8_CreateDevice failed with %08x\n", hr);
1985     if(!device)
1986     {
1987         skip("Failed to create a d3d device\n");
1988         goto cleanup;
1989     }
1990
1991     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1992     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1993
1994     hr = IDirect3DDevice8_BeginScene(device);
1995     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1996     if(hr == D3D_OK)
1997     {
1998         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
1999                                                     0 /*PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
2000         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
2001
2002         hr = IDirect3DDevice8_EndScene(device);
2003         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
2004     }
2005
2006     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2007
2008 cleanup:
2009     if (device)
2010     {
2011         UINT refcount = IDirect3DDevice8_Release(device);
2012         ok(!refcount, "Device has %u references left.\n", refcount);
2013     }
2014     if (d3d8) IDirect3D8_Release(d3d8);
2015     DestroyWindow(hwnd);
2016 }
2017
2018 static void test_depth_stencil_reset(void)
2019 {
2020     D3DPRESENT_PARAMETERS present_parameters;
2021     D3DDISPLAYMODE display_mode;
2022     IDirect3DSurface8 *surface, *orig_rt;
2023     IDirect3DDevice8 *device = NULL;
2024     IDirect3D8 *d3d8;
2025     UINT refcount;
2026     HRESULT hr;
2027     HWND hwnd;
2028
2029     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2030     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2031     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2032     ok(hwnd != NULL, "Failed to create window\n");
2033     if (!d3d8 || !hwnd) goto cleanup;
2034
2035     IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
2036     memset(&present_parameters, 0, sizeof(present_parameters));
2037     present_parameters.Windowed               = TRUE;
2038     present_parameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
2039     present_parameters.BackBufferFormat       = display_mode.Format;
2040     present_parameters.EnableAutoDepthStencil = TRUE;
2041     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2042
2043     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2044             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
2045     if(FAILED(hr))
2046     {
2047         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2048         goto cleanup;
2049     }
2050
2051     hr = IDirect3DDevice8_GetRenderTarget(device, &orig_rt);
2052     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2053
2054     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2055     ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
2056
2057     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2058     ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
2059
2060     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
2061     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2062     ok(surface == orig_rt, "Render target is %p, should be %p\n", surface, orig_rt);
2063     if (surface) IDirect3DSurface8_Release(surface);
2064     IDirect3DSurface8_Release(orig_rt);
2065
2066     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2067     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2068     ok(surface == NULL, "Depth stencil should be NULL\n");
2069
2070     present_parameters.EnableAutoDepthStencil = TRUE;
2071     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2072     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2073     ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2074
2075     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2076     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2077     ok(surface != NULL, "Depth stencil should not be NULL\n");
2078     if (surface) IDirect3DSurface8_Release(surface);
2079
2080     present_parameters.EnableAutoDepthStencil = FALSE;
2081     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2082     ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2083
2084     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2085     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2086     ok(surface == NULL, "Depth stencil should be NULL\n");
2087
2088     refcount = IDirect3DDevice8_Release(device);
2089     ok(!refcount, "Device has %u references left.\n", refcount);
2090     device = NULL;
2091
2092     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
2093
2094     ZeroMemory( &present_parameters, sizeof(present_parameters) );
2095     present_parameters.Windowed         = TRUE;
2096     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2097     present_parameters.BackBufferFormat = display_mode.Format;
2098     present_parameters.EnableAutoDepthStencil = FALSE;
2099     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2100
2101     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2102                     D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2103
2104     if(FAILED(hr))
2105     {
2106         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2107         goto cleanup;
2108     }
2109
2110     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2111     ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
2112
2113     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2114     present_parameters.Windowed         = TRUE;
2115     present_parameters.BackBufferWidth  = 400;
2116     present_parameters.BackBufferHeight = 300;
2117     present_parameters.EnableAutoDepthStencil = TRUE;
2118     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2119
2120     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2121     ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
2122
2123     if (FAILED(hr)) goto cleanup;
2124
2125     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2126     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2127     ok(surface != NULL, "Depth stencil should not be NULL\n");
2128     if (surface) IDirect3DSurface8_Release(surface);
2129
2130 cleanup:
2131     if (device)
2132     {
2133         refcount = IDirect3DDevice8_Release(device);
2134         ok(!refcount, "Device has %u references left.\n", refcount);
2135     }
2136     if (d3d8) IDirect3D8_Release(d3d8);
2137     DestroyWindow(hwnd);
2138 }
2139
2140 static HWND filter_messages;
2141
2142 enum message_window
2143 {
2144     DEVICE_WINDOW,
2145     FOCUS_WINDOW,
2146 };
2147
2148 struct message
2149 {
2150     UINT message;
2151     enum message_window window;
2152 };
2153
2154 static const struct message *expect_messages;
2155 static HWND device_window, focus_window;
2156
2157 struct wndproc_thread_param
2158 {
2159     HWND dummy_window;
2160     HANDLE window_created;
2161     HANDLE test_finished;
2162     BOOL running_in_foreground;
2163 };
2164
2165 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2166 {
2167     if (filter_messages && filter_messages == hwnd)
2168     {
2169         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2170             todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2171     }
2172
2173     if (expect_messages)
2174     {
2175         HWND w;
2176
2177         switch (expect_messages->window)
2178         {
2179             case DEVICE_WINDOW:
2180                 w = device_window;
2181                 break;
2182
2183             case FOCUS_WINDOW:
2184                 w = focus_window;
2185                 break;
2186
2187             default:
2188                 w = NULL;
2189                 break;
2190         };
2191
2192         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2193     }
2194
2195     return DefWindowProcA(hwnd, message, wparam, lparam);
2196 }
2197
2198 static DWORD WINAPI wndproc_thread(void *param)
2199 {
2200     struct wndproc_thread_param *p = param;
2201     DWORD res;
2202     BOOL ret;
2203
2204     p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2205             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2206     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2207
2208     ret = SetEvent(p->window_created);
2209     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2210
2211     for (;;)
2212     {
2213         MSG msg;
2214
2215         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2216         res = WaitForSingleObject(p->test_finished, 100);
2217         if (res == WAIT_OBJECT_0) break;
2218         if (res != WAIT_TIMEOUT)
2219         {
2220             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2221             break;
2222         }
2223     }
2224
2225     DestroyWindow(p->dummy_window);
2226
2227     return 0;
2228 }
2229
2230 static void test_wndproc(void)
2231 {
2232     struct wndproc_thread_param thread_params;
2233     IDirect3DDevice8 *device;
2234     WNDCLASSA wc = {0};
2235     IDirect3D8 *d3d8;
2236     HANDLE thread;
2237     LONG_PTR proc;
2238     ULONG ref;
2239     DWORD res, tid;
2240     HWND tmp;
2241
2242     static const struct message messages[] =
2243     {
2244         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2245         {WM_ACTIVATE,           FOCUS_WINDOW},
2246         {WM_SETFOCUS,           FOCUS_WINDOW},
2247         {WM_WINDOWPOSCHANGING,  DEVICE_WINDOW},
2248         {WM_MOVE,               DEVICE_WINDOW},
2249         {WM_SIZE,               DEVICE_WINDOW},
2250         {0,                     0},
2251     };
2252
2253     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2254     {
2255         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2256         return;
2257     }
2258
2259     wc.lpfnWndProc = test_proc;
2260     wc.lpszClassName = "d3d8_test_wndproc_wc";
2261     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2262
2263     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2264     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2265     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2266     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2267
2268     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2269             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2270     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2271             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2272     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2273     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2274
2275     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2276     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2277
2278     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2279     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2280             (LONG_PTR)test_proc, proc);
2281     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2282     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2283             (LONG_PTR)test_proc, proc);
2284
2285     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2286             device_window, focus_window, thread_params.dummy_window);
2287
2288     tmp = GetFocus();
2289     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2290     if (thread_params.running_in_foreground)
2291     {
2292         tmp = GetForegroundWindow();
2293         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2294                 thread_params.dummy_window, tmp);
2295     }
2296     else
2297         skip("Not running in foreground, skip foreground window test\n");
2298
2299     flush_events();
2300
2301     expect_messages = messages;
2302
2303     device = create_device(d3d8, device_window, focus_window, FALSE);
2304     if (!device)
2305     {
2306         skip("Failed to create a D3D device, skipping tests.\n");
2307         goto done;
2308     }
2309
2310     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2311             expect_messages->message, expect_messages->window);
2312     expect_messages = NULL;
2313
2314     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2315     {
2316         tmp = GetFocus();
2317         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2318         tmp = GetForegroundWindow();
2319         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2320     }
2321     SetForegroundWindow(focus_window);
2322     flush_events();
2323
2324     filter_messages = focus_window;
2325
2326     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2327     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2328             (LONG_PTR)test_proc, proc);
2329
2330     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2331     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2332             (LONG_PTR)test_proc, proc);
2333
2334     ref = IDirect3DDevice8_Release(device);
2335     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2336
2337     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2338     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2339             (LONG_PTR)test_proc, proc);
2340
2341     device = create_device(d3d8, focus_window, focus_window, FALSE);
2342     if (!device)
2343     {
2344         skip("Failed to create a D3D device, skipping tests.\n");
2345         goto done;
2346     }
2347
2348     ref = IDirect3DDevice8_Release(device);
2349     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2350
2351     device = create_device(d3d8, device_window, focus_window, FALSE);
2352     if (!device)
2353     {
2354         skip("Failed to create a D3D device, skipping tests.\n");
2355         goto done;
2356     }
2357
2358     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2359     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2360             (LONG_PTR)test_proc, proc);
2361
2362     ref = IDirect3DDevice8_Release(device);
2363     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2364
2365     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2366     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2367             (LONG_PTR)DefWindowProcA, proc);
2368
2369 done:
2370     filter_messages = NULL;
2371     IDirect3D8_Release(d3d8);
2372
2373     SetEvent(thread_params.test_finished);
2374     WaitForSingleObject(thread, INFINITE);
2375     CloseHandle(thread_params.test_finished);
2376     CloseHandle(thread_params.window_created);
2377     CloseHandle(thread);
2378
2379     DestroyWindow(device_window);
2380     DestroyWindow(focus_window);
2381     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2382 }
2383
2384 static void test_wndproc_windowed(void)
2385 {
2386     struct wndproc_thread_param thread_params;
2387     IDirect3DDevice8 *device;
2388     WNDCLASSA wc = {0};
2389     IDirect3D8 *d3d8;
2390     HANDLE thread;
2391     LONG_PTR proc;
2392     HRESULT hr;
2393     ULONG ref;
2394     DWORD res, tid;
2395     HWND tmp;
2396
2397     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2398     {
2399         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2400         return;
2401     }
2402
2403     wc.lpfnWndProc = test_proc;
2404     wc.lpszClassName = "d3d8_test_wndproc_wc";
2405     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2406
2407     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2408     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2409     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2410     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2411
2412     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2413             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2414     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2415             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2416     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2417     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2418
2419     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2420     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2421
2422     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2423     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2424             (LONG_PTR)test_proc, proc);
2425     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2426     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2427             (LONG_PTR)test_proc, proc);
2428
2429     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2430             device_window, focus_window, thread_params.dummy_window);
2431
2432     tmp = GetFocus();
2433     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2434     if (thread_params.running_in_foreground)
2435     {
2436         tmp = GetForegroundWindow();
2437         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2438                 thread_params.dummy_window, tmp);
2439     }
2440     else
2441         skip("Not running in foreground, skip foreground window test\n");
2442
2443     filter_messages = focus_window;
2444
2445     device = create_device(d3d8, device_window, focus_window, TRUE);
2446     if (!device)
2447     {
2448         skip("Failed to create a D3D device, skipping tests.\n");
2449         goto done;
2450     }
2451
2452     tmp = GetFocus();
2453     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2454     tmp = GetForegroundWindow();
2455     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2456             thread_params.dummy_window, tmp);
2457
2458     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2459     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2460             (LONG_PTR)test_proc, proc);
2461
2462     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2463     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2464             (LONG_PTR)test_proc, proc);
2465
2466     filter_messages = NULL;
2467
2468     hr = reset_device(device, device_window, FALSE);
2469     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2470
2471     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2472     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2473             (LONG_PTR)test_proc, proc);
2474
2475     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2476     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2477             (LONG_PTR)test_proc, proc);
2478
2479     hr = reset_device(device, device_window, TRUE);
2480     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2481
2482     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2483     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2484             (LONG_PTR)test_proc, proc);
2485
2486     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2487     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2488             (LONG_PTR)test_proc, proc);
2489
2490     filter_messages = focus_window;
2491
2492     ref = IDirect3DDevice8_Release(device);
2493     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2494
2495     filter_messages = device_window;
2496
2497     device = create_device(d3d8, focus_window, focus_window, TRUE);
2498     if (!device)
2499     {
2500         skip("Failed to create a D3D device, skipping tests.\n");
2501         goto done;
2502     }
2503
2504     filter_messages = NULL;
2505
2506     hr = reset_device(device, focus_window, FALSE);
2507     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2508
2509     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2510     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2511             (LONG_PTR)test_proc, proc);
2512
2513     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2514     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2515             (LONG_PTR)test_proc, proc);
2516
2517     hr = reset_device(device, focus_window, TRUE);
2518     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2519
2520     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2521     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2522             (LONG_PTR)test_proc, proc);
2523
2524     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2525     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2526             (LONG_PTR)test_proc, proc);
2527
2528     filter_messages = device_window;
2529
2530     ref = IDirect3DDevice8_Release(device);
2531     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2532
2533     device = create_device(d3d8, device_window, focus_window, TRUE);
2534     if (!device)
2535     {
2536         skip("Failed to create a D3D device, skipping tests.\n");
2537         goto done;
2538     }
2539
2540     filter_messages = NULL;
2541
2542     hr = reset_device(device, device_window, FALSE);
2543     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2544
2545     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2546     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2547             (LONG_PTR)test_proc, proc);
2548
2549     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2550     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2551             (LONG_PTR)test_proc, proc);
2552
2553     hr = reset_device(device, device_window, TRUE);
2554     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2555
2556     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2557     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2558             (LONG_PTR)test_proc, proc);
2559
2560     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2561     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2562             (LONG_PTR)test_proc, proc);
2563
2564     filter_messages = device_window;
2565
2566     ref = IDirect3DDevice8_Release(device);
2567     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2568
2569 done:
2570     filter_messages = NULL;
2571     IDirect3D8_Release(d3d8);
2572
2573     SetEvent(thread_params.test_finished);
2574     WaitForSingleObject(thread, INFINITE);
2575     CloseHandle(thread_params.test_finished);
2576     CloseHandle(thread_params.window_created);
2577     CloseHandle(thread);
2578
2579     DestroyWindow(device_window);
2580     DestroyWindow(focus_window);
2581     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2582 }
2583
2584 static inline void set_fpu_cw(WORD cw)
2585 {
2586 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2587 #define D3D8_TEST_SET_FPU_CW 1
2588     __asm__ volatile ("fnclex");
2589     __asm__ volatile ("fldcw %0" : : "m" (cw));
2590 #elif defined(__i386__) && defined(_MSC_VER)
2591 #define D3D8_TEST_SET_FPU_CW 1
2592     __asm fnclex;
2593     __asm fldcw cw;
2594 #endif
2595 }
2596
2597 static inline WORD get_fpu_cw(void)
2598 {
2599     WORD cw = 0;
2600 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2601 #define D3D8_TEST_GET_FPU_CW 1
2602     __asm__ volatile ("fnstcw %0" : "=m" (cw));
2603 #elif defined(__i386__) && defined(_MSC_VER)
2604 #define D3D8_TEST_GET_FPU_CW 1
2605     __asm fnstcw cw;
2606 #endif
2607     return cw;
2608 }
2609
2610 static void test_fpu_setup(void)
2611 {
2612 #if defined(D3D8_TEST_SET_FPU_CW) && defined(D3D8_TEST_GET_FPU_CW)
2613     D3DPRESENT_PARAMETERS present_parameters;
2614     IDirect3DDevice8 *device;
2615     D3DDISPLAYMODE d3ddm;
2616     HWND window = NULL;
2617     IDirect3D8 *d3d8;
2618     HRESULT hr;
2619     WORD cw;
2620
2621     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2622     ok(!!d3d8, "Failed to create a d3d8 object.\n");
2623     if (!d3d8) return;
2624
2625     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2626     ok(!!window, "Failed to create a window.\n");
2627     if (!window) goto done;
2628
2629     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
2630     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
2631
2632     memset(&present_parameters, 0, sizeof(present_parameters));
2633     present_parameters.Windowed = TRUE;
2634     present_parameters.hDeviceWindow = window;
2635     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2636     present_parameters.BackBufferFormat = d3ddm.Format;
2637
2638     set_fpu_cw(0xf60);
2639     cw = get_fpu_cw();
2640     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2641
2642     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2643             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
2644     if (FAILED(hr))
2645     {
2646         skip("Failed to create a device, hr %#x.\n", hr);
2647         set_fpu_cw(0x37f);
2648         goto done;
2649     }
2650
2651     cw = get_fpu_cw();
2652     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2653
2654     IDirect3DDevice8_Release(device);
2655
2656     cw = get_fpu_cw();
2657     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2658     set_fpu_cw(0xf60);
2659     cw = get_fpu_cw();
2660     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2661
2662     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2663             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
2664     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
2665
2666     cw = get_fpu_cw();
2667     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2668     set_fpu_cw(0x37f);
2669
2670     IDirect3DDevice8_Release(device);
2671
2672 done:
2673     if (window) DestroyWindow(window);
2674     if (d3d8) IDirect3D8_Release(d3d8);
2675 #endif
2676 }
2677
2678 static void test_ApplyStateBlock(void)
2679 {
2680     D3DPRESENT_PARAMETERS d3dpp;
2681     IDirect3DDevice8 *device = NULL;
2682     IDirect3D8 *d3d8;
2683     HWND hwnd;
2684     HRESULT hr;
2685     D3DDISPLAYMODE d3ddm;
2686     DWORD received, token;
2687
2688     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2689     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2690     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2691     ok(hwnd != NULL, "Failed to create window\n");
2692     if (!d3d8 || !hwnd) goto cleanup;
2693
2694     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
2695     ZeroMemory( &d3dpp, sizeof(d3dpp) );
2696     d3dpp.Windowed         = TRUE;
2697     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2698     d3dpp.BackBufferWidth  = 800;
2699     d3dpp.BackBufferHeight  = 600;
2700     d3dpp.BackBufferFormat = d3ddm.Format;
2701     d3dpp.EnableAutoDepthStencil = TRUE;
2702     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2703
2704     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2705                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
2706     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2707        "IDirect3D8_CreateDevice failed with %#x\n", hr);
2708     if(!device)
2709     {
2710         skip("Failed to create a d3d device\n");
2711         goto cleanup;
2712     }
2713
2714     IDirect3DDevice8_BeginStateBlock(device);
2715     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
2716     IDirect3DDevice8_EndStateBlock(device, &token);
2717     ok(token, "Received zero stateblock handle.\n");
2718     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
2719
2720     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2721     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2722     ok(!received, "Expected = FALSE, received TRUE.\n");
2723
2724     hr = IDirect3DDevice8_ApplyStateBlock(device, 0);
2725     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2726     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2727     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2728     ok(!received, "Expected FALSE, received TRUE.\n");
2729
2730     hr = IDirect3DDevice8_ApplyStateBlock(device, token);
2731     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2732     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2733     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2734     ok(received, "Expected TRUE, received FALSE.\n");
2735
2736     IDirect3DDevice8_DeleteStateBlock(device, token);
2737     IDirect3DDevice8_Release(device);
2738 cleanup:
2739     if (d3d8) IDirect3D8_Release(d3d8);
2740     DestroyWindow(hwnd);
2741 }
2742
2743 static void test_depth_stencil_size(void)
2744 {
2745     IDirect3DDevice8 *device;
2746     IDirect3DSurface8 *ds, *rt, *ds_bigger, *ds_bigger2;
2747     IDirect3DSurface8 *surf;
2748     IDirect3D8 *d3d8;
2749     HRESULT hr;
2750     HWND hwnd;
2751
2752     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2753     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2754     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2755     ok(hwnd != NULL, "Failed to create window\n");
2756     if (!d3d8 || !hwnd) goto cleanup;
2757
2758     device = create_device(d3d8, hwnd, hwnd, TRUE);
2759     if (!device) goto cleanup;
2760
2761     hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
2762     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateRenderTarget failed, hr %#x.\n", hr);
2763     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds);
2764     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2765     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger);
2766     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2767     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger2);
2768     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2769
2770     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2771     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2772     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds_bigger);
2773     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2774
2775     /* try to set the small ds without changing the render target at the same time */
2776     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds);
2777     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2778     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds_bigger2);
2779     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2780
2781     hr = IDirect3DDevice8_GetRenderTarget(device, &surf);
2782     ok(hr == D3D_OK, "IDirect3DDevice8_GetRenderTarget failed, hr %#x.\n", hr);
2783     ok(surf == rt, "The render target is %p, expected %p\n", surf, rt);
2784     IDirect3DSurface8_Release(surf);
2785     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2786     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr %#x.\n", hr);
2787     ok(surf == ds_bigger2, "The depth stencil is %p, expected %p\n", surf, ds_bigger2);
2788     IDirect3DSurface8_Release(surf);
2789
2790     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2791     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2792     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2793     ok(FAILED(hr), "IDirect3DDevice8_GetDepthStencilSurface should have failed, hr %#x.\n", hr);
2794     ok(surf == NULL, "The depth stencil is %p, expected NULL\n", surf);
2795     if (surf) IDirect3DSurface8_Release(surf);
2796
2797     IDirect3DSurface8_Release(rt);
2798     IDirect3DSurface8_Release(ds);
2799     IDirect3DSurface8_Release(ds_bigger);
2800     IDirect3DSurface8_Release(ds_bigger2);
2801
2802 cleanup:
2803     if (d3d8) IDirect3D8_Release(d3d8);
2804     DestroyWindow(hwnd);
2805 }
2806
2807 static void test_window_style(void)
2808 {
2809     RECT focus_rect, fullscreen_rect, r;
2810     LONG device_style, device_exstyle;
2811     LONG focus_style, focus_exstyle;
2812     LONG style, expected_style;
2813     IDirect3DDevice8 *device;
2814     IDirect3D8 *d3d8;
2815     ULONG ref;
2816
2817
2818     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2819     {
2820         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2821         return;
2822     }
2823
2824     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2825             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2826     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2827             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2828
2829     device_style = GetWindowLongA(device_window, GWL_STYLE);
2830     device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
2831     focus_style = GetWindowLongA(focus_window, GWL_STYLE);
2832     focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
2833
2834     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
2835     GetWindowRect(focus_window, &focus_rect);
2836
2837     device = create_device(d3d8, device_window, focus_window, FALSE);
2838     if (!device)
2839     {
2840         skip("Failed to create a D3D device, skipping tests.\n");
2841         goto done;
2842     }
2843
2844     style = GetWindowLongA(device_window, GWL_STYLE);
2845     expected_style = device_style | WS_VISIBLE;
2846     todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
2847             expected_style, style);
2848     style = GetWindowLongA(device_window, GWL_EXSTYLE);
2849     expected_style = device_exstyle | WS_EX_TOPMOST;
2850     todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
2851             expected_style, style);
2852
2853     style = GetWindowLongA(focus_window, GWL_STYLE);
2854     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
2855             focus_style, style);
2856     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
2857     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
2858             focus_exstyle, style);
2859
2860     GetWindowRect(device_window, &r);
2861     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2862             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2863             r.left, r.top, r.right, r.bottom);
2864     GetClientRect(device_window, &r);
2865     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2866     GetWindowRect(focus_window, &r);
2867     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2868             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
2869             r.left, r.top, r.right, r.bottom);
2870
2871     ref = IDirect3DDevice8_Release(device);
2872     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2873
2874 done:
2875     IDirect3D8_Release(d3d8);
2876
2877     DestroyWindow(device_window);
2878     DestroyWindow(focus_window);
2879 }
2880
2881 static void test_wrong_shader(void)
2882 {
2883     HRESULT hr;
2884     HWND hwnd = NULL;
2885     IDirect3D8 *d3d = NULL;
2886     IDirect3DDevice8 *device = NULL;
2887     D3DPRESENT_PARAMETERS d3dpp;
2888     D3DDISPLAYMODE d3ddm;
2889     DWORD vs, ps;
2890
2891     static const DWORD vs_2_0[] =
2892     {
2893         0xfffe0200,                                         /* vs_2_0           */
2894         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
2895         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2896         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
2897         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
2898         0x0000ffff                                          /* end              */
2899     };
2900     static const DWORD ps_2_0[] =
2901     {
2902         0xffff0200,                                         /* ps_2_0           */
2903         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2904         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
2905         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
2906         0x0000ffff                                          /* end              */
2907     };
2908
2909     static const DWORD decl[] =
2910     {
2911         D3DVSD_STREAM(0),
2912         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
2913         D3DVSD_END()
2914     };
2915
2916     d3d = pDirect3DCreate8(D3D_SDK_VERSION);
2917     ok(d3d != NULL, "Failed to create IDirect3D8 object\n");
2918     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2919     ok(hwnd != NULL, "Failed to create window\n");
2920     if (!d3d || !hwnd)
2921         goto cleanup;
2922
2923     IDirect3D8_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2924     ZeroMemory(&d3dpp, sizeof(d3dpp));
2925     d3dpp.Windowed = TRUE;
2926     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2927     d3dpp.BackBufferWidth = 800;
2928     d3dpp.BackBufferHeight = 600;
2929     d3dpp.BackBufferFormat = d3ddm.Format;
2930
2931     hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2932             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
2933     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
2934     if (!device)
2935     {
2936         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
2937         goto cleanup;
2938     }
2939
2940     hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_ps, &vs, 0);
2941     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2942
2943     hr = IDirect3DDevice8_CreatePixelShader(device, simple_vs, &ps);
2944     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2945
2946     hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_2_0, &vs, 0);
2947     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2948
2949     hr = IDirect3DDevice8_CreatePixelShader(device, ps_2_0, &ps);
2950     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2951
2952 cleanup:
2953     if (device)
2954     {
2955         UINT refcount = IDirect3DDevice8_Release(device);
2956         ok(!refcount, "Device has %u references left.\n", refcount);
2957     }
2958     if (d3d)
2959         IDirect3D8_Release(d3d);
2960     DestroyWindow(hwnd);
2961 }
2962
2963 static void test_mode_change(void)
2964 {
2965     RECT fullscreen_rect, focus_rect, r;
2966     IDirect3DSurface8 *backbuffer;
2967     IDirect3DDevice8 *device;
2968     D3DSURFACE_DESC desc;
2969     IDirect3D8 *d3d8;
2970     DEVMODEW devmode;
2971     UINT refcount;
2972     HRESULT hr;
2973     DWORD ret;
2974
2975     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2976     {
2977         skip("Failed to create IDirect3D8 object, skipping mode change tests.\n");
2978         return;
2979     }
2980
2981     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2982             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2983     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2984             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2985
2986     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
2987     GetWindowRect(focus_window, &focus_rect);
2988
2989     device = create_device(d3d8, device_window, focus_window, FALSE);
2990     if (!device)
2991     {
2992         skip("Failed to create a D3D device, skipping tests.\n");
2993         goto done;
2994     }
2995
2996     memset(&devmode, 0, sizeof(devmode));
2997     devmode.dmSize = sizeof(devmode);
2998     devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2999     devmode.dmPelsWidth = 640;
3000     devmode.dmPelsHeight = 480;
3001
3002     ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3003     ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3004
3005     memset(&devmode, 0, sizeof(devmode));
3006     devmode.dmSize = sizeof(devmode);
3007     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3008     ok(ret, "Failed to get display mode.\n");
3009     ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3010     ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3011
3012     GetWindowRect(device_window, &r);
3013     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3014             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3015             r.left, r.top, r.right, r.bottom);
3016     GetWindowRect(focus_window, &r);
3017     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3018             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3019             r.left, r.top, r.right, r.bottom);
3020
3021     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3022     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3023     hr = IDirect3DSurface8_GetDesc(backbuffer, &desc);
3024     ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3025     ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3026     ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3027     IDirect3DSurface8_Release(backbuffer);
3028
3029     refcount = IDirect3DDevice8_Release(device);
3030     ok(!refcount, "Device has %u references left.\n", refcount);
3031
3032     memset(&devmode, 0, sizeof(devmode));
3033     devmode.dmSize = sizeof(devmode);
3034     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3035     ok(ret, "Failed to get display mode.\n");
3036     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3037     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3038
3039 done:
3040     DestroyWindow(device_window);
3041     DestroyWindow(focus_window);
3042     if (d3d8)
3043         IDirect3D8_Release(d3d8);
3044
3045     memset(&devmode, 0, sizeof(devmode));
3046     devmode.dmSize = sizeof(devmode);
3047     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3048     ok(ret, "Failed to get display mode.\n");
3049     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3050     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3051 }
3052
3053 static void test_device_window_reset(void)
3054 {
3055     RECT fullscreen_rect, device_rect, r;
3056     IDirect3DDevice8 *device;
3057     WNDCLASSA wc = {0};
3058     IDirect3D8 *d3d8;
3059     LONG_PTR proc;
3060     HRESULT hr;
3061     ULONG ref;
3062
3063     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3064     {
3065         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3066         return;
3067     }
3068
3069     wc.lpfnWndProc = test_proc;
3070     wc.lpszClassName = "d3d8_test_wndproc_wc";
3071     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3072
3073     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3074             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3075     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3076             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3077
3078     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3079     GetWindowRect(device_window, &device_rect);
3080
3081     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3082     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3083             (LONG_PTR)test_proc, proc);
3084     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3085     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3086             (LONG_PTR)test_proc, proc);
3087
3088     device = create_device(d3d8, NULL, focus_window, FALSE);
3089     if (!device)
3090     {
3091         skip("Failed to create a D3D device, skipping tests.\n");
3092         goto done;
3093     }
3094
3095     GetWindowRect(focus_window, &r);
3096     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3097             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3098             r.left, r.top, r.right, r.bottom);
3099     GetWindowRect(device_window, &r);
3100     ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3101             device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3102             r.left, r.top, r.right, r.bottom);
3103
3104     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3105     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3106             (LONG_PTR)test_proc, proc);
3107     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3108     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3109             (LONG_PTR)test_proc, proc);
3110
3111     hr = reset_device(device, device_window, FALSE);
3112     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3113
3114     GetWindowRect(focus_window, &r);
3115     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3116             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3117             r.left, r.top, r.right, r.bottom);
3118     GetWindowRect(device_window, &r);
3119     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3120             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3121             r.left, r.top, r.right, r.bottom);
3122
3123     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3124     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3125             (LONG_PTR)test_proc, proc);
3126     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3127     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3128             (LONG_PTR)test_proc, proc);
3129
3130     ref = IDirect3DDevice8_Release(device);
3131     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3132
3133 done:
3134     IDirect3D8_Release(d3d8);
3135     DestroyWindow(device_window);
3136     DestroyWindow(focus_window);
3137     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3138 }
3139
3140 static void depth_blit_test(void)
3141 {
3142     HWND hwnd = NULL;
3143     IDirect3D8 *d3d8 = NULL;
3144     IDirect3DDevice8 *device = NULL;
3145     IDirect3DSurface8 *backbuffer, *ds1, *ds2, *ds3;
3146     RECT src_rect;
3147     const POINT dst_point = {0, 0};
3148     HRESULT hr;
3149
3150     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
3151     ok(d3d8 != NULL, "Direct3DCreate8 failed.\n");
3152     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
3153     ok(hwnd != NULL, "CreateWindow failed.\n");
3154     if (!d3d8 || !hwnd)
3155         goto done;
3156
3157     device = create_device(d3d8, hwnd, hwnd, TRUE);
3158     if (!device)
3159     {
3160         skip("Failed to create a D3D device, skipping tests.\n");
3161         goto done;
3162     }
3163
3164     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
3165     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
3166     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds1);
3167     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
3168     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds2);
3169     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3170     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds3);
3171     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3172
3173     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
3174     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
3175
3176     /* Partial blit. */
3177     SetRect(&src_rect, 0, 0, 320, 240);
3178     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3179     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3180     /* Flipped. */
3181     SetRect(&src_rect, 0, 480, 640, 0);
3182     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3183     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3184     /* Full, explicit. */
3185     SetRect(&src_rect, 0, 0, 640, 480);
3186     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3187     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3188     /* Depth -> color blit.*/
3189     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, backbuffer, &dst_point);
3190     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3191     /* Full, NULL rects, current depth stencil -> unbound depth stencil */
3192     hr = IDirect3DDevice8_CopyRects(device, ds1, NULL, 0, ds2, NULL);
3193     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3194     /* Full, NULL rects, unbound depth stencil -> current depth stencil */
3195     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds1, NULL);
3196     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3197     /* Full, NULL rects, unbound depth stencil -> unbound depth stencil */
3198     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds3, NULL);
3199     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3200
3201     IDirect3DSurface8_Release(backbuffer);
3202     IDirect3DSurface8_Release(ds3);
3203     IDirect3DSurface8_Release(ds2);
3204     IDirect3DSurface8_Release(ds1);
3205
3206 done:
3207     if (device) IDirect3DDevice8_Release(device);
3208     if (d3d8) IDirect3D8_Release(d3d8);
3209     if (hwnd) DestroyWindow(hwnd);
3210 }
3211
3212 static void test_reset_resources(void)
3213 {
3214     IDirect3DSurface8 *surface, *rt;
3215     IDirect3DTexture8 *texture;
3216     IDirect3DDevice8 *device;
3217     IDirect3D8 *d3d8;
3218     HWND window;
3219     HRESULT hr;
3220     ULONG ref;
3221
3222     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
3223             0, 0, 640, 480, 0, 0, 0, 0);
3224
3225     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3226     {
3227         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3228         DestroyWindow(window);
3229         return;
3230     }
3231
3232     if (!(device = create_device(d3d8, window, window, TRUE)))
3233     {
3234         skip("Failed to create a D3D device, skipping tests.\n");
3235         goto done;
3236     }
3237
3238     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_DEPTHSTENCIL,
3239             D3DFMT_D24S8, D3DPOOL_DEFAULT, &texture);
3240     ok(SUCCEEDED(hr), "Failed to create depth/stencil texture, hr %#x.\n", hr);
3241     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
3242     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3243     IDirect3DTexture8_Release(texture);
3244
3245     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3246             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3247     ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr);
3248     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &rt);
3249     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3250     IDirect3DTexture8_Release(texture);
3251
3252     hr = IDirect3DDevice8_SetRenderTarget(device, rt, surface);
3253     ok(SUCCEEDED(hr), "Failed to set render target surface, hr %#x.\n", hr);
3254     IDirect3DSurface8_Release(rt);
3255     IDirect3DSurface8_Release(surface);
3256
3257     hr = reset_device(device, device_window, TRUE);
3258     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3259
3260     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3261     ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3262     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3263     ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3264     ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3265     IDirect3DSurface8_Release(surface);
3266     IDirect3DSurface8_Release(rt);
3267
3268     ref = IDirect3DDevice8_Release(device);
3269     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3270
3271 done:
3272     IDirect3D8_Release(d3d8);
3273     DestroyWindow(window);
3274 }
3275
3276 START_TEST(device)
3277 {
3278     HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
3279     WNDCLASS wc = {0};
3280     if (!d3d8_handle)
3281     {
3282         skip("Could not load d3d8.dll\n");
3283         return;
3284     }
3285
3286     wc.lpfnWndProc = DefWindowProc;
3287     wc.lpszClassName = "d3d8_test_wc";
3288     RegisterClass(&wc);
3289
3290     pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
3291     ok(pDirect3DCreate8 != NULL, "Failed to get address of Direct3DCreate8\n");
3292     if (pDirect3DCreate8)
3293     {
3294         IDirect3D8 *d3d8;
3295         d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
3296         if(!d3d8)
3297         {
3298             skip("could not create D3D8\n");
3299             return;
3300         }
3301         IDirect3D8_Release(d3d8);
3302
3303         screen_width = GetSystemMetrics(SM_CXSCREEN);
3304         screen_height = GetSystemMetrics(SM_CYSCREEN);
3305
3306         test_fpu_setup();
3307         test_display_modes();
3308         test_shader_versions();
3309         test_swapchain();
3310         test_refcount();
3311         test_mipmap_levels();
3312         test_cursor();
3313         test_cursor_pos();
3314         test_states();
3315         test_reset();
3316         test_scene();
3317         test_shader();
3318         test_limits();
3319         test_lights();
3320         test_ApplyStateBlock();
3321         test_render_zero_triangles();
3322         test_depth_stencil_reset();
3323         test_wndproc();
3324         test_wndproc_windowed();
3325         test_depth_stencil_size();
3326         test_window_style();
3327         test_wrong_shader();
3328         test_mode_change();
3329         test_device_window_reset();
3330         test_reset_resources();
3331         depth_blit_test();
3332     }
3333     UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));
3334 }