include: Assorted spelling fixes.
[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     DWORD value;
1026     HRESULT hr;
1027     UINT i;
1028
1029     static const DWORD decl[] =
1030     {
1031         D3DVSD_STREAM(0),
1032         D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT4),
1033         D3DVSD_END(),
1034     };
1035
1036     struct
1037     {
1038         UINT w;
1039         UINT h;
1040     } *modes = NULL;
1041
1042     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
1043     ok(!!d3d8, "Failed to create IDirect3D8 object.\n");
1044     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1045             100, 100, 160, 160, NULL, NULL, NULL, NULL);
1046     ok(!!window, "Failed to create window.\n");
1047     if (!d3d8 || !window)
1048         goto cleanup;
1049
1050     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1051     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1052     adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
1053     modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1054     for (i = 0; i < adapter_mode_count; ++i)
1055     {
1056         UINT j;
1057
1058         memset(&d3ddm2, 0, sizeof(d3ddm2));
1059         hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm2);
1060         ok(SUCCEEDED(hr), "EnumAdapterModes failed, hr %#x.\n", hr);
1061
1062         if (d3ddm2.Format != d3ddm.Format)
1063             continue;
1064
1065         for (j = 0; j < mode_count; ++j)
1066         {
1067             if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1068                 break;
1069         }
1070         if (j == mode_count)
1071         {
1072             modes[j].w = d3ddm2.Width;
1073             modes[j].h = d3ddm2.Height;
1074             ++mode_count;
1075         }
1076
1077         /* We use them as invalid modes. */
1078         if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
1079                 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
1080         {
1081             skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
1082                     d3ddm2.Width, d3ddm2.Height);
1083             goto cleanup;
1084         }
1085     }
1086
1087     if (mode_count < 2)
1088     {
1089         skip("Less than 2 modes supported, skipping mode tests.\n");
1090         goto cleanup;
1091     }
1092
1093     i = 0;
1094     if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1095
1096     memset(&d3dpp, 0, sizeof(d3dpp));
1097     d3dpp.Windowed = FALSE;
1098     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1099     d3dpp.BackBufferWidth = modes[i].w;
1100     d3dpp.BackBufferHeight = modes[i].h;
1101     d3dpp.BackBufferFormat = d3ddm.Format;
1102     d3dpp.EnableAutoDepthStencil = TRUE;
1103     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1104
1105     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1106             window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
1107     if (FAILED(hr))
1108     {
1109         skip("Failed to create device, hr %#x.\n", hr);
1110         goto cleanup;
1111     }
1112     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1113     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1114
1115     hr = IDirect3DDevice8_GetDeviceCaps(device1, &caps);
1116     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1117
1118     width = GetSystemMetrics(SM_CXSCREEN);
1119     height = GetSystemMetrics(SM_CYSCREEN);
1120     ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1121     ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1122
1123     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1124     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1125     if (SUCCEEDED(hr))
1126     {
1127         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1128         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1129         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1130         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1131         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1132         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1133     }
1134
1135     i = 1;
1136     vp.X = 10;
1137     vp.Y = 20;
1138     vp.Width = modes[i].w  / 2;
1139     vp.Height = modes[i].h / 2;
1140     vp.MinZ = 0.2f;
1141     vp.MaxZ = 0.3f;
1142     hr = IDirect3DDevice8_SetViewport(device1, &vp);
1143     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1144
1145     hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1146     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1147     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1148     hr = IDirect3DDevice8_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1149     ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1150
1151     memset(&d3dpp, 0, sizeof(d3dpp));
1152     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1153     d3dpp.Windowed = FALSE;
1154     d3dpp.BackBufferWidth = modes[i].w;
1155     d3dpp.BackBufferHeight = modes[i].h;
1156     d3dpp.BackBufferFormat = d3ddm.Format;
1157     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1158     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1159     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1160     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1161
1162     hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1163     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1164     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1165
1166     memset(&vp, 0, sizeof(vp));
1167     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1168     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1169     if (SUCCEEDED(hr))
1170     {
1171         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1172         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1173         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1174         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1175         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1176         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1177     }
1178
1179     width = GetSystemMetrics(SM_CXSCREEN);
1180     height = GetSystemMetrics(SM_CYSCREEN);
1181     ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1182     ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1183
1184     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1185     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1186     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1187     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1188     ok(surface_desc.Width == modes[i].w, "Back buffer width is %u, expected %u.\n",
1189             surface_desc.Width, modes[i].w);
1190     ok(surface_desc.Height == modes[i].h, "Back buffer height is %u, expected %u.\n",
1191             surface_desc.Height, modes[i].h);
1192     IDirect3DSurface8_Release(surface);
1193
1194     memset(&d3dpp, 0, sizeof(d3dpp));
1195     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1196     d3dpp.Windowed = TRUE;
1197     d3dpp.BackBufferWidth = 400;
1198     d3dpp.BackBufferHeight = 300;
1199     d3dpp.BackBufferFormat = d3ddm.Format;
1200     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1201     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1202     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1203     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1204
1205     memset(&vp, 0, sizeof(vp));
1206     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1207     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1208     if (SUCCEEDED(hr))
1209     {
1210         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1211         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1212         ok(vp.Width == 400, "D3DVIEWPORT->Width = %u, expected 400.\n", vp.Width);
1213         ok(vp.Height == 300, "D3DVIEWPORT->Height = %u, expected 300.\n", vp.Height);
1214         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1215         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1216     }
1217
1218     width = GetSystemMetrics(SM_CXSCREEN);
1219     height = GetSystemMetrics(SM_CYSCREEN);
1220     ok(width == orig_width, "Screen width is %u, expected %u.\n", width, orig_width);
1221     ok(height == orig_height, "Screen height is %u, expected %u.\n", height, orig_height);
1222
1223     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1224     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1225     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1226     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1227     ok(surface_desc.Width == 400, "Back buffer width is %u, expected 400.\n",
1228             surface_desc.Width);
1229     ok(surface_desc.Height == 300, "Back buffer height is %u, expected 300.\n",
1230             surface_desc.Height);
1231     IDirect3DSurface8_Release(surface);
1232
1233     winrect.left = 0;
1234     winrect.top = 0;
1235     winrect.right = 200;
1236     winrect.bottom = 150;
1237     ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1238     ok(SetWindowPos(window, NULL, 0, 0,
1239                     winrect.right-winrect.left,
1240                     winrect.bottom-winrect.top,
1241                     SWP_NOMOVE|SWP_NOZORDER),
1242        "SetWindowPos failed\n");
1243
1244     memset(&d3dpp, 0, sizeof(d3dpp));
1245     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1246     d3dpp.Windowed = TRUE;
1247     d3dpp.BackBufferWidth = 0;
1248     d3dpp.BackBufferHeight = 0;
1249     d3dpp.BackBufferFormat = d3ddm.Format;
1250     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1251     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1252     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1253     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1254
1255     memset(&vp, 0, sizeof(vp));
1256     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1257     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1258     if (SUCCEEDED(hr))
1259     {
1260         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1261         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1262         todo_wine ok(vp.Width == 200, "D3DVIEWPORT->Width = %u, expected 200.\n", vp.Width);
1263         todo_wine ok(vp.Height == 150, "D3DVIEWPORT->Height = %u, expected 150.\n", vp.Height);
1264         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1265         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1266     }
1267
1268     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1269     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1270     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1271     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1272     todo_wine ok(surface_desc.Width == 200, "Back buffer width is %u, expected 200.\n",
1273                  surface_desc.Width);
1274     todo_wine ok(surface_desc.Height == 150, "Back buffer height is %u, expected 150.\n",
1275                  surface_desc.Height);
1276     IDirect3DSurface8_Release(surface);
1277
1278     memset(&d3dpp, 0, sizeof(d3dpp));
1279     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1280     d3dpp.Windowed = TRUE;
1281     d3dpp.BackBufferWidth = 400;
1282     d3dpp.BackBufferHeight = 300;
1283     d3dpp.BackBufferFormat = d3ddm.Format;
1284
1285     /* Reset fails if there is a resource in the default pool. */
1286     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texture);
1287     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1288     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1289     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1290     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1291     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1292     IDirect3DTexture8_Release(texture);
1293     /* Reset again to get the device out of the lost state. */
1294     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1295     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1296     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1297     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1298
1299     if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1300     {
1301         IDirect3DVolumeTexture8 *volume_texture;
1302
1303         hr = IDirect3DDevice8_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1304                 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture);
1305         ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1306         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1307         ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1308         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1309         ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1310                 hr, D3DERR_DEVICENOTRESET);
1311         IDirect3DVolumeTexture8_Release(volume_texture);
1312         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1313         ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1314         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1315         ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1316     }
1317     else
1318     {
1319         skip("Volume textures not supported.\n");
1320     }
1321
1322     /* Scratch, sysmem and managed pool resources are fine. */
1323     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1324     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1325     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1326     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1327     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1328     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1329     IDirect3DTexture8_Release(texture);
1330
1331     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1332     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1333     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1334     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1335     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1336     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1337     IDirect3DTexture8_Release(texture);
1338
1339     /* The depth stencil should get reset to the auto depth stencil when present. */
1340     hr = IDirect3DDevice8_SetRenderTarget(device1, NULL, NULL);
1341     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1342
1343     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1344     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1345     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1346
1347     d3dpp.EnableAutoDepthStencil = TRUE;
1348     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1349     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1350     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1351
1352     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1353     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1354     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1355     if (surface) IDirect3DSurface8_Release(surface);
1356
1357     d3dpp.EnableAutoDepthStencil = FALSE;
1358     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1359     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1360
1361     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1362     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1363     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1364
1365     /* Will a sysmem or scratch resource survive while locked? */
1366     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &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_SCRATCH, &texture);
1378     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1379     hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1380     ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1381     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1382     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1383     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1384     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1385     IDirect3DTexture8_UnlockRect(texture, 0);
1386     IDirect3DTexture8_Release(texture);
1387
1388     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture);
1389     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1390     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1391     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1392     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1393     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1394     IDirect3DTexture8_Release(texture);
1395
1396     /* A reference held to an implicit surface causes failures as well. */
1397     hr = IDirect3DDevice8_GetBackBuffer(device1, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1398     ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
1399     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1400     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1401     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1402     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1403     IDirect3DSurface8_Release(surface);
1404     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1405     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1406     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1407     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1408
1409     /* Shaders are fine as well. */
1410     hr = IDirect3DDevice8_CreateVertexShader(device1, decl, simple_vs, &shader, 0);
1411     ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
1412     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1413     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1414     hr = IDirect3DDevice8_DeleteVertexShader(device1, shader);
1415     ok(SUCCEEDED(hr), "DeleteVertexShader failed, hr %#x.\n", hr);
1416
1417     /* Try setting invalid modes. */
1418     memset(&d3dpp, 0, sizeof(d3dpp));
1419     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1420     d3dpp.Windowed = FALSE;
1421     d3dpp.BackBufferWidth = 32;
1422     d3dpp.BackBufferHeight = 32;
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     memset(&d3dpp, 0, sizeof(d3dpp));
1430     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1431     d3dpp.Windowed = FALSE;
1432     d3dpp.BackBufferWidth = 801;
1433     d3dpp.BackBufferHeight = 600;
1434     d3dpp.BackBufferFormat = d3ddm.Format;
1435     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1436     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1437     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1438     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1439
1440     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1441     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1442
1443     memset(&d3dpp, 0, sizeof(d3dpp));
1444     d3dpp.Windowed = TRUE;
1445     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1446     d3dpp.BackBufferFormat = d3ddm.Format;
1447     d3dpp.EnableAutoDepthStencil = FALSE;
1448     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1449
1450     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1451             window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1452     if (FAILED(hr))
1453     {
1454         skip("Failed to create device, hr %#x.\n", hr);
1455         goto cleanup;
1456     }
1457
1458     hr = IDirect3DDevice8_TestCooperativeLevel(device2);
1459     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1460
1461     d3dpp.Windowed = TRUE;
1462     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1463     d3dpp.BackBufferWidth = 400;
1464     d3dpp.BackBufferHeight = 300;
1465     d3dpp.BackBufferFormat = d3ddm.Format;
1466     d3dpp.EnableAutoDepthStencil = TRUE;
1467     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1468
1469     hr = IDirect3DDevice8_Reset(device2, &d3dpp);
1470     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1471     if (FAILED(hr))
1472         goto cleanup;
1473
1474     hr = IDirect3DDevice8_GetDepthStencilSurface(device2, &surface);
1475     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1476     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1477     if (surface)
1478         IDirect3DSurface8_Release(surface);
1479
1480 cleanup:
1481     HeapFree(GetProcessHeap(), 0, modes);
1482     if (device2)
1483         IDirect3DDevice8_Release(device2);
1484     if (device1)
1485         IDirect3DDevice8_Release(device1);
1486     if (d3d8)
1487         IDirect3D8_Release(d3d8);
1488     if (window)
1489         DestroyWindow(window);
1490 }
1491
1492 static void test_scene(void)
1493 {
1494     HRESULT                      hr;
1495     HWND                         hwnd               = NULL;
1496     IDirect3D8                  *pD3d               = NULL;
1497     IDirect3DDevice8            *pDevice            = NULL;
1498     D3DPRESENT_PARAMETERS        d3dpp;
1499     D3DDISPLAYMODE               d3ddm;
1500
1501     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1502     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1503     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1504     ok(hwnd != NULL, "Failed to create window\n");
1505     if (!pD3d || !hwnd) goto cleanup;
1506
1507     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1508     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1509     d3dpp.Windowed         = TRUE;
1510     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1511     d3dpp.BackBufferWidth  = 800;
1512     d3dpp.BackBufferHeight = 600;
1513     d3dpp.BackBufferFormat = d3ddm.Format;
1514
1515
1516     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1517                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1518     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1519     if(!pDevice)
1520     {
1521         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1522         goto cleanup;
1523     }
1524
1525     /* Test an EndScene without BeginScene. Should return an error */
1526     hr = IDirect3DDevice8_EndScene(pDevice);
1527     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1528
1529     /* Test a normal BeginScene / EndScene pair, this should work */
1530     hr = IDirect3DDevice8_BeginScene(pDevice);
1531     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1532     if(SUCCEEDED(hr))
1533     {
1534         hr = IDirect3DDevice8_EndScene(pDevice);
1535         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1536     }
1537
1538     /* Test another EndScene without having begun a new scene. Should return an error */
1539     hr = IDirect3DDevice8_EndScene(pDevice);
1540     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1541
1542     /* Two nested BeginScene and EndScene calls */
1543     hr = IDirect3DDevice8_BeginScene(pDevice);
1544     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1545     hr = IDirect3DDevice8_BeginScene(pDevice);
1546     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1547     hr = IDirect3DDevice8_EndScene(pDevice);
1548     ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1549     hr = IDirect3DDevice8_EndScene(pDevice);
1550     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1551
1552     /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
1553
1554 cleanup:
1555     if (pDevice)
1556     {
1557         UINT refcount = IDirect3DDevice8_Release(pDevice);
1558         ok(!refcount, "Device has %u references left.\n", refcount);
1559     }
1560     if (pD3d) IDirect3D8_Release(pD3d);
1561     DestroyWindow(hwnd);
1562 }
1563
1564 static void test_shader(void)
1565 {
1566     HRESULT                      hr;
1567     HWND                         hwnd               = NULL;
1568     IDirect3D8                  *pD3d               = NULL;
1569     IDirect3DDevice8            *pDevice            = NULL;
1570     D3DPRESENT_PARAMETERS        d3dpp;
1571     D3DDISPLAYMODE               d3ddm;
1572     DWORD                        hPixelShader = 0, hVertexShader = 0;
1573     DWORD                        hPixelShader2 = 0, hVertexShader2 = 0;
1574     DWORD                        hTempHandle;
1575     D3DCAPS8                     caps;
1576     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
1577     DWORD data_size;
1578     void *data;
1579
1580     static DWORD dwVertexDecl[] =
1581     {
1582         D3DVSD_STREAM(0),
1583         D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT3),
1584         D3DVSD_END()
1585     };
1586     DWORD decl_normal_float2[] =
1587     {
1588         D3DVSD_STREAM(0),
1589         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1590         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT2),  /* D3DVSDE_NORMAL,   Register v1 */
1591         D3DVSD_END()
1592     };
1593     DWORD decl_normal_float4[] =
1594     {
1595         D3DVSD_STREAM(0),
1596         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1597         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT4),  /* D3DVSDE_NORMAL,   Register v1 */
1598         D3DVSD_END()
1599     };
1600     DWORD decl_normal_d3dcolor[] =
1601     {
1602         D3DVSD_STREAM(0),
1603         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1604         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL,   Register v1 */
1605         D3DVSD_END()
1606     };
1607     const DWORD vertex_decl_size = sizeof(dwVertexDecl);
1608     const DWORD simple_vs_size = sizeof(simple_vs);
1609     const DWORD simple_ps_size = sizeof(simple_ps);
1610
1611     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1612     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1613     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1614     ok(hwnd != NULL, "Failed to create window\n");
1615     if (!pD3d || !hwnd) goto cleanup;
1616
1617     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1618     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1619     d3dpp.Windowed         = TRUE;
1620     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1621     d3dpp.BackBufferWidth  = 800;
1622     d3dpp.BackBufferHeight = 600;
1623     d3dpp.BackBufferFormat = d3ddm.Format;
1624
1625
1626     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1627                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1628     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1629     if(!pDevice)
1630     {
1631         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1632         goto cleanup;
1633     }
1634     IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
1635
1636     /* Test setting and retrieving a FVF */
1637     hr = IDirect3DDevice8_SetVertexShader(pDevice, fvf);
1638     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1639     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1640     ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1641     ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
1642
1643     /* First create a vertex shader */
1644     hr = IDirect3DDevice8_SetVertexShader(pDevice, 0);
1645     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1646     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, simple_vs, &hVertexShader, 0);
1647     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1648     /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
1649     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1650     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1651     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1652     /* Assign the shader, then verify that GetVertexShader works */
1653     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1654     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1655     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1656     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1657     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1658     /* Verify that we can retrieve the declaration */
1659     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, NULL, &data_size);
1660     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1661     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1662     data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
1663     data_size = 1;
1664     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1665     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
1666             "expected D3DERR_INVALIDCALL\n", hr);
1667     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1668     data_size = vertex_decl_size;
1669     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1670     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1671     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1672     ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
1673     HeapFree(GetProcessHeap(), 0, data);
1674     /* Verify that we can retrieve the shader function */
1675     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, NULL, &data_size);
1676     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1677     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1678     data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
1679     data_size = 1;
1680     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1681     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
1682             "expected D3DERR_INVALIDCALL\n", hr);
1683     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1684     data_size = simple_vs_size;
1685     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1686     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1687     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1688     ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
1689     HeapFree(GetProcessHeap(), 0, data);
1690     /* Delete the assigned shader. This is supposed to work */
1691     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1692     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1693     /* The shader should be unset now */
1694     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1695     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1696     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1697
1698     /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
1699      * First try the fixed function shader function, then a custom one
1700      */
1701     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, 0, &hVertexShader, 0);
1702     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1703     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1704     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float4, 0, &hVertexShader, 0);
1705     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1706     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1707     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_d3dcolor, 0, &hVertexShader, 0);
1708     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1709     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1710
1711     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, simple_vs, &hVertexShader, 0);
1712     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1713     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1714
1715     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
1716     {
1717         /* The same with a pixel shader */
1718         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1719         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1720         /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
1721         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1722         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1723         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1724         /* Assign the shader, then verify that GetPixelShader works */
1725         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1726         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1727         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1728         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1729         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1730         /* Verify that we can retrieve the shader function */
1731         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, NULL, &data_size);
1732         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1733         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1734         data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
1735         data_size = 1;
1736         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1737         ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
1738                 "expected D3DERR_INVALIDCALL\n", hr);
1739         ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1740         data_size = simple_ps_size;
1741         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1742         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1743         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1744         ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
1745         HeapFree(GetProcessHeap(), 0, data);
1746         /* Delete the assigned shader. This is supposed to work */
1747         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1748         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1749         /* The shader should be unset now */
1750         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1751         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1752         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1753
1754         /* What happens if a non-bound shader is deleted? */
1755         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1756         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1757         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader2);
1758         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1759
1760         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1761         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1762         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1763         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1764         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1765         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1766         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1767         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1768         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1769
1770         /* Check for double delete. */
1771         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1772         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1773         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1774         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1775     }
1776     else
1777     {
1778         skip("Pixel shaders not supported\n");
1779     }
1780
1781     /* What happens if a non-bound shader is deleted? */
1782     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader, 0);
1783     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1784     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader2, 0);
1785     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1786
1787     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1788     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1789     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1790     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1791     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1792     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1793     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1794     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1795     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1796
1797     /* Check for double delete. */
1798     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1799     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1800     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1801     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1802
1803 cleanup:
1804     if (pDevice)
1805     {
1806         UINT refcount = IDirect3DDevice8_Release(pDevice);
1807         ok(!refcount, "Device has %u references left.\n", refcount);
1808     }
1809     if (pD3d) IDirect3D8_Release(pD3d);
1810     DestroyWindow(hwnd);
1811 }
1812
1813 static void test_limits(void)
1814 {
1815     HRESULT                      hr;
1816     HWND                         hwnd               = NULL;
1817     IDirect3D8                  *pD3d               = NULL;
1818     IDirect3DDevice8            *pDevice            = NULL;
1819     D3DPRESENT_PARAMETERS        d3dpp;
1820     D3DDISPLAYMODE               d3ddm;
1821     IDirect3DTexture8           *pTexture           = NULL;
1822     int i;
1823
1824     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1825     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1826     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1827     ok(hwnd != NULL, "Failed to create window\n");
1828     if (!pD3d || !hwnd) goto cleanup;
1829
1830     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1831     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1832     d3dpp.Windowed         = TRUE;
1833     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1834     d3dpp.BackBufferWidth  = 800;
1835     d3dpp.BackBufferHeight = 600;
1836     d3dpp.BackBufferFormat = d3ddm.Format;
1837     d3dpp.EnableAutoDepthStencil = TRUE;
1838     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1839
1840     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1841                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1842     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1843     if(!pDevice)
1844     {
1845         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1846         goto cleanup;
1847     }
1848
1849     hr = IDirect3DDevice8_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture);
1850     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
1851     if(!pTexture) goto cleanup;
1852
1853     /* There are 8 texture stages. We should be able to access all of them */
1854     for(i = 0; i < 8; i++) {
1855         hr = IDirect3DDevice8_SetTexture(pDevice, i, (IDirect3DBaseTexture8 *) pTexture);
1856         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1857         hr = IDirect3DDevice8_SetTexture(pDevice, i, NULL);
1858         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1859         hr = IDirect3DDevice8_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1860         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
1861     }
1862
1863     /* Investigations show that accessing higher textures stage states does not return an error either. Writing
1864      * to too high texture stages(approximately texture 40) causes memory corruption in windows, so there is no
1865      * bounds checking but how do I test that?
1866      */
1867
1868 cleanup:
1869     if(pTexture) IDirect3DTexture8_Release(pTexture);
1870     if (pDevice)
1871     {
1872         UINT refcount = IDirect3DDevice8_Release(pDevice);
1873         ok(!refcount, "Device has %u references left.\n", refcount);
1874     }
1875     if (pD3d) IDirect3D8_Release(pD3d);
1876     DestroyWindow(hwnd);
1877 }
1878
1879 static void test_lights(void)
1880 {
1881     D3DPRESENT_PARAMETERS d3dpp;
1882     IDirect3DDevice8 *device = NULL;
1883     IDirect3D8 *d3d8;
1884     HWND hwnd;
1885     HRESULT hr;
1886     unsigned int i;
1887     BOOL enabled;
1888     D3DCAPS8 caps;
1889     D3DDISPLAYMODE               d3ddm;
1890
1891     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1892     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1893     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1894     ok(hwnd != NULL, "Failed to create window\n");
1895     if (!d3d8 || !hwnd) goto cleanup;
1896
1897     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1898     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1899     d3dpp.Windowed         = TRUE;
1900     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1901     d3dpp.BackBufferWidth  = 800;
1902     d3dpp.BackBufferHeight = 600;
1903     d3dpp.BackBufferFormat = d3ddm.Format;
1904     d3dpp.EnableAutoDepthStencil = TRUE;
1905     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1906
1907     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1908                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
1909     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1910        "IDirect3D8_CreateDevice failed with %08x\n", hr);
1911     if(!device)
1912     {
1913         skip("Failed to create a d3d device\n");
1914         goto cleanup;
1915     }
1916
1917     memset(&caps, 0, sizeof(caps));
1918     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1919     ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
1920
1921     for(i = 1; i <= caps.MaxActiveLights; i++) {
1922         hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
1923         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1924         hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
1925         ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
1926             "GetLightEnable on light %u failed with %08x\n", i, hr);
1927         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1928     }
1929
1930     /* TODO: Test the rendering results in this situation */
1931     hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
1932     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
1933     hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
1934     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1935     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1936     hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
1937     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1938
1939     for(i = 1; i <= caps.MaxActiveLights; i++) {
1940         hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
1941         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
1942     }
1943
1944 cleanup:
1945     if (device)
1946     {
1947         UINT refcount = IDirect3DDevice8_Release(device);
1948         ok(!refcount, "Device has %u references left.\n", refcount);
1949     }
1950     if (d3d8) IDirect3D8_Release(d3d8);
1951     DestroyWindow(hwnd);
1952 }
1953
1954 static void test_render_zero_triangles(void)
1955 {
1956     D3DPRESENT_PARAMETERS d3dpp;
1957     IDirect3DDevice8 *device = NULL;
1958     IDirect3D8 *d3d8;
1959     HWND hwnd;
1960     HRESULT hr;
1961     D3DDISPLAYMODE               d3ddm;
1962
1963     struct nvertex
1964     {
1965         float x, y, z;
1966         float nx, ny, nz;
1967         DWORD diffuse;
1968     }  quad[] =
1969     {
1970         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1971         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1972         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1973         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1974     };
1975
1976     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1977     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1978     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1979     ok(hwnd != NULL, "Failed to create window\n");
1980     if (!d3d8 || !hwnd) goto cleanup;
1981
1982     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1983     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1984     d3dpp.Windowed         = TRUE;
1985     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1986     d3dpp.BackBufferWidth  = 800;
1987     d3dpp.BackBufferHeight = 600;
1988     d3dpp.BackBufferFormat = d3ddm.Format;
1989     d3dpp.EnableAutoDepthStencil = TRUE;
1990     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1991
1992     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1993                                   D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
1994     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1995        "IDirect3D8_CreateDevice failed with %08x\n", hr);
1996     if(!device)
1997     {
1998         skip("Failed to create a d3d device\n");
1999         goto cleanup;
2000     }
2001
2002     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2003     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2004
2005     hr = IDirect3DDevice8_BeginScene(device);
2006     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
2007     if(hr == D3D_OK)
2008     {
2009         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
2010                                                     0 /*PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
2011         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
2012
2013         hr = IDirect3DDevice8_EndScene(device);
2014         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
2015     }
2016
2017     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2018
2019 cleanup:
2020     if (device)
2021     {
2022         UINT refcount = IDirect3DDevice8_Release(device);
2023         ok(!refcount, "Device has %u references left.\n", refcount);
2024     }
2025     if (d3d8) IDirect3D8_Release(d3d8);
2026     DestroyWindow(hwnd);
2027 }
2028
2029 static void test_depth_stencil_reset(void)
2030 {
2031     D3DPRESENT_PARAMETERS present_parameters;
2032     D3DDISPLAYMODE display_mode;
2033     IDirect3DSurface8 *surface, *orig_rt;
2034     IDirect3DDevice8 *device = NULL;
2035     IDirect3D8 *d3d8;
2036     UINT refcount;
2037     HRESULT hr;
2038     HWND hwnd;
2039
2040     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2041     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2042     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2043     ok(hwnd != NULL, "Failed to create window\n");
2044     if (!d3d8 || !hwnd) goto cleanup;
2045
2046     IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
2047     memset(&present_parameters, 0, sizeof(present_parameters));
2048     present_parameters.Windowed               = TRUE;
2049     present_parameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
2050     present_parameters.BackBufferFormat       = display_mode.Format;
2051     present_parameters.EnableAutoDepthStencil = TRUE;
2052     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2053
2054     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2055             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
2056     if(FAILED(hr))
2057     {
2058         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2059         goto cleanup;
2060     }
2061
2062     hr = IDirect3DDevice8_GetRenderTarget(device, &orig_rt);
2063     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2064
2065     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2066     ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
2067
2068     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2069     ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
2070
2071     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
2072     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2073     ok(surface == orig_rt, "Render target is %p, should be %p\n", surface, orig_rt);
2074     if (surface) IDirect3DSurface8_Release(surface);
2075     IDirect3DSurface8_Release(orig_rt);
2076
2077     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2078     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2079     ok(surface == NULL, "Depth stencil should be NULL\n");
2080
2081     present_parameters.EnableAutoDepthStencil = TRUE;
2082     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2083     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2084     ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2085
2086     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2087     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2088     ok(surface != NULL, "Depth stencil should not be NULL\n");
2089     if (surface) IDirect3DSurface8_Release(surface);
2090
2091     present_parameters.EnableAutoDepthStencil = FALSE;
2092     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2093     ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2094
2095     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2096     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2097     ok(surface == NULL, "Depth stencil should be NULL\n");
2098
2099     refcount = IDirect3DDevice8_Release(device);
2100     ok(!refcount, "Device has %u references left.\n", refcount);
2101     device = NULL;
2102
2103     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
2104
2105     ZeroMemory( &present_parameters, sizeof(present_parameters) );
2106     present_parameters.Windowed         = TRUE;
2107     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2108     present_parameters.BackBufferFormat = display_mode.Format;
2109     present_parameters.EnableAutoDepthStencil = FALSE;
2110     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2111
2112     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2113                     D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2114
2115     if(FAILED(hr))
2116     {
2117         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2118         goto cleanup;
2119     }
2120
2121     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2122     ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
2123
2124     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2125     present_parameters.Windowed         = TRUE;
2126     present_parameters.BackBufferWidth  = 400;
2127     present_parameters.BackBufferHeight = 300;
2128     present_parameters.EnableAutoDepthStencil = TRUE;
2129     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2130
2131     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2132     ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
2133
2134     if (FAILED(hr)) goto cleanup;
2135
2136     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2137     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2138     ok(surface != NULL, "Depth stencil should not be NULL\n");
2139     if (surface) IDirect3DSurface8_Release(surface);
2140
2141 cleanup:
2142     if (device)
2143     {
2144         refcount = IDirect3DDevice8_Release(device);
2145         ok(!refcount, "Device has %u references left.\n", refcount);
2146     }
2147     if (d3d8) IDirect3D8_Release(d3d8);
2148     DestroyWindow(hwnd);
2149 }
2150
2151 static HWND filter_messages;
2152
2153 enum message_window
2154 {
2155     DEVICE_WINDOW,
2156     FOCUS_WINDOW,
2157 };
2158
2159 struct message
2160 {
2161     UINT message;
2162     enum message_window window;
2163 };
2164
2165 static const struct message *expect_messages;
2166 static HWND device_window, focus_window;
2167
2168 struct wndproc_thread_param
2169 {
2170     HWND dummy_window;
2171     HANDLE window_created;
2172     HANDLE test_finished;
2173     BOOL running_in_foreground;
2174 };
2175
2176 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2177 {
2178     if (filter_messages && filter_messages == hwnd)
2179     {
2180         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2181             todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2182     }
2183
2184     if (expect_messages)
2185     {
2186         HWND w;
2187
2188         switch (expect_messages->window)
2189         {
2190             case DEVICE_WINDOW:
2191                 w = device_window;
2192                 break;
2193
2194             case FOCUS_WINDOW:
2195                 w = focus_window;
2196                 break;
2197
2198             default:
2199                 w = NULL;
2200                 break;
2201         };
2202
2203         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2204     }
2205
2206     return DefWindowProcA(hwnd, message, wparam, lparam);
2207 }
2208
2209 static DWORD WINAPI wndproc_thread(void *param)
2210 {
2211     struct wndproc_thread_param *p = param;
2212     DWORD res;
2213     BOOL ret;
2214
2215     p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2216             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2217     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2218
2219     ret = SetEvent(p->window_created);
2220     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2221
2222     for (;;)
2223     {
2224         MSG msg;
2225
2226         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2227         res = WaitForSingleObject(p->test_finished, 100);
2228         if (res == WAIT_OBJECT_0) break;
2229         if (res != WAIT_TIMEOUT)
2230         {
2231             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2232             break;
2233         }
2234     }
2235
2236     DestroyWindow(p->dummy_window);
2237
2238     return 0;
2239 }
2240
2241 static void test_wndproc(void)
2242 {
2243     struct wndproc_thread_param thread_params;
2244     IDirect3DDevice8 *device;
2245     WNDCLASSA wc = {0};
2246     IDirect3D8 *d3d8;
2247     HANDLE thread;
2248     LONG_PTR proc;
2249     ULONG ref;
2250     DWORD res, tid;
2251     HWND tmp;
2252
2253     static const struct message messages[] =
2254     {
2255         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2256         {WM_ACTIVATE,           FOCUS_WINDOW},
2257         {WM_SETFOCUS,           FOCUS_WINDOW},
2258         {WM_WINDOWPOSCHANGING,  DEVICE_WINDOW},
2259         {WM_MOVE,               DEVICE_WINDOW},
2260         {WM_SIZE,               DEVICE_WINDOW},
2261         {0,                     0},
2262     };
2263
2264     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2265     {
2266         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2267         return;
2268     }
2269
2270     wc.lpfnWndProc = test_proc;
2271     wc.lpszClassName = "d3d8_test_wndproc_wc";
2272     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2273
2274     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2275     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2276     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2277     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2278
2279     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2280             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2281     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2282             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2283     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2284     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2285
2286     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2287     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2288
2289     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2290     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2291             (LONG_PTR)test_proc, proc);
2292     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2293     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2294             (LONG_PTR)test_proc, proc);
2295
2296     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2297             device_window, focus_window, thread_params.dummy_window);
2298
2299     tmp = GetFocus();
2300     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2301     if (thread_params.running_in_foreground)
2302     {
2303         tmp = GetForegroundWindow();
2304         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2305                 thread_params.dummy_window, tmp);
2306     }
2307     else
2308         skip("Not running in foreground, skip foreground window test\n");
2309
2310     flush_events();
2311
2312     expect_messages = messages;
2313
2314     device = create_device(d3d8, device_window, focus_window, FALSE);
2315     if (!device)
2316     {
2317         skip("Failed to create a D3D device, skipping tests.\n");
2318         goto done;
2319     }
2320
2321     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2322             expect_messages->message, expect_messages->window);
2323     expect_messages = NULL;
2324
2325     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2326     {
2327         tmp = GetFocus();
2328         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2329         tmp = GetForegroundWindow();
2330         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2331     }
2332     SetForegroundWindow(focus_window);
2333     flush_events();
2334
2335     filter_messages = focus_window;
2336
2337     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2338     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2339             (LONG_PTR)test_proc, proc);
2340
2341     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2342     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2343             (LONG_PTR)test_proc, proc);
2344
2345     ref = IDirect3DDevice8_Release(device);
2346     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2347
2348     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2349     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2350             (LONG_PTR)test_proc, proc);
2351
2352     device = create_device(d3d8, focus_window, focus_window, FALSE);
2353     if (!device)
2354     {
2355         skip("Failed to create a D3D device, skipping tests.\n");
2356         goto done;
2357     }
2358
2359     ref = IDirect3DDevice8_Release(device);
2360     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2361
2362     device = create_device(d3d8, device_window, focus_window, FALSE);
2363     if (!device)
2364     {
2365         skip("Failed to create a D3D device, skipping tests.\n");
2366         goto done;
2367     }
2368
2369     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2370     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2371             (LONG_PTR)test_proc, proc);
2372
2373     ref = IDirect3DDevice8_Release(device);
2374     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2375
2376     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2377     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2378             (LONG_PTR)DefWindowProcA, proc);
2379
2380 done:
2381     filter_messages = NULL;
2382     IDirect3D8_Release(d3d8);
2383
2384     SetEvent(thread_params.test_finished);
2385     WaitForSingleObject(thread, INFINITE);
2386     CloseHandle(thread_params.test_finished);
2387     CloseHandle(thread_params.window_created);
2388     CloseHandle(thread);
2389
2390     DestroyWindow(device_window);
2391     DestroyWindow(focus_window);
2392     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2393 }
2394
2395 static void test_wndproc_windowed(void)
2396 {
2397     struct wndproc_thread_param thread_params;
2398     IDirect3DDevice8 *device;
2399     WNDCLASSA wc = {0};
2400     IDirect3D8 *d3d8;
2401     HANDLE thread;
2402     LONG_PTR proc;
2403     HRESULT hr;
2404     ULONG ref;
2405     DWORD res, tid;
2406     HWND tmp;
2407
2408     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2409     {
2410         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2411         return;
2412     }
2413
2414     wc.lpfnWndProc = test_proc;
2415     wc.lpszClassName = "d3d8_test_wndproc_wc";
2416     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2417
2418     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2419     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2420     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2421     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2422
2423     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2424             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2425     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2426             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2427     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2428     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2429
2430     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2431     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2432
2433     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2434     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2435             (LONG_PTR)test_proc, proc);
2436     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2437     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2438             (LONG_PTR)test_proc, proc);
2439
2440     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2441             device_window, focus_window, thread_params.dummy_window);
2442
2443     tmp = GetFocus();
2444     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2445     if (thread_params.running_in_foreground)
2446     {
2447         tmp = GetForegroundWindow();
2448         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2449                 thread_params.dummy_window, tmp);
2450     }
2451     else
2452         skip("Not running in foreground, skip foreground window test\n");
2453
2454     filter_messages = focus_window;
2455
2456     device = create_device(d3d8, device_window, focus_window, TRUE);
2457     if (!device)
2458     {
2459         skip("Failed to create a D3D device, skipping tests.\n");
2460         goto done;
2461     }
2462
2463     tmp = GetFocus();
2464     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2465     tmp = GetForegroundWindow();
2466     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2467             thread_params.dummy_window, tmp);
2468
2469     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2470     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2471             (LONG_PTR)test_proc, proc);
2472
2473     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2474     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2475             (LONG_PTR)test_proc, proc);
2476
2477     filter_messages = NULL;
2478
2479     hr = reset_device(device, device_window, FALSE);
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     hr = reset_device(device, device_window, TRUE);
2491     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2492
2493     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2494     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2495             (LONG_PTR)test_proc, proc);
2496
2497     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2498     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2499             (LONG_PTR)test_proc, proc);
2500
2501     filter_messages = focus_window;
2502
2503     ref = IDirect3DDevice8_Release(device);
2504     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2505
2506     filter_messages = device_window;
2507
2508     device = create_device(d3d8, focus_window, focus_window, TRUE);
2509     if (!device)
2510     {
2511         skip("Failed to create a D3D device, skipping tests.\n");
2512         goto done;
2513     }
2514
2515     filter_messages = NULL;
2516
2517     hr = reset_device(device, focus_window, FALSE);
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     hr = reset_device(device, focus_window, TRUE);
2529     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2530
2531     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2532     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2533             (LONG_PTR)test_proc, proc);
2534
2535     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2536     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2537             (LONG_PTR)test_proc, proc);
2538
2539     filter_messages = device_window;
2540
2541     ref = IDirect3DDevice8_Release(device);
2542     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2543
2544     device = create_device(d3d8, device_window, focus_window, TRUE);
2545     if (!device)
2546     {
2547         skip("Failed to create a D3D device, skipping tests.\n");
2548         goto done;
2549     }
2550
2551     filter_messages = NULL;
2552
2553     hr = reset_device(device, device_window, FALSE);
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     hr = reset_device(device, device_window, TRUE);
2565     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2566
2567     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2568     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2569             (LONG_PTR)test_proc, proc);
2570
2571     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2572     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2573             (LONG_PTR)test_proc, proc);
2574
2575     filter_messages = device_window;
2576
2577     ref = IDirect3DDevice8_Release(device);
2578     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2579
2580 done:
2581     filter_messages = NULL;
2582     IDirect3D8_Release(d3d8);
2583
2584     SetEvent(thread_params.test_finished);
2585     WaitForSingleObject(thread, INFINITE);
2586     CloseHandle(thread_params.test_finished);
2587     CloseHandle(thread_params.window_created);
2588     CloseHandle(thread);
2589
2590     DestroyWindow(device_window);
2591     DestroyWindow(focus_window);
2592     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2593 }
2594
2595 static inline void set_fpu_cw(WORD cw)
2596 {
2597 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2598 #define D3D8_TEST_SET_FPU_CW 1
2599     __asm__ volatile ("fnclex");
2600     __asm__ volatile ("fldcw %0" : : "m" (cw));
2601 #elif defined(__i386__) && defined(_MSC_VER)
2602 #define D3D8_TEST_SET_FPU_CW 1
2603     __asm fnclex;
2604     __asm fldcw cw;
2605 #endif
2606 }
2607
2608 static inline WORD get_fpu_cw(void)
2609 {
2610     WORD cw = 0;
2611 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2612 #define D3D8_TEST_GET_FPU_CW 1
2613     __asm__ volatile ("fnstcw %0" : "=m" (cw));
2614 #elif defined(__i386__) && defined(_MSC_VER)
2615 #define D3D8_TEST_GET_FPU_CW 1
2616     __asm fnstcw cw;
2617 #endif
2618     return cw;
2619 }
2620
2621 static void test_fpu_setup(void)
2622 {
2623 #if defined(D3D8_TEST_SET_FPU_CW) && defined(D3D8_TEST_GET_FPU_CW)
2624     D3DPRESENT_PARAMETERS present_parameters;
2625     IDirect3DDevice8 *device;
2626     D3DDISPLAYMODE d3ddm;
2627     HWND window = NULL;
2628     IDirect3D8 *d3d8;
2629     HRESULT hr;
2630     WORD cw;
2631
2632     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2633     ok(!!d3d8, "Failed to create a d3d8 object.\n");
2634     if (!d3d8) return;
2635
2636     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2637     ok(!!window, "Failed to create a window.\n");
2638     if (!window) goto done;
2639
2640     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
2641     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
2642
2643     memset(&present_parameters, 0, sizeof(present_parameters));
2644     present_parameters.Windowed = TRUE;
2645     present_parameters.hDeviceWindow = window;
2646     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2647     present_parameters.BackBufferFormat = d3ddm.Format;
2648
2649     set_fpu_cw(0xf60);
2650     cw = get_fpu_cw();
2651     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2652
2653     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2654             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
2655     if (FAILED(hr))
2656     {
2657         skip("Failed to create a device, hr %#x.\n", hr);
2658         set_fpu_cw(0x37f);
2659         goto done;
2660     }
2661
2662     cw = get_fpu_cw();
2663     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2664
2665     IDirect3DDevice8_Release(device);
2666
2667     cw = get_fpu_cw();
2668     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2669     set_fpu_cw(0xf60);
2670     cw = get_fpu_cw();
2671     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2672
2673     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2674             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
2675     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
2676
2677     cw = get_fpu_cw();
2678     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2679     set_fpu_cw(0x37f);
2680
2681     IDirect3DDevice8_Release(device);
2682
2683 done:
2684     if (window) DestroyWindow(window);
2685     if (d3d8) IDirect3D8_Release(d3d8);
2686 #endif
2687 }
2688
2689 static void test_ApplyStateBlock(void)
2690 {
2691     D3DPRESENT_PARAMETERS d3dpp;
2692     IDirect3DDevice8 *device = NULL;
2693     IDirect3D8 *d3d8;
2694     HWND hwnd;
2695     HRESULT hr;
2696     D3DDISPLAYMODE d3ddm;
2697     DWORD received, token;
2698
2699     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2700     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2701     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2702     ok(hwnd != NULL, "Failed to create window\n");
2703     if (!d3d8 || !hwnd) goto cleanup;
2704
2705     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
2706     ZeroMemory( &d3dpp, sizeof(d3dpp) );
2707     d3dpp.Windowed         = TRUE;
2708     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2709     d3dpp.BackBufferWidth  = 800;
2710     d3dpp.BackBufferHeight  = 600;
2711     d3dpp.BackBufferFormat = d3ddm.Format;
2712     d3dpp.EnableAutoDepthStencil = TRUE;
2713     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2714
2715     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2716                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
2717     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2718        "IDirect3D8_CreateDevice failed with %#x\n", hr);
2719     if(!device)
2720     {
2721         skip("Failed to create a d3d device\n");
2722         goto cleanup;
2723     }
2724
2725     IDirect3DDevice8_BeginStateBlock(device);
2726     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
2727     IDirect3DDevice8_EndStateBlock(device, &token);
2728     ok(token, "Received zero stateblock handle.\n");
2729     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
2730
2731     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2732     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2733     ok(!received, "Expected = FALSE, received TRUE.\n");
2734
2735     hr = IDirect3DDevice8_ApplyStateBlock(device, 0);
2736     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2737     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2738     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2739     ok(!received, "Expected FALSE, received TRUE.\n");
2740
2741     hr = IDirect3DDevice8_ApplyStateBlock(device, token);
2742     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2743     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2744     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2745     ok(received, "Expected TRUE, received FALSE.\n");
2746
2747     IDirect3DDevice8_DeleteStateBlock(device, token);
2748     IDirect3DDevice8_Release(device);
2749 cleanup:
2750     if (d3d8) IDirect3D8_Release(d3d8);
2751     DestroyWindow(hwnd);
2752 }
2753
2754 static void test_depth_stencil_size(void)
2755 {
2756     IDirect3DDevice8 *device;
2757     IDirect3DSurface8 *ds, *rt, *ds_bigger, *ds_bigger2;
2758     IDirect3DSurface8 *surf;
2759     IDirect3D8 *d3d8;
2760     HRESULT hr;
2761     HWND hwnd;
2762
2763     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2764     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2765     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2766     ok(hwnd != NULL, "Failed to create window\n");
2767     if (!d3d8 || !hwnd) goto cleanup;
2768
2769     device = create_device(d3d8, hwnd, hwnd, TRUE);
2770     if (!device) goto cleanup;
2771
2772     hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
2773     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateRenderTarget failed, hr %#x.\n", hr);
2774     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds);
2775     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2776     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger);
2777     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2778     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger2);
2779     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2780
2781     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2782     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2783     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds_bigger);
2784     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2785
2786     /* try to set the small ds without changing the render target at the same time */
2787     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds);
2788     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2789     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds_bigger2);
2790     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2791
2792     hr = IDirect3DDevice8_GetRenderTarget(device, &surf);
2793     ok(hr == D3D_OK, "IDirect3DDevice8_GetRenderTarget failed, hr %#x.\n", hr);
2794     ok(surf == rt, "The render target is %p, expected %p\n", surf, rt);
2795     IDirect3DSurface8_Release(surf);
2796     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2797     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr %#x.\n", hr);
2798     ok(surf == ds_bigger2, "The depth stencil is %p, expected %p\n", surf, ds_bigger2);
2799     IDirect3DSurface8_Release(surf);
2800
2801     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2802     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2803     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2804     ok(FAILED(hr), "IDirect3DDevice8_GetDepthStencilSurface should have failed, hr %#x.\n", hr);
2805     ok(surf == NULL, "The depth stencil is %p, expected NULL\n", surf);
2806     if (surf) IDirect3DSurface8_Release(surf);
2807
2808     IDirect3DSurface8_Release(rt);
2809     IDirect3DSurface8_Release(ds);
2810     IDirect3DSurface8_Release(ds_bigger);
2811     IDirect3DSurface8_Release(ds_bigger2);
2812
2813 cleanup:
2814     if (d3d8) IDirect3D8_Release(d3d8);
2815     DestroyWindow(hwnd);
2816 }
2817
2818 static void test_window_style(void)
2819 {
2820     RECT focus_rect, fullscreen_rect, r;
2821     LONG device_style, device_exstyle;
2822     LONG focus_style, focus_exstyle;
2823     LONG style, expected_style;
2824     IDirect3DDevice8 *device;
2825     IDirect3D8 *d3d8;
2826     ULONG ref;
2827
2828
2829     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2830     {
2831         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2832         return;
2833     }
2834
2835     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2836             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2837     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2838             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2839
2840     device_style = GetWindowLongA(device_window, GWL_STYLE);
2841     device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
2842     focus_style = GetWindowLongA(focus_window, GWL_STYLE);
2843     focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
2844
2845     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
2846     GetWindowRect(focus_window, &focus_rect);
2847
2848     device = create_device(d3d8, device_window, focus_window, FALSE);
2849     if (!device)
2850     {
2851         skip("Failed to create a D3D device, skipping tests.\n");
2852         goto done;
2853     }
2854
2855     style = GetWindowLongA(device_window, GWL_STYLE);
2856     expected_style = device_style | WS_VISIBLE;
2857     todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
2858             expected_style, style);
2859     style = GetWindowLongA(device_window, GWL_EXSTYLE);
2860     expected_style = device_exstyle | WS_EX_TOPMOST;
2861     todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
2862             expected_style, style);
2863
2864     style = GetWindowLongA(focus_window, GWL_STYLE);
2865     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
2866             focus_style, style);
2867     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
2868     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
2869             focus_exstyle, style);
2870
2871     GetWindowRect(device_window, &r);
2872     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2873             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2874             r.left, r.top, r.right, r.bottom);
2875     GetClientRect(device_window, &r);
2876     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2877     GetWindowRect(focus_window, &r);
2878     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2879             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
2880             r.left, r.top, r.right, r.bottom);
2881
2882     ref = IDirect3DDevice8_Release(device);
2883     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2884
2885 done:
2886     IDirect3D8_Release(d3d8);
2887
2888     DestroyWindow(device_window);
2889     DestroyWindow(focus_window);
2890 }
2891
2892 static void test_wrong_shader(void)
2893 {
2894     HRESULT hr;
2895     HWND hwnd = NULL;
2896     IDirect3D8 *d3d = NULL;
2897     IDirect3DDevice8 *device = NULL;
2898     D3DPRESENT_PARAMETERS d3dpp;
2899     D3DDISPLAYMODE d3ddm;
2900     DWORD vs, ps;
2901
2902     static const DWORD vs_2_0[] =
2903     {
2904         0xfffe0200,                                         /* vs_2_0           */
2905         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
2906         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2907         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
2908         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
2909         0x0000ffff                                          /* end              */
2910     };
2911     static const DWORD ps_2_0[] =
2912     {
2913         0xffff0200,                                         /* ps_2_0           */
2914         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2915         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
2916         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
2917         0x0000ffff                                          /* end              */
2918     };
2919
2920     static const DWORD decl[] =
2921     {
2922         D3DVSD_STREAM(0),
2923         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
2924         D3DVSD_END()
2925     };
2926
2927     d3d = pDirect3DCreate8(D3D_SDK_VERSION);
2928     ok(d3d != NULL, "Failed to create IDirect3D8 object\n");
2929     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2930     ok(hwnd != NULL, "Failed to create window\n");
2931     if (!d3d || !hwnd)
2932         goto cleanup;
2933
2934     IDirect3D8_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2935     ZeroMemory(&d3dpp, sizeof(d3dpp));
2936     d3dpp.Windowed = TRUE;
2937     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2938     d3dpp.BackBufferWidth = 800;
2939     d3dpp.BackBufferHeight = 600;
2940     d3dpp.BackBufferFormat = d3ddm.Format;
2941
2942     hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2943             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
2944     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
2945     if (!device)
2946     {
2947         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
2948         goto cleanup;
2949     }
2950
2951     hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_ps, &vs, 0);
2952     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2953
2954     hr = IDirect3DDevice8_CreatePixelShader(device, simple_vs, &ps);
2955     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2956
2957     hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_2_0, &vs, 0);
2958     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2959
2960     hr = IDirect3DDevice8_CreatePixelShader(device, ps_2_0, &ps);
2961     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2962
2963 cleanup:
2964     if (device)
2965     {
2966         UINT refcount = IDirect3DDevice8_Release(device);
2967         ok(!refcount, "Device has %u references left.\n", refcount);
2968     }
2969     if (d3d)
2970         IDirect3D8_Release(d3d);
2971     DestroyWindow(hwnd);
2972 }
2973
2974 static void test_mode_change(void)
2975 {
2976     RECT fullscreen_rect, focus_rect, r;
2977     IDirect3DSurface8 *backbuffer;
2978     IDirect3DDevice8 *device;
2979     D3DSURFACE_DESC desc;
2980     IDirect3D8 *d3d8;
2981     DEVMODEW devmode;
2982     UINT refcount;
2983     HRESULT hr;
2984     DWORD ret;
2985
2986     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2987     {
2988         skip("Failed to create IDirect3D8 object, skipping mode change tests.\n");
2989         return;
2990     }
2991
2992     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2993             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2994     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2995             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2996
2997     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
2998     GetWindowRect(focus_window, &focus_rect);
2999
3000     device = create_device(d3d8, device_window, focus_window, FALSE);
3001     if (!device)
3002     {
3003         skip("Failed to create a D3D device, skipping tests.\n");
3004         goto done;
3005     }
3006
3007     memset(&devmode, 0, sizeof(devmode));
3008     devmode.dmSize = sizeof(devmode);
3009     devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3010     devmode.dmPelsWidth = 640;
3011     devmode.dmPelsHeight = 480;
3012
3013     ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3014     ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3015
3016     memset(&devmode, 0, sizeof(devmode));
3017     devmode.dmSize = sizeof(devmode);
3018     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3019     ok(ret, "Failed to get display mode.\n");
3020     ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3021     ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3022
3023     GetWindowRect(device_window, &r);
3024     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3025             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3026             r.left, r.top, r.right, r.bottom);
3027     GetWindowRect(focus_window, &r);
3028     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3029             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3030             r.left, r.top, r.right, r.bottom);
3031
3032     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3033     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3034     hr = IDirect3DSurface8_GetDesc(backbuffer, &desc);
3035     ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3036     ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3037     ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3038     IDirect3DSurface8_Release(backbuffer);
3039
3040     refcount = IDirect3DDevice8_Release(device);
3041     ok(!refcount, "Device has %u references left.\n", refcount);
3042
3043     memset(&devmode, 0, sizeof(devmode));
3044     devmode.dmSize = sizeof(devmode);
3045     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3046     ok(ret, "Failed to get display mode.\n");
3047     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3048     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3049
3050 done:
3051     DestroyWindow(device_window);
3052     DestroyWindow(focus_window);
3053     if (d3d8)
3054         IDirect3D8_Release(d3d8);
3055
3056     memset(&devmode, 0, sizeof(devmode));
3057     devmode.dmSize = sizeof(devmode);
3058     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3059     ok(ret, "Failed to get display mode.\n");
3060     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3061     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3062 }
3063
3064 static void test_device_window_reset(void)
3065 {
3066     RECT fullscreen_rect, device_rect, r;
3067     IDirect3DDevice8 *device;
3068     WNDCLASSA wc = {0};
3069     IDirect3D8 *d3d8;
3070     LONG_PTR proc;
3071     HRESULT hr;
3072     ULONG ref;
3073
3074     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3075     {
3076         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3077         return;
3078     }
3079
3080     wc.lpfnWndProc = test_proc;
3081     wc.lpszClassName = "d3d8_test_wndproc_wc";
3082     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3083
3084     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3085             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3086     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3087             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3088
3089     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3090     GetWindowRect(device_window, &device_rect);
3091
3092     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3093     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3094             (LONG_PTR)test_proc, proc);
3095     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3096     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3097             (LONG_PTR)test_proc, proc);
3098
3099     device = create_device(d3d8, NULL, focus_window, FALSE);
3100     if (!device)
3101     {
3102         skip("Failed to create a D3D device, skipping tests.\n");
3103         goto done;
3104     }
3105
3106     GetWindowRect(focus_window, &r);
3107     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3108             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3109             r.left, r.top, r.right, r.bottom);
3110     GetWindowRect(device_window, &r);
3111     ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3112             device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3113             r.left, r.top, r.right, r.bottom);
3114
3115     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3116     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3117             (LONG_PTR)test_proc, proc);
3118     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3119     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3120             (LONG_PTR)test_proc, proc);
3121
3122     hr = reset_device(device, device_window, FALSE);
3123     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3124
3125     GetWindowRect(focus_window, &r);
3126     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3127             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3128             r.left, r.top, r.right, r.bottom);
3129     GetWindowRect(device_window, &r);
3130     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3131             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3132             r.left, r.top, r.right, r.bottom);
3133
3134     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3135     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3136             (LONG_PTR)test_proc, proc);
3137     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3138     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3139             (LONG_PTR)test_proc, proc);
3140
3141     ref = IDirect3DDevice8_Release(device);
3142     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3143
3144 done:
3145     IDirect3D8_Release(d3d8);
3146     DestroyWindow(device_window);
3147     DestroyWindow(focus_window);
3148     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3149 }
3150
3151 static void depth_blit_test(void)
3152 {
3153     HWND hwnd = NULL;
3154     IDirect3D8 *d3d8 = NULL;
3155     IDirect3DDevice8 *device = NULL;
3156     IDirect3DSurface8 *backbuffer, *ds1, *ds2, *ds3;
3157     RECT src_rect;
3158     const POINT dst_point = {0, 0};
3159     HRESULT hr;
3160
3161     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
3162     ok(d3d8 != NULL, "Direct3DCreate8 failed.\n");
3163     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
3164     ok(hwnd != NULL, "CreateWindow failed.\n");
3165     if (!d3d8 || !hwnd)
3166         goto done;
3167
3168     device = create_device(d3d8, hwnd, hwnd, TRUE);
3169     if (!device)
3170     {
3171         skip("Failed to create a D3D device, skipping tests.\n");
3172         goto done;
3173     }
3174
3175     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
3176     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
3177     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds1);
3178     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
3179     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds2);
3180     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3181     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds3);
3182     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3183
3184     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
3185     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
3186
3187     /* Partial blit. */
3188     SetRect(&src_rect, 0, 0, 320, 240);
3189     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3190     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3191     /* Flipped. */
3192     SetRect(&src_rect, 0, 480, 640, 0);
3193     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3194     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3195     /* Full, explicit. */
3196     SetRect(&src_rect, 0, 0, 640, 480);
3197     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3198     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3199     /* Depth -> color blit.*/
3200     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, backbuffer, &dst_point);
3201     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3202     /* Full, NULL rects, current depth stencil -> unbound depth stencil */
3203     hr = IDirect3DDevice8_CopyRects(device, ds1, NULL, 0, ds2, NULL);
3204     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3205     /* Full, NULL rects, unbound depth stencil -> current depth stencil */
3206     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds1, NULL);
3207     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3208     /* Full, NULL rects, unbound depth stencil -> unbound depth stencil */
3209     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds3, NULL);
3210     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3211
3212     IDirect3DSurface8_Release(backbuffer);
3213     IDirect3DSurface8_Release(ds3);
3214     IDirect3DSurface8_Release(ds2);
3215     IDirect3DSurface8_Release(ds1);
3216
3217 done:
3218     if (device) IDirect3DDevice8_Release(device);
3219     if (d3d8) IDirect3D8_Release(d3d8);
3220     if (hwnd) DestroyWindow(hwnd);
3221 }
3222
3223 static void test_reset_resources(void)
3224 {
3225     IDirect3DSurface8 *surface, *rt;
3226     IDirect3DTexture8 *texture;
3227     IDirect3DDevice8 *device;
3228     IDirect3D8 *d3d8;
3229     HWND window;
3230     HRESULT hr;
3231     ULONG ref;
3232
3233     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
3234             0, 0, 640, 480, 0, 0, 0, 0);
3235
3236     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3237     {
3238         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3239         DestroyWindow(window);
3240         return;
3241     }
3242
3243     if (!(device = create_device(d3d8, window, window, TRUE)))
3244     {
3245         skip("Failed to create a D3D device, skipping tests.\n");
3246         goto done;
3247     }
3248
3249     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_DEPTHSTENCIL,
3250             D3DFMT_D24S8, D3DPOOL_DEFAULT, &texture);
3251     ok(SUCCEEDED(hr), "Failed to create depth/stencil texture, hr %#x.\n", hr);
3252     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
3253     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3254     IDirect3DTexture8_Release(texture);
3255
3256     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3257             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3258     ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr);
3259     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &rt);
3260     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3261     IDirect3DTexture8_Release(texture);
3262
3263     hr = IDirect3DDevice8_SetRenderTarget(device, rt, surface);
3264     ok(SUCCEEDED(hr), "Failed to set render target surface, hr %#x.\n", hr);
3265     IDirect3DSurface8_Release(rt);
3266     IDirect3DSurface8_Release(surface);
3267
3268     hr = reset_device(device, device_window, TRUE);
3269     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3270
3271     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3272     ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3273     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3274     ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3275     ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3276     IDirect3DSurface8_Release(surface);
3277     IDirect3DSurface8_Release(rt);
3278
3279     ref = IDirect3DDevice8_Release(device);
3280     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3281
3282 done:
3283     IDirect3D8_Release(d3d8);
3284     DestroyWindow(window);
3285 }
3286
3287 static void test_set_rt_vp_scissor(void)
3288 {
3289     IDirect3DDevice8 *device;
3290     IDirect3DSurface8 *rt;
3291     IDirect3D8 *d3d8;
3292     DWORD stateblock;
3293     D3DVIEWPORT8 vp;
3294     UINT refcount;
3295     HWND window;
3296     HRESULT hr;
3297
3298     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3299     {
3300         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3301         return;
3302     }
3303
3304     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
3305             0, 0, 640, 480, 0, 0, 0, 0);
3306     if (!(device = create_device(d3d8, window, window, TRUE)))
3307     {
3308         skip("Failed to create a D3D device, skipping tests.\n");
3309         DestroyWindow(window);
3310         return;
3311     }
3312
3313     hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3314             D3DMULTISAMPLE_NONE, FALSE, &rt);
3315     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3316
3317     hr = IDirect3DDevice8_GetViewport(device, &vp);
3318     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3319     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3320     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3321     ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3322     ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3323     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3324     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3325
3326     hr = IDirect3DDevice8_BeginStateBlock(device);
3327     ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3328
3329     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3330     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3331
3332     hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
3333     ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3334     hr = IDirect3DDevice8_DeleteStateBlock(device, stateblock);
3335     ok(SUCCEEDED(hr), "Failed to delete stateblock, hr %#x.\n", hr);
3336
3337     hr = IDirect3DDevice8_GetViewport(device, &vp);
3338     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3339     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3340     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3341     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3342     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3343     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3344     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3345
3346     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3347     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3348
3349     vp.X = 10;
3350     vp.Y = 20;
3351     vp.Width = 30;
3352     vp.Height = 40;
3353     vp.MinZ = 0.25f;
3354     vp.MaxZ = 0.75f;
3355     hr = IDirect3DDevice8_SetViewport(device, &vp);
3356     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3357
3358     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3359     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3360
3361     hr = IDirect3DDevice8_GetViewport(device, &vp);
3362     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3363     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3364     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3365     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3366     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3367     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3368     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3369
3370     IDirect3DSurface8_Release(rt);
3371     refcount = IDirect3DDevice8_Release(device);
3372     ok(!refcount, "Device has %u references left.\n", refcount);
3373     IDirect3D8_Release(d3d8);
3374     DestroyWindow(window);
3375 }
3376
3377 START_TEST(device)
3378 {
3379     HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
3380     WNDCLASS wc = {0};
3381     if (!d3d8_handle)
3382     {
3383         skip("Could not load d3d8.dll\n");
3384         return;
3385     }
3386
3387     wc.lpfnWndProc = DefWindowProc;
3388     wc.lpszClassName = "d3d8_test_wc";
3389     RegisterClass(&wc);
3390
3391     pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
3392     ok(pDirect3DCreate8 != NULL, "Failed to get address of Direct3DCreate8\n");
3393     if (pDirect3DCreate8)
3394     {
3395         IDirect3D8 *d3d8;
3396         d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
3397         if(!d3d8)
3398         {
3399             skip("could not create D3D8\n");
3400             return;
3401         }
3402         IDirect3D8_Release(d3d8);
3403
3404         screen_width = GetSystemMetrics(SM_CXSCREEN);
3405         screen_height = GetSystemMetrics(SM_CYSCREEN);
3406
3407         test_fpu_setup();
3408         test_display_modes();
3409         test_shader_versions();
3410         test_swapchain();
3411         test_refcount();
3412         test_mipmap_levels();
3413         test_cursor();
3414         test_cursor_pos();
3415         test_states();
3416         test_reset();
3417         test_scene();
3418         test_shader();
3419         test_limits();
3420         test_lights();
3421         test_ApplyStateBlock();
3422         test_render_zero_triangles();
3423         test_depth_stencil_reset();
3424         test_wndproc();
3425         test_wndproc_windowed();
3426         test_depth_stencil_size();
3427         test_window_style();
3428         test_wrong_shader();
3429         test_mode_change();
3430         test_device_window_reset();
3431         test_reset_resources();
3432         depth_blit_test();
3433         test_set_rt_vp_scissor();
3434     }
3435     UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));
3436 }