wbemprox: Both signature parameters are optional in IWbemClassObject::GetMethod.
[wine] / dlls / d3d8 / tests / device.c
1 /*
2  * Copyright (C) 2006 Vitaliy Margolen
3  * Copyright (C) 2006 Chris Robinson
4  * Copyright (C) 2006 Louis Lenders
5  * Copyright 2006-2007 Henri Verbeet
6  * Copyright 2010, 2011 Stefan Dösinger for CodeWeavers
7  * Copyright 2013 Henri Verbeet for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #define COBJMACROS
25 #include <windowsx.h>
26 #include <initguid.h>
27 #include <d3d8.h>
28 #include "wine/test.h"
29
30 static INT screen_width;
31 static INT screen_height;
32
33 static HRESULT (WINAPI *ValidateVertexShader)(DWORD *, DWORD *, DWORD *, int, DWORD *);
34 static HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, int, DWORD *);
35 static IDirect3D8 *(WINAPI *pDirect3DCreate8)(UINT);
36
37 static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
38
39 static const DWORD simple_vs[] = {0xFFFE0101,       /* vs_1_1               */
40     0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0   */
41     0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1   */
42     0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2   */
43     0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3   */
44     0x0000FFFF};                                    /* END                  */
45 static const DWORD simple_ps[] = {0xFFFF0101,                               /* ps_1_1                       */
46     0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
47     0x00000042, 0xB00F0000,                                                 /* tex t0                       */
48     0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000,                         /* dp3 r0, c1, c0               */
49     0x00000005, 0x800F0000, 0x90E40000, 0x80E40000,                         /* mul r0, v0, r0               */
50     0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000,                         /* mul r0, t0, r0               */
51     0x0000FFFF};                                                            /* END                          */
52
53 static int get_refcount(IUnknown *object)
54 {
55     IUnknown_AddRef( object );
56     return IUnknown_Release( object );
57 }
58
59 /* try to make sure pending X events have been processed before continuing */
60 static void flush_events(void)
61 {
62     MSG msg;
63     int diff = 200;
64     int min_timeout = 100;
65     DWORD time = GetTickCount() + diff;
66
67     while (diff > 0)
68     {
69         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
70         while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
71         diff = time - GetTickCount();
72     }
73 }
74
75 static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND device_window, HWND focus_window, BOOL windowed)
76 {
77     D3DPRESENT_PARAMETERS present_parameters = {0};
78     IDirect3DDevice8 *device;
79
80     present_parameters.Windowed = windowed;
81     present_parameters.hDeviceWindow = device_window;
82     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
83     present_parameters.BackBufferWidth = screen_width;
84     present_parameters.BackBufferHeight = screen_height;
85     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
86     present_parameters.EnableAutoDepthStencil = TRUE;
87     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
88
89     if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
90             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
91
92     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
93     if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
94             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
95
96     if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
97             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
98
99     return NULL;
100 }
101
102 static HRESULT reset_device(IDirect3DDevice8 *device, HWND device_window, BOOL windowed)
103 {
104     D3DPRESENT_PARAMETERS present_parameters = {0};
105
106     present_parameters.Windowed = windowed;
107     present_parameters.hDeviceWindow = device_window;
108     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
109     present_parameters.BackBufferWidth = screen_width;
110     present_parameters.BackBufferHeight = screen_height;
111     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
112     present_parameters.EnableAutoDepthStencil = TRUE;
113     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
114
115     return IDirect3DDevice8_Reset(device, &present_parameters);
116 }
117
118 #define CHECK_CALL(r,c,d,rc) \
119     if (SUCCEEDED(r)) {\
120         int tmp1 = get_refcount( (IUnknown *)d ); \
121         int rc_new = rc; \
122         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
123     } else {\
124         trace("%s failed: %#08x\n", c, r); \
125     }
126
127 #define CHECK_RELEASE(obj,d,rc) \
128     if (obj) { \
129         int tmp1, rc_new = rc; \
130         IUnknown_Release( (IUnknown*)obj ); \
131         tmp1 = get_refcount( (IUnknown *)d ); \
132         ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
133     }
134
135 #define CHECK_REFCOUNT(obj,rc) \
136     { \
137         int rc_new = rc; \
138         int count = get_refcount( (IUnknown *)obj ); \
139         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
140     }
141
142 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
143     { \
144         int rc_new = rc; \
145         int count = IUnknown_Release( (IUnknown *)obj ); \
146         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
147     }
148
149 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
150     { \
151         int rc_new = rc; \
152         int count = IUnknown_AddRef( (IUnknown *)obj ); \
153         ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
154     }
155
156 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
157     { \
158         void *container_ptr = (void *)0x1337c0d3; \
159         hr = IDirect3DSurface8_GetContainer(obj, &iid, &container_ptr); \
160         ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#08x, container_ptr %p. " \
161             "Expected hr %#08x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
162         if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
163     }
164
165 static void check_mipmap_levels(IDirect3DDevice8 *device, UINT width, UINT height, UINT count)
166 {
167     IDirect3DBaseTexture8* texture = NULL;
168     HRESULT hr = IDirect3DDevice8_CreateTexture( device, width, height, 0, 0,
169             D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture8**) &texture );
170
171     if (SUCCEEDED(hr)) {
172         DWORD levels = IDirect3DBaseTexture8_GetLevelCount(texture);
173         ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
174     } else
175         trace("CreateTexture failed: %#08x\n", hr);
176
177     if (texture) IDirect3DBaseTexture8_Release( texture );
178 }
179
180 static void test_mipmap_levels(void)
181 {
182
183     HRESULT               hr;
184     HWND                  hwnd = NULL;
185
186     IDirect3D8            *pD3d = NULL;
187     IDirect3DDevice8      *pDevice = NULL;
188     D3DPRESENT_PARAMETERS d3dpp;
189     D3DDISPLAYMODE        d3ddm;
190
191     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
192     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
193     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
194     ok(hwnd != NULL, "Failed to create window\n");
195     if (!pD3d || !hwnd) goto cleanup;
196
197     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
198     ZeroMemory( &d3dpp, sizeof(d3dpp) );
199     d3dpp.Windowed         = TRUE;
200     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
201     d3dpp.BackBufferFormat = d3ddm.Format;
202
203     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
204                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
205     if(FAILED(hr))
206     {
207         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
208         goto cleanup;
209     }
210
211     check_mipmap_levels(pDevice, 32, 32, 6);
212     check_mipmap_levels(pDevice, 256, 1, 9);
213     check_mipmap_levels(pDevice, 1, 256, 9);
214     check_mipmap_levels(pDevice, 1, 1, 1);
215
216 cleanup:
217     if (pDevice)
218     {
219         UINT refcount = IDirect3DDevice8_Release( pDevice );
220         ok(!refcount, "Device has %u references left.\n", refcount);
221     }
222     if (pD3d) IDirect3D8_Release( pD3d );
223     DestroyWindow( hwnd );
224 }
225
226 static void test_swapchain(void)
227 {
228     HRESULT                      hr;
229     HWND                         hwnd               = NULL;
230     IDirect3D8                  *pD3d               = NULL;
231     IDirect3DDevice8            *pDevice            = NULL;
232     IDirect3DSwapChain8         *swapchain1         = NULL;
233     IDirect3DSwapChain8         *swapchain2         = NULL;
234     IDirect3DSwapChain8         *swapchain3         = NULL;
235     IDirect3DSurface8           *backbuffer         = NULL;
236     D3DPRESENT_PARAMETERS        d3dpp;
237     D3DDISPLAYMODE               d3ddm;
238
239     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
240     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
241     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
242     ok(hwnd != NULL, "Failed to create window\n");
243     if (!pD3d || !hwnd) goto cleanup;
244
245     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
246     ZeroMemory( &d3dpp, sizeof(d3dpp) );
247     d3dpp.Windowed         = TRUE;
248     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
249     d3dpp.BackBufferFormat = d3ddm.Format;
250     d3dpp.BackBufferCount  = 0;
251
252     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
253                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
254     if(FAILED(hr))
255     {
256         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
257         goto cleanup;
258     }
259
260     /* Check if the back buffer count was modified */
261     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
262
263     /* Create a bunch of swapchains */
264     d3dpp.BackBufferCount = 0;
265     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
266     ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
267     ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
268
269     d3dpp.BackBufferCount  = 1;
270     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
271     ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
272
273     d3dpp.BackBufferCount  = 2;
274     hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
275     ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
276     if(SUCCEEDED(hr)) {
277         /* Swapchain 3, created with backbuffercount 2 */
278         backbuffer = (void *) 0xdeadbeef;
279         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
280         ok(SUCCEEDED(hr), "Failed to get the 1st 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, 1, 0, &backbuffer);
286         ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%#08x)\n", hr);
287         ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
288         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
289
290         backbuffer = (void *) 0xdeadbeef;
291         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
292         ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#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         backbuffer = (void *) 0xdeadbeef;
297         hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
298         ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
299         ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
300         if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
301     }
302
303     /* Check the back buffers of the swapchains */
304     /* Swapchain 1, created with backbuffercount 0 */
305     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
306     ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
307     ok(backbuffer != NULL, "The back buffer is NULL (%#08x)\n", hr);
308     if(backbuffer) IDirect3DSurface8_Release(backbuffer);
309
310     backbuffer = (void *) 0xdeadbeef;
311     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
312     ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
313     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
314     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
315
316     /* Swapchain 2 - created with backbuffercount 1 */
317     backbuffer = (void *) 0xdeadbeef;
318     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
319     ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
320     ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
321     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
322
323     backbuffer = (void *) 0xdeadbeef;
324     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
325     ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#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     backbuffer = (void *) 0xdeadbeef;
330     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
331     ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
332     ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
333     if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
334
335 cleanup:
336     if(swapchain1) IDirect3DSwapChain8_Release(swapchain1);
337     if(swapchain2) IDirect3DSwapChain8_Release(swapchain2);
338     if(swapchain3) IDirect3DSwapChain8_Release(swapchain3);
339     if (pDevice)
340     {
341         UINT refcount = IDirect3DDevice8_Release(pDevice);
342         ok(!refcount, "Device has %u references left.\n", refcount);
343     }
344     if (pD3d) IDirect3D8_Release(pD3d);
345     DestroyWindow( hwnd );
346 }
347
348 static void test_refcount(void)
349 {
350     HRESULT                      hr;
351     HWND                         hwnd               = NULL;
352     IDirect3D8                  *pD3d               = NULL;
353     IDirect3D8                  *pD3d2              = NULL;
354     IDirect3DDevice8            *pDevice            = NULL;
355     IDirect3DVertexBuffer8      *pVertexBuffer      = NULL;
356     IDirect3DIndexBuffer8       *pIndexBuffer       = NULL;
357     DWORD                       dVertexShader       = -1;
358     DWORD                       dPixelShader        = -1;
359     IDirect3DCubeTexture8       *pCubeTexture       = NULL;
360     IDirect3DTexture8           *pTexture           = NULL;
361     IDirect3DVolumeTexture8     *pVolumeTexture     = NULL;
362     IDirect3DVolume8            *pVolumeLevel       = NULL;
363     IDirect3DSurface8           *pStencilSurface    = NULL;
364     IDirect3DSurface8           *pImageSurface      = NULL;
365     IDirect3DSurface8           *pRenderTarget      = NULL;
366     IDirect3DSurface8           *pRenderTarget2     = NULL;
367     IDirect3DSurface8           *pRenderTarget3     = NULL;
368     IDirect3DSurface8           *pTextureLevel      = NULL;
369     IDirect3DSurface8           *pBackBuffer        = NULL;
370     DWORD                       dStateBlock         = -1;
371     IDirect3DSwapChain8         *pSwapChain         = NULL;
372     D3DCAPS8                    caps;
373
374     D3DPRESENT_PARAMETERS        d3dpp;
375     D3DDISPLAYMODE               d3ddm;
376     int                          refcount = 0, tmp;
377
378     DWORD decl[] =
379     {
380         D3DVSD_STREAM(0),
381         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
382         D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
383         D3DVSD_END()
384     };
385
386     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
387     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
388     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
389     ok(hwnd != NULL, "Failed to create window\n");
390     if (!pD3d || !hwnd) goto cleanup;
391
392     CHECK_REFCOUNT( pD3d, 1 );
393
394     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
395     ZeroMemory( &d3dpp, sizeof(d3dpp) );
396     d3dpp.Windowed         = TRUE;
397     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
398     d3dpp.BackBufferFormat = d3ddm.Format;
399     d3dpp.EnableAutoDepthStencil = TRUE;
400     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
401
402     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
403                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
404     if(FAILED(hr))
405     {
406         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
407         goto cleanup;
408     }
409     IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
410
411     refcount = get_refcount( (IUnknown *)pDevice );
412     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
413
414     CHECK_REFCOUNT( pD3d, 2 );
415
416     hr = IDirect3DDevice8_GetDirect3D(pDevice, &pD3d2);
417     CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
418
419     ok(pD3d2 == pD3d, "Expected IDirect3D8 pointers to be equal\n");
420     CHECK_REFCOUNT( pD3d, 3 );
421     CHECK_RELEASE_REFCOUNT( pD3d, 2 );
422
423     /**
424      * Check refcount of implicit surfaces. Findings:
425      *   - the container is the device
426      *   - they hold a reference to the device
427      *   - they are created with a refcount of 0 (Get/Release returns original refcount)
428      *   - they are not freed if refcount reaches 0.
429      *   - the refcount is not forwarded to the container.
430      */
431     hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
432     CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
433     if(pRenderTarget)
434     {
435         CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DDevice8, pDevice);
436         CHECK_REFCOUNT( pRenderTarget, 1);
437
438         CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
439         CHECK_REFCOUNT(pDevice, refcount);
440         CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
441         CHECK_REFCOUNT(pDevice, refcount);
442
443         hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
444         CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
445         CHECK_REFCOUNT( pRenderTarget, 2);
446         CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
447         CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
448         CHECK_REFCOUNT( pDevice, --refcount);
449
450         /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
451         CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
452         CHECK_REFCOUNT(pDevice, ++refcount);
453         CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
454         CHECK_REFCOUNT(pDevice, --refcount);
455     }
456
457     /* Render target and back buffer are identical. */
458     hr = IDirect3DDevice8_GetBackBuffer(pDevice, 0, 0, &pBackBuffer);
459     CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
460     if(pBackBuffer)
461     {
462         CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
463         ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
464            pRenderTarget, pBackBuffer);
465         pBackBuffer = NULL;
466     }
467     CHECK_REFCOUNT( pDevice, --refcount);
468
469     hr = IDirect3DDevice8_GetDepthStencilSurface(pDevice, &pStencilSurface);
470     CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
471     if(pStencilSurface)
472     {
473         CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice8, pDevice);
474         CHECK_REFCOUNT( pStencilSurface, 1);
475
476         CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
477         CHECK_REFCOUNT(pDevice, refcount);
478         CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
479         CHECK_REFCOUNT(pDevice, refcount);
480
481         CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
482         CHECK_REFCOUNT( pDevice, --refcount);
483
484         /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
485         CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
486         CHECK_REFCOUNT(pDevice, ++refcount);
487         CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
488         CHECK_REFCOUNT(pDevice, --refcount);
489         pStencilSurface = NULL;
490     }
491
492     /* Buffers */
493     hr = IDirect3DDevice8_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer );
494     CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
495     if(pIndexBuffer)
496     {
497         tmp = get_refcount( (IUnknown *)pIndexBuffer );
498
499         hr = IDirect3DDevice8_SetIndices(pDevice, pIndexBuffer, 0);
500         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
501         hr = IDirect3DDevice8_SetIndices(pDevice, NULL, 0);
502         CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
503     }
504
505     hr = IDirect3DDevice8_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer );
506     CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
507     if(pVertexBuffer)
508     {
509         IDirect3DVertexBuffer8 *pVBuf = (void*)~0;
510         UINT stride = ~0;
511
512         tmp = get_refcount( (IUnknown *)pVertexBuffer );
513
514         hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, pVertexBuffer, 3 * sizeof(float));
515         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
516         hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, NULL, 0);
517         CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
518
519         hr = IDirect3DDevice8_GetStreamSource(pDevice, 0, &pVBuf, &stride);
520         ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
521         ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
522         ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
523     }
524
525     /* Shaders */
526     hr = IDirect3DDevice8_CreateVertexShader( pDevice, decl, simple_vs, &dVertexShader, 0 );
527     CHECK_CALL( hr, "CreateVertexShader", pDevice, refcount );
528     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
529     {
530         hr = IDirect3DDevice8_CreatePixelShader( pDevice, simple_ps, &dPixelShader );
531         CHECK_CALL( hr, "CreatePixelShader", pDevice, refcount );
532     }
533     /* Textures */
534     hr = IDirect3DDevice8_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture );
535     CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
536     if (pTexture)
537     {
538         tmp = get_refcount( (IUnknown *)pTexture );
539
540         /* SetTexture should not increase refcounts */
541         hr = IDirect3DDevice8_SetTexture(pDevice, 0, (IDirect3DBaseTexture8 *) pTexture);
542         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
543         hr = IDirect3DDevice8_SetTexture(pDevice, 0, NULL);
544         CHECK_CALL( hr, "SetTexture", pTexture, tmp);
545
546         /* This should not increment device refcount */
547         hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
548         CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
549         /* But should increment texture's refcount */
550         CHECK_REFCOUNT( pTexture, tmp+1 );
551         /* Because the texture and surface refcount are identical */
552         if (pTextureLevel)
553         {
554             CHECK_REFCOUNT        ( pTextureLevel, tmp+1 );
555             CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
556             CHECK_REFCOUNT        ( pTexture     , tmp+2 );
557             CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
558             CHECK_REFCOUNT        ( pTexture     , tmp+1 );
559             CHECK_RELEASE_REFCOUNT( pTexture     , tmp   );
560             CHECK_REFCOUNT        ( pTextureLevel, tmp   );
561         }
562     }
563     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
564     {
565         hr = IDirect3DDevice8_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture );
566         CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
567     }
568     else
569     {
570         skip("Cube textures not supported\n");
571     }
572     if(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
573     {
574         hr = IDirect3DDevice8_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture );
575         CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
576     }
577     else
578     {
579         skip("Volume textures not supported\n");
580     }
581
582     if (pVolumeTexture)
583     {
584         tmp = get_refcount( (IUnknown *)pVolumeTexture );
585
586         /* This should not increment device refcount */
587         hr = IDirect3DVolumeTexture8_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
588         CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
589         /* But should increment volume texture's refcount */
590         CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
591         /* Because the volume texture and volume refcount are identical */
592         if (pVolumeLevel)
593         {
594             CHECK_REFCOUNT        ( pVolumeLevel  , tmp+1 );
595             CHECK_ADDREF_REFCOUNT ( pVolumeLevel  , tmp+2 );
596             CHECK_REFCOUNT        ( pVolumeTexture, tmp+2 );
597             CHECK_RELEASE_REFCOUNT( pVolumeLevel  , tmp+1 );
598             CHECK_REFCOUNT        ( pVolumeTexture, tmp+1 );
599             CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp   );
600             CHECK_REFCOUNT        ( pVolumeLevel  , tmp   );
601         }
602     }
603     /* Surfaces */
604     hr = IDirect3DDevice8_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D16, D3DMULTISAMPLE_NONE, &pStencilSurface );
605     CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
606     CHECK_REFCOUNT( pStencilSurface, 1);
607     hr = IDirect3DDevice8_CreateImageSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, &pImageSurface );
608     CHECK_CALL( hr, "CreateImageSurface", pDevice, ++refcount );
609     CHECK_REFCOUNT( pImageSurface, 1);
610     hr = IDirect3DDevice8_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget3 );
611     CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
612     CHECK_REFCOUNT( pRenderTarget3, 1);
613     /* Misc */
614     hr = IDirect3DDevice8_CreateStateBlock( pDevice, D3DSBT_ALL, &dStateBlock );
615     CHECK_CALL( hr, "CreateStateBlock", pDevice, refcount );
616     hr = IDirect3DDevice8_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
617     CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
618     if(pSwapChain)
619     {
620         /* check implicit back buffer */
621         hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
622         CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
623         CHECK_REFCOUNT( pSwapChain, 1);
624         if(pBackBuffer)
625         {
626             CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DDevice8, pDevice);
627             CHECK_REFCOUNT( pBackBuffer, 1);
628             CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
629             CHECK_REFCOUNT( pDevice, --refcount);
630
631             /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
632             CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
633             CHECK_REFCOUNT(pDevice, ++refcount);
634             CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
635             CHECK_REFCOUNT(pDevice, --refcount);
636             pBackBuffer = NULL;
637         }
638         CHECK_REFCOUNT( pSwapChain, 1);
639     }
640
641     if(pVertexBuffer)
642     {
643         BYTE *data;
644         /* Vertex buffers can be locked multiple times */
645         hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
646         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
647         hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
648         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
649         hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
650         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
651         hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
652         ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
653     }
654
655     /* The implicit render target is not freed if refcount reaches 0.
656      * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
657     hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget2);
658     CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
659     if(pRenderTarget2)
660     {
661         CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
662         ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
663            pRenderTarget, pRenderTarget2);
664         CHECK_REFCOUNT( pDevice, --refcount);
665         pRenderTarget2 = NULL;
666     }
667     pRenderTarget = NULL;
668
669 cleanup:
670     CHECK_RELEASE(pDevice,              pDevice, --refcount);
671
672     /* Buffers */
673     CHECK_RELEASE(pVertexBuffer,        pDevice, --refcount);
674     CHECK_RELEASE(pIndexBuffer,         pDevice, --refcount);
675     /* Shaders */
676     if (dVertexShader != ~0U) IDirect3DDevice8_DeleteVertexShader( pDevice, dVertexShader );
677     if (dPixelShader != ~0U) IDirect3DDevice8_DeletePixelShader( pDevice, dPixelShader );
678     /* Textures */
679     CHECK_RELEASE(pTexture,             pDevice, --refcount);
680     CHECK_RELEASE(pCubeTexture,         pDevice, --refcount);
681     CHECK_RELEASE(pVolumeTexture,       pDevice, --refcount);
682     /* Surfaces */
683     CHECK_RELEASE(pStencilSurface,      pDevice, --refcount);
684     CHECK_RELEASE(pImageSurface,        pDevice, --refcount);
685     CHECK_RELEASE(pRenderTarget3,       pDevice, --refcount);
686     /* Misc */
687     if (dStateBlock != ~0U) IDirect3DDevice8_DeleteStateBlock( pDevice, dStateBlock );
688     /* This will destroy device - cannot check the refcount here */
689     if (pSwapChain)           CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
690
691     if (pD3d)                 CHECK_RELEASE_REFCOUNT( pD3d, 0);
692
693     DestroyWindow( hwnd );
694 }
695
696 static void test_cursor(void)
697 {
698     HRESULT                      hr;
699     HWND                         hwnd               = NULL;
700     IDirect3D8                  *pD3d               = NULL;
701     IDirect3DDevice8            *pDevice            = NULL;
702     D3DPRESENT_PARAMETERS        d3dpp;
703     D3DDISPLAYMODE               d3ddm;
704     CURSORINFO                   info;
705     IDirect3DSurface8 *cursor = NULL;
706     HCURSOR cur;
707     HMODULE user32_handle = GetModuleHandleA("user32.dll");
708
709     pGetCursorInfo = (void *)GetProcAddress(user32_handle, "GetCursorInfo");
710     if (!pGetCursorInfo)
711     {
712         win_skip("GetCursorInfo is not available\n");
713         return;
714     }
715
716     memset(&info, 0, sizeof(info));
717     info.cbSize = sizeof(info);
718     ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
719     cur = info.hCursor;
720
721     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
722     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
723     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
724     ok(hwnd != NULL, "Failed to create window\n");
725     if (!pD3d || !hwnd) goto cleanup;
726
727     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
728     ZeroMemory( &d3dpp, sizeof(d3dpp) );
729     d3dpp.Windowed         = TRUE;
730     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
731     d3dpp.BackBufferFormat = d3ddm.Format;
732
733     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
734                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
735     if(FAILED(hr))
736     {
737         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
738         goto cleanup;
739     }
740
741     IDirect3DDevice8_CreateImageSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, &cursor);
742     ok(cursor != NULL, "IDirect3DDevice8_CreateOffscreenPlainSurface failed with %#08x\n", hr);
743
744     /* Initially hidden */
745     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
746     ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
747
748     /* Not enabled without a surface*/
749     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
750     ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
751
752     /* Fails */
753     hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, NULL);
754     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
755
756     hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, cursor);
757     ok(hr == D3D_OK, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
758
759     IDirect3DSurface8_Release(cursor);
760
761     memset(&info, 0, sizeof(info));
762     info.cbSize = sizeof(info);
763     ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
764     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
765     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
766
767     /* Still hidden */
768     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
769     ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
770
771     /* Enabled now*/
772     hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
773     ok(hr == TRUE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
774
775     /* GDI cursor unchanged */
776     memset(&info, 0, sizeof(info));
777     info.cbSize = sizeof(info);
778     ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
779     ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
780     ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
781
782 cleanup:
783     if (pDevice)
784     {
785         UINT refcount = IDirect3DDevice8_Release(pDevice);
786         ok(!refcount, "Device has %u references left.\n", refcount);
787     }
788     if (pD3d) IDirect3D8_Release(pD3d);
789     DestroyWindow(hwnd);
790 }
791
792 static const POINT *expect_pos;
793
794 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
795 {
796     if (message == WM_MOUSEMOVE)
797     {
798         if (expect_pos && expect_pos->x && expect_pos->y)
799         {
800             POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
801
802             ClientToScreen(window, &p);
803             if (expect_pos->x == p.x && expect_pos->y == p.y)
804                 ++expect_pos;
805         }
806     }
807
808     return DefWindowProcA(window, message, wparam, lparam);
809 }
810
811 static void test_cursor_pos(void)
812 {
813     IDirect3DSurface8 *cursor;
814     IDirect3DDevice8 *device;
815     WNDCLASSA wc = {0};
816     IDirect3D8 *d3d8;
817     UINT refcount;
818     HWND window;
819     HRESULT hr;
820     BOOL ret;
821
822     /* Note that we don't check for movement we're not supposed to receive.
823      * That's because it's hard to distinguish from the user accidentally
824      * moving the mouse. */
825     static const POINT points[] =
826     {
827         {50, 50},
828         {75, 75},
829         {100, 100},
830         {125, 125},
831         {150, 150},
832         {125, 125},
833         {150, 150},
834         {150, 150},
835         {0, 0},
836     };
837
838     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
839     {
840         skip("Failed to create IDirect3D8 object, skipping cursor tests.\n");
841         return;
842     }
843
844     wc.lpfnWndProc = test_cursor_proc;
845     wc.lpszClassName = "d3d8_test_cursor_wc";
846     ok(RegisterClassA(&wc), "Failed to register window class.\n");
847     window = CreateWindow("d3d8_test_cursor_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
848             0, 0, 320, 240, NULL, NULL, NULL, NULL);
849     ShowWindow(window, SW_SHOW);
850
851     device = create_device(d3d8, window, window, TRUE);
852     if (!device)
853     {
854         skip("Failed to create a D3D device, skipping tests.\n");
855         goto done;
856     }
857
858     hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
859     ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
860     hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
861     ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
862     IDirect3DSurface8_Release(cursor);
863     ret = IDirect3DDevice8_ShowCursor(device, TRUE);
864     ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
865
866     flush_events();
867     expect_pos = points;
868
869     ret = SetCursorPos(50, 50);
870     ok(ret, "Failed to set cursor position.\n");
871     flush_events();
872
873     IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
874     flush_events();
875     /* SetCursorPosition() eats duplicates. */
876     IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
877     flush_events();
878
879     ret = SetCursorPos(100, 100);
880     ok(ret, "Failed to set cursor position.\n");
881     flush_events();
882     /* Even if the position was set with SetCursorPos(). */
883     IDirect3DDevice8_SetCursorPosition(device, 100, 100, 0);
884     flush_events();
885
886     IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
887     flush_events();
888     ret = SetCursorPos(150, 150);
889     ok(ret, "Failed to set cursor position.\n");
890     flush_events();
891     IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
892     flush_events();
893
894     IDirect3DDevice8_SetCursorPosition(device, 150, 150, 0);
895     flush_events();
896     /* SetCursorPos() doesn't. */
897     ret = SetCursorPos(150, 150);
898     ok(ret, "Failed to set cursor position.\n");
899     flush_events();
900
901     ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
902        (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
903
904     refcount = IDirect3DDevice8_Release(device);
905     ok(!refcount, "Device has %u references left.\n", refcount);
906 done:
907     DestroyWindow(window);
908     UnregisterClassA("d3d8_test_cursor_wc", GetModuleHandleA(NULL));
909     if (d3d8)
910         IDirect3D8_Release(d3d8);
911 }
912
913 static void test_states(void)
914 {
915     HRESULT                      hr;
916     HWND                         hwnd               = NULL;
917     IDirect3D8                  *pD3d               = NULL;
918     IDirect3DDevice8            *pDevice            = NULL;
919     D3DPRESENT_PARAMETERS        d3dpp;
920     D3DDISPLAYMODE               d3ddm;
921
922     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
923     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
924     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
925     ok(hwnd != NULL, "Failed to create window\n");
926     if (!pD3d || !hwnd) goto cleanup;
927
928     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
929     ZeroMemory( &d3dpp, sizeof(d3dpp) );
930     d3dpp.Windowed         = TRUE;
931     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
932     d3dpp.BackBufferWidth  = screen_width;
933     d3dpp.BackBufferHeight = screen_height;
934     d3dpp.BackBufferFormat = d3ddm.Format;
935
936     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
937                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
938     if(FAILED(hr))
939     {
940         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
941         goto cleanup;
942     }
943
944     hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, TRUE);
945     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, TRUE) returned %#08x\n", hr);
946     hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, FALSE);
947     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, FALSE) returned %#08x\n", hr);
948
949 cleanup:
950     if (pDevice)
951     {
952         UINT refcount = IDirect3DDevice8_Release(pDevice);
953         ok(!refcount, "Device has %u references left.\n", refcount);
954     }
955     if (pD3d) IDirect3D8_Release(pD3d);
956     DestroyWindow(hwnd);
957 }
958
959 static void test_shader_versions(void)
960 {
961     HRESULT                      hr;
962     IDirect3D8                  *pD3d               = NULL;
963     D3DCAPS8                     d3dcaps;
964
965     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
966     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
967     if (pD3d != NULL) {
968         hr = IDirect3D8_GetDeviceCaps(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);
969         ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to get D3D8 caps (%#08x)\n", hr);
970         if (SUCCEEDED(hr)) {
971             ok(d3dcaps.VertexShaderVersion <= D3DVS_VERSION(1,1), "Unexpected VertexShaderVersion (%#x > %#x)\n", d3dcaps.VertexShaderVersion, D3DVS_VERSION(1,1));
972             ok(d3dcaps.PixelShaderVersion <= D3DPS_VERSION(1,4), "Unexpected PixelShaderVersion (%#x > %#x)\n", d3dcaps.PixelShaderVersion, D3DPS_VERSION(1,4));
973         } else {
974             skip("No Direct3D support\n");
975         }
976         IDirect3D8_Release(pD3d);
977     }
978 }
979
980
981 /* Test adapter display modes */
982 static void test_display_modes(void)
983 {
984     UINT max_modes, i;
985     D3DDISPLAYMODE dmode;
986     HRESULT res;
987     IDirect3D8 *pD3d;
988
989     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
990     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
991     if(!pD3d) return;
992
993     max_modes = IDirect3D8_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT);
994     ok(max_modes > 0 ||
995        broken(max_modes == 0), /* VMware */
996        "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
997
998     for(i=0; i<max_modes;i++) {
999         res = IDirect3D8_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, i, &dmode);
1000         ok(res==D3D_OK, "EnumAdapterModes returned %#08x for mode %u!\n", res, i);
1001         if(res != D3D_OK)
1002             continue;
1003
1004         ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
1005            "Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
1006     }
1007
1008     IDirect3D8_Release(pD3d);
1009 }
1010
1011 static void test_reset(void)
1012 {
1013     UINT width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1014     UINT height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1015     IDirect3DDevice8 *device1 = NULL;
1016     IDirect3DDevice8 *device2 = NULL;
1017     D3DDISPLAYMODE d3ddm, d3ddm2;
1018     D3DSURFACE_DESC surface_desc;
1019     D3DPRESENT_PARAMETERS d3dpp;
1020     IDirect3DSurface8 *surface;
1021     IDirect3DTexture8 *texture;
1022     UINT adapter_mode_count;
1023     D3DLOCKED_RECT lockrect;
1024     IDirect3D8 *d3d8 = NULL;
1025     UINT mode_count = 0;
1026     HWND window = NULL;
1027     RECT winrect;
1028     D3DVIEWPORT8 vp;
1029     D3DCAPS8 caps;
1030     DWORD shader;
1031     DWORD value;
1032     HRESULT hr;
1033     UINT i;
1034
1035     static const DWORD decl[] =
1036     {
1037         D3DVSD_STREAM(0),
1038         D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT4),
1039         D3DVSD_END(),
1040     };
1041
1042     struct
1043     {
1044         UINT w;
1045         UINT h;
1046     } *modes = NULL;
1047
1048     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
1049     ok(!!d3d8, "Failed to create IDirect3D8 object.\n");
1050     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1051             100, 100, 160, 160, NULL, NULL, NULL, NULL);
1052     ok(!!window, "Failed to create window.\n");
1053     if (!d3d8 || !window)
1054         goto cleanup;
1055
1056     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1057     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1058     adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
1059     modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1060     for (i = 0; i < adapter_mode_count; ++i)
1061     {
1062         UINT j;
1063
1064         memset(&d3ddm2, 0, sizeof(d3ddm2));
1065         hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm2);
1066         ok(SUCCEEDED(hr), "EnumAdapterModes failed, hr %#x.\n", hr);
1067
1068         if (d3ddm2.Format != d3ddm.Format)
1069             continue;
1070
1071         for (j = 0; j < mode_count; ++j)
1072         {
1073             if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1074                 break;
1075         }
1076         if (j == mode_count)
1077         {
1078             modes[j].w = d3ddm2.Width;
1079             modes[j].h = d3ddm2.Height;
1080             ++mode_count;
1081         }
1082
1083         /* We use them as invalid modes. */
1084         if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
1085                 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
1086         {
1087             skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
1088                     d3ddm2.Width, d3ddm2.Height);
1089             goto cleanup;
1090         }
1091     }
1092
1093     if (mode_count < 2)
1094     {
1095         skip("Less than 2 modes supported, skipping mode tests.\n");
1096         goto cleanup;
1097     }
1098
1099     i = 0;
1100     if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1101
1102     memset(&d3dpp, 0, sizeof(d3dpp));
1103     d3dpp.Windowed = FALSE;
1104     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1105     d3dpp.BackBufferWidth = modes[i].w;
1106     d3dpp.BackBufferHeight = modes[i].h;
1107     d3dpp.BackBufferFormat = d3ddm.Format;
1108     d3dpp.EnableAutoDepthStencil = TRUE;
1109     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1110
1111     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1112             window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
1113     if (FAILED(hr))
1114     {
1115         skip("Failed to create device, hr %#x.\n", hr);
1116         goto cleanup;
1117     }
1118     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1119     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1120
1121     hr = IDirect3DDevice8_GetDeviceCaps(device1, &caps);
1122     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1123
1124     width = GetSystemMetrics(SM_CXSCREEN);
1125     height = GetSystemMetrics(SM_CYSCREEN);
1126     ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1127     ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1128
1129     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1130     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1131     if (SUCCEEDED(hr))
1132     {
1133         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1134         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1135         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1136         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1137         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1138         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1139     }
1140
1141     i = 1;
1142     vp.X = 10;
1143     vp.Y = 20;
1144     vp.Width = modes[i].w  / 2;
1145     vp.Height = modes[i].h / 2;
1146     vp.MinZ = 0.2f;
1147     vp.MaxZ = 0.3f;
1148     hr = IDirect3DDevice8_SetViewport(device1, &vp);
1149     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1150
1151     hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1152     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1153     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1154     hr = IDirect3DDevice8_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1155     ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1156
1157     memset(&d3dpp, 0, sizeof(d3dpp));
1158     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1159     d3dpp.Windowed = FALSE;
1160     d3dpp.BackBufferWidth = modes[i].w;
1161     d3dpp.BackBufferHeight = modes[i].h;
1162     d3dpp.BackBufferFormat = d3ddm.Format;
1163     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1164     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1165     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1166     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1167
1168     hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1169     ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1170     ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1171
1172     memset(&vp, 0, sizeof(vp));
1173     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1174     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1175     if (SUCCEEDED(hr))
1176     {
1177         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1178         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1179         ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1180         ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1181         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1182         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1183     }
1184
1185     width = GetSystemMetrics(SM_CXSCREEN);
1186     height = GetSystemMetrics(SM_CYSCREEN);
1187     ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1188     ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1189
1190     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1191     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1192     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1193     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1194     ok(surface_desc.Width == modes[i].w, "Back buffer width is %u, expected %u.\n",
1195             surface_desc.Width, modes[i].w);
1196     ok(surface_desc.Height == modes[i].h, "Back buffer height is %u, expected %u.\n",
1197             surface_desc.Height, modes[i].h);
1198     IDirect3DSurface8_Release(surface);
1199
1200     memset(&d3dpp, 0, sizeof(d3dpp));
1201     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1202     d3dpp.Windowed = TRUE;
1203     d3dpp.BackBufferWidth = 400;
1204     d3dpp.BackBufferHeight = 300;
1205     d3dpp.BackBufferFormat = d3ddm.Format;
1206     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1207     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1208     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1209     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1210
1211     memset(&vp, 0, sizeof(vp));
1212     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1213     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1214     if (SUCCEEDED(hr))
1215     {
1216         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1217         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1218         ok(vp.Width == 400, "D3DVIEWPORT->Width = %u, expected 400.\n", vp.Width);
1219         ok(vp.Height == 300, "D3DVIEWPORT->Height = %u, expected 300.\n", vp.Height);
1220         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1221         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1222     }
1223
1224     width = GetSystemMetrics(SM_CXSCREEN);
1225     height = GetSystemMetrics(SM_CYSCREEN);
1226     ok(width == orig_width, "Screen width is %u, expected %u.\n", width, orig_width);
1227     ok(height == orig_height, "Screen height is %u, expected %u.\n", height, orig_height);
1228
1229     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1230     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1231     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1232     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1233     ok(surface_desc.Width == 400, "Back buffer width is %u, expected 400.\n",
1234             surface_desc.Width);
1235     ok(surface_desc.Height == 300, "Back buffer height is %u, expected 300.\n",
1236             surface_desc.Height);
1237     IDirect3DSurface8_Release(surface);
1238
1239     winrect.left = 0;
1240     winrect.top = 0;
1241     winrect.right = 200;
1242     winrect.bottom = 150;
1243     ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1244     ok(SetWindowPos(window, NULL, 0, 0,
1245                     winrect.right-winrect.left,
1246                     winrect.bottom-winrect.top,
1247                     SWP_NOMOVE|SWP_NOZORDER),
1248        "SetWindowPos failed\n");
1249
1250     memset(&d3dpp, 0, sizeof(d3dpp));
1251     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1252     d3dpp.Windowed = TRUE;
1253     d3dpp.BackBufferWidth = 0;
1254     d3dpp.BackBufferHeight = 0;
1255     d3dpp.BackBufferFormat = d3ddm.Format;
1256     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1257     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1258     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1259     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1260
1261     memset(&vp, 0, sizeof(vp));
1262     hr = IDirect3DDevice8_GetViewport(device1, &vp);
1263     ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1264     if (SUCCEEDED(hr))
1265     {
1266         ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1267         ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1268         todo_wine ok(vp.Width == 200, "D3DVIEWPORT->Width = %u, expected 200.\n", vp.Width);
1269         todo_wine ok(vp.Height == 150, "D3DVIEWPORT->Height = %u, expected 150.\n", vp.Height);
1270         ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1271         ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1272     }
1273
1274     hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1275     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1276     hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1277     ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1278     todo_wine ok(surface_desc.Width == 200, "Back buffer width is %u, expected 200.\n",
1279                  surface_desc.Width);
1280     todo_wine ok(surface_desc.Height == 150, "Back buffer height is %u, expected 150.\n",
1281                  surface_desc.Height);
1282     IDirect3DSurface8_Release(surface);
1283
1284     memset(&d3dpp, 0, sizeof(d3dpp));
1285     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1286     d3dpp.Windowed = TRUE;
1287     d3dpp.BackBufferWidth = 400;
1288     d3dpp.BackBufferHeight = 300;
1289     d3dpp.BackBufferFormat = d3ddm.Format;
1290
1291     /* Reset fails if there is a resource in the default pool. */
1292     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texture);
1293     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1294     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1295     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1296     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1297     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1298     IDirect3DTexture8_Release(texture);
1299     /* Reset again to get the device out of the lost state. */
1300     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1301     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1302     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1303     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1304
1305     if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1306     {
1307         IDirect3DVolumeTexture8 *volume_texture;
1308
1309         hr = IDirect3DDevice8_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1310                 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture);
1311         ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1312         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1313         ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1314         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1315         ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1316                 hr, D3DERR_DEVICENOTRESET);
1317         IDirect3DVolumeTexture8_Release(volume_texture);
1318         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1319         ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1320         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1321         ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1322     }
1323     else
1324     {
1325         skip("Volume textures not supported.\n");
1326     }
1327
1328     /* Scratch, sysmem and managed pool resources are fine. */
1329     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1330     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1331     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1332     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1333     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1334     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1335     IDirect3DTexture8_Release(texture);
1336
1337     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1338     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1339     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1340     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1341     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1342     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1343     IDirect3DTexture8_Release(texture);
1344
1345     /* The depth stencil should get reset to the auto depth stencil when present. */
1346     hr = IDirect3DDevice8_SetRenderTarget(device1, NULL, NULL);
1347     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1348
1349     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1350     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1351     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1352
1353     d3dpp.EnableAutoDepthStencil = TRUE;
1354     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1355     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1356     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1357
1358     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1359     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1360     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1361     if (surface) IDirect3DSurface8_Release(surface);
1362
1363     d3dpp.EnableAutoDepthStencil = FALSE;
1364     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1365     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1366
1367     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1368     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1369     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1370
1371     /* Will a sysmem or scratch resource survive while locked? */
1372     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1373     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1374     hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1375     ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1376     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1377     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1378     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1379     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1380     IDirect3DTexture8_UnlockRect(texture, 0);
1381     IDirect3DTexture8_Release(texture);
1382
1383     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1384     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1385     hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1386     ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1387     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1388     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1389     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1390     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1391     IDirect3DTexture8_UnlockRect(texture, 0);
1392     IDirect3DTexture8_Release(texture);
1393
1394     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture);
1395     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1396     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1397     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1398     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1399     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1400     IDirect3DTexture8_Release(texture);
1401
1402     /* A reference held to an implicit surface causes failures as well. */
1403     hr = IDirect3DDevice8_GetBackBuffer(device1, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1404     ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
1405     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1406     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1407     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1408     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1409     IDirect3DSurface8_Release(surface);
1410     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1411     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1412     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1413     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1414
1415     /* Shaders are fine as well. */
1416     hr = IDirect3DDevice8_CreateVertexShader(device1, decl, simple_vs, &shader, 0);
1417     ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
1418     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1419     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1420     hr = IDirect3DDevice8_DeleteVertexShader(device1, shader);
1421     ok(SUCCEEDED(hr), "DeleteVertexShader failed, hr %#x.\n", hr);
1422
1423     /* Try setting invalid modes. */
1424     memset(&d3dpp, 0, sizeof(d3dpp));
1425     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1426     d3dpp.Windowed = FALSE;
1427     d3dpp.BackBufferWidth = 32;
1428     d3dpp.BackBufferHeight = 32;
1429     d3dpp.BackBufferFormat = d3ddm.Format;
1430     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1431     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1432     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1433     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1434
1435     memset(&d3dpp, 0, sizeof(d3dpp));
1436     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1437     d3dpp.Windowed = FALSE;
1438     d3dpp.BackBufferWidth = 801;
1439     d3dpp.BackBufferHeight = 600;
1440     d3dpp.BackBufferFormat = d3ddm.Format;
1441     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1442     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1443     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1444     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1445
1446     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1447     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1448
1449     memset(&d3dpp, 0, sizeof(d3dpp));
1450     d3dpp.Windowed = TRUE;
1451     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1452     d3dpp.BackBufferFormat = d3ddm.Format;
1453     d3dpp.EnableAutoDepthStencil = FALSE;
1454     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1455
1456     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1457             window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1458     if (FAILED(hr))
1459     {
1460         skip("Failed to create device, hr %#x.\n", hr);
1461         goto cleanup;
1462     }
1463
1464     hr = IDirect3DDevice8_TestCooperativeLevel(device2);
1465     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1466
1467     d3dpp.Windowed = TRUE;
1468     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1469     d3dpp.BackBufferWidth = 400;
1470     d3dpp.BackBufferHeight = 300;
1471     d3dpp.BackBufferFormat = d3ddm.Format;
1472     d3dpp.EnableAutoDepthStencil = TRUE;
1473     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1474
1475     hr = IDirect3DDevice8_Reset(device2, &d3dpp);
1476     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1477     if (FAILED(hr))
1478         goto cleanup;
1479
1480     hr = IDirect3DDevice8_GetDepthStencilSurface(device2, &surface);
1481     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1482     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1483     if (surface)
1484         IDirect3DSurface8_Release(surface);
1485
1486 cleanup:
1487     HeapFree(GetProcessHeap(), 0, modes);
1488     if (device2)
1489         IDirect3DDevice8_Release(device2);
1490     if (device1)
1491         IDirect3DDevice8_Release(device1);
1492     if (d3d8)
1493         IDirect3D8_Release(d3d8);
1494     if (window)
1495         DestroyWindow(window);
1496 }
1497
1498 static void test_scene(void)
1499 {
1500     HRESULT                      hr;
1501     HWND                         hwnd               = NULL;
1502     IDirect3D8                  *pD3d               = NULL;
1503     IDirect3DDevice8            *pDevice            = NULL;
1504     D3DPRESENT_PARAMETERS        d3dpp;
1505     D3DDISPLAYMODE               d3ddm;
1506
1507     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1508     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1509     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1510     ok(hwnd != NULL, "Failed to create window\n");
1511     if (!pD3d || !hwnd) goto cleanup;
1512
1513     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1514     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1515     d3dpp.Windowed         = TRUE;
1516     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1517     d3dpp.BackBufferWidth  = 800;
1518     d3dpp.BackBufferHeight = 600;
1519     d3dpp.BackBufferFormat = d3ddm.Format;
1520
1521
1522     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1523                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1524     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1525     if(!pDevice)
1526     {
1527         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1528         goto cleanup;
1529     }
1530
1531     /* Test an EndScene without BeginScene. Should return an error */
1532     hr = IDirect3DDevice8_EndScene(pDevice);
1533     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1534
1535     /* Test a normal BeginScene / EndScene pair, this should work */
1536     hr = IDirect3DDevice8_BeginScene(pDevice);
1537     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1538     if(SUCCEEDED(hr))
1539     {
1540         hr = IDirect3DDevice8_EndScene(pDevice);
1541         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1542     }
1543
1544     /* Test another EndScene without having begun a new scene. Should return an error */
1545     hr = IDirect3DDevice8_EndScene(pDevice);
1546     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1547
1548     /* Two nested BeginScene and EndScene calls */
1549     hr = IDirect3DDevice8_BeginScene(pDevice);
1550     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1551     hr = IDirect3DDevice8_BeginScene(pDevice);
1552     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1553     hr = IDirect3DDevice8_EndScene(pDevice);
1554     ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1555     hr = IDirect3DDevice8_EndScene(pDevice);
1556     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1557
1558     /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
1559
1560 cleanup:
1561     if (pDevice)
1562     {
1563         UINT refcount = IDirect3DDevice8_Release(pDevice);
1564         ok(!refcount, "Device has %u references left.\n", refcount);
1565     }
1566     if (pD3d) IDirect3D8_Release(pD3d);
1567     DestroyWindow(hwnd);
1568 }
1569
1570 static void test_shader(void)
1571 {
1572     HRESULT                      hr;
1573     HWND                         hwnd               = NULL;
1574     IDirect3D8                  *pD3d               = NULL;
1575     IDirect3DDevice8            *pDevice            = NULL;
1576     D3DPRESENT_PARAMETERS        d3dpp;
1577     D3DDISPLAYMODE               d3ddm;
1578     DWORD                        hPixelShader = 0, hVertexShader = 0;
1579     DWORD                        hPixelShader2 = 0, hVertexShader2 = 0;
1580     DWORD                        hTempHandle;
1581     D3DCAPS8                     caps;
1582     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
1583     DWORD data_size;
1584     void *data;
1585
1586     static DWORD dwVertexDecl[] =
1587     {
1588         D3DVSD_STREAM(0),
1589         D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT3),
1590         D3DVSD_END()
1591     };
1592     DWORD decl_normal_float2[] =
1593     {
1594         D3DVSD_STREAM(0),
1595         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1596         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT2),  /* D3DVSDE_NORMAL,   Register v1 */
1597         D3DVSD_END()
1598     };
1599     DWORD decl_normal_float4[] =
1600     {
1601         D3DVSD_STREAM(0),
1602         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1603         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT4),  /* D3DVSDE_NORMAL,   Register v1 */
1604         D3DVSD_END()
1605     };
1606     DWORD decl_normal_d3dcolor[] =
1607     {
1608         D3DVSD_STREAM(0),
1609         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1610         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL,   Register v1 */
1611         D3DVSD_END()
1612     };
1613     const DWORD vertex_decl_size = sizeof(dwVertexDecl);
1614     const DWORD simple_vs_size = sizeof(simple_vs);
1615     const DWORD simple_ps_size = sizeof(simple_ps);
1616
1617     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1618     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1619     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1620     ok(hwnd != NULL, "Failed to create window\n");
1621     if (!pD3d || !hwnd) goto cleanup;
1622
1623     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1624     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1625     d3dpp.Windowed         = TRUE;
1626     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1627     d3dpp.BackBufferWidth  = 800;
1628     d3dpp.BackBufferHeight = 600;
1629     d3dpp.BackBufferFormat = d3ddm.Format;
1630
1631
1632     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1633                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1634     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1635     if(!pDevice)
1636     {
1637         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1638         goto cleanup;
1639     }
1640     IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
1641
1642     /* Test setting and retrieving a FVF */
1643     hr = IDirect3DDevice8_SetVertexShader(pDevice, fvf);
1644     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1645     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1646     ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1647     ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
1648
1649     /* First create a vertex shader */
1650     hr = IDirect3DDevice8_SetVertexShader(pDevice, 0);
1651     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1652     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, simple_vs, &hVertexShader, 0);
1653     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1654     /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
1655     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1656     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1657     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1658     /* Assign the shader, then verify that GetVertexShader works */
1659     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1660     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1661     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1662     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1663     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1664     /* Verify that we can retrieve the declaration */
1665     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, NULL, &data_size);
1666     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1667     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1668     data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
1669     data_size = 1;
1670     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1671     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
1672             "expected D3DERR_INVALIDCALL\n", hr);
1673     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1674     data_size = vertex_decl_size;
1675     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1676     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1677     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1678     ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
1679     HeapFree(GetProcessHeap(), 0, data);
1680     /* Verify that we can retrieve the shader function */
1681     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, NULL, &data_size);
1682     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1683     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1684     data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
1685     data_size = 1;
1686     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1687     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
1688             "expected D3DERR_INVALIDCALL\n", hr);
1689     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1690     data_size = simple_vs_size;
1691     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1692     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1693     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1694     ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
1695     HeapFree(GetProcessHeap(), 0, data);
1696     /* Delete the assigned shader. This is supposed to work */
1697     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1698     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1699     /* The shader should be unset now */
1700     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1701     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1702     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1703
1704     /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
1705      * First try the fixed function shader function, then a custom one
1706      */
1707     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, 0, &hVertexShader, 0);
1708     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1709     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1710     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float4, 0, &hVertexShader, 0);
1711     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1712     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1713     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_d3dcolor, 0, &hVertexShader, 0);
1714     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1715     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1716
1717     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, simple_vs, &hVertexShader, 0);
1718     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1719     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1720
1721     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
1722     {
1723         /* The same with a pixel shader */
1724         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1725         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1726         /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
1727         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1728         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1729         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1730         /* Assign the shader, then verify that GetPixelShader works */
1731         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1732         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1733         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1734         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1735         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1736         /* Verify that we can retrieve the shader function */
1737         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, NULL, &data_size);
1738         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1739         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1740         data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
1741         data_size = 1;
1742         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1743         ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
1744                 "expected D3DERR_INVALIDCALL\n", hr);
1745         ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1746         data_size = simple_ps_size;
1747         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1748         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1749         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1750         ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
1751         HeapFree(GetProcessHeap(), 0, data);
1752         /* Delete the assigned shader. This is supposed to work */
1753         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1754         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1755         /* The shader should be unset now */
1756         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1757         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1758         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1759
1760         /* What happens if a non-bound shader is deleted? */
1761         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1762         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1763         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader2);
1764         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1765
1766         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1767         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1768         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1769         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1770         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1771         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1772         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1773         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1774         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1775
1776         /* Check for double delete. */
1777         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1778         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1779         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1780         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1781     }
1782     else
1783     {
1784         skip("Pixel shaders not supported\n");
1785     }
1786
1787     /* What happens if a non-bound shader is deleted? */
1788     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader, 0);
1789     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1790     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader2, 0);
1791     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1792
1793     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1794     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1795     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1796     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1797     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1798     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1799     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1800     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1801     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1802
1803     /* Check for double delete. */
1804     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1805     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1806     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1807     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1808
1809 cleanup:
1810     if (pDevice)
1811     {
1812         UINT refcount = IDirect3DDevice8_Release(pDevice);
1813         ok(!refcount, "Device has %u references left.\n", refcount);
1814     }
1815     if (pD3d) IDirect3D8_Release(pD3d);
1816     DestroyWindow(hwnd);
1817 }
1818
1819 static void test_limits(void)
1820 {
1821     HRESULT                      hr;
1822     HWND                         hwnd               = NULL;
1823     IDirect3D8                  *pD3d               = NULL;
1824     IDirect3DDevice8            *pDevice            = NULL;
1825     D3DPRESENT_PARAMETERS        d3dpp;
1826     D3DDISPLAYMODE               d3ddm;
1827     IDirect3DTexture8           *pTexture           = NULL;
1828     int i;
1829
1830     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1831     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1832     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1833     ok(hwnd != NULL, "Failed to create window\n");
1834     if (!pD3d || !hwnd) goto cleanup;
1835
1836     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1837     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1838     d3dpp.Windowed         = TRUE;
1839     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1840     d3dpp.BackBufferWidth  = 800;
1841     d3dpp.BackBufferHeight = 600;
1842     d3dpp.BackBufferFormat = d3ddm.Format;
1843     d3dpp.EnableAutoDepthStencil = TRUE;
1844     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1845
1846     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1847                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1848     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1849     if(!pDevice)
1850     {
1851         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1852         goto cleanup;
1853     }
1854
1855     hr = IDirect3DDevice8_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture);
1856     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
1857     if(!pTexture) goto cleanup;
1858
1859     /* There are 8 texture stages. We should be able to access all of them */
1860     for(i = 0; i < 8; i++) {
1861         hr = IDirect3DDevice8_SetTexture(pDevice, i, (IDirect3DBaseTexture8 *) pTexture);
1862         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1863         hr = IDirect3DDevice8_SetTexture(pDevice, i, NULL);
1864         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1865         hr = IDirect3DDevice8_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1866         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
1867     }
1868
1869     /* Investigations show that accessing higher textures stage states does not return an error either. Writing
1870      * to too high texture stages(approximately texture 40) causes memory corruption in windows, so there is no
1871      * bounds checking but how do I test that?
1872      */
1873
1874 cleanup:
1875     if(pTexture) IDirect3DTexture8_Release(pTexture);
1876     if (pDevice)
1877     {
1878         UINT refcount = IDirect3DDevice8_Release(pDevice);
1879         ok(!refcount, "Device has %u references left.\n", refcount);
1880     }
1881     if (pD3d) IDirect3D8_Release(pD3d);
1882     DestroyWindow(hwnd);
1883 }
1884
1885 static void test_lights(void)
1886 {
1887     D3DPRESENT_PARAMETERS d3dpp;
1888     IDirect3DDevice8 *device = NULL;
1889     IDirect3D8 *d3d8;
1890     HWND hwnd;
1891     HRESULT hr;
1892     unsigned int i;
1893     BOOL enabled;
1894     D3DCAPS8 caps;
1895     D3DDISPLAYMODE               d3ddm;
1896
1897     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1898     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1899     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1900     ok(hwnd != NULL, "Failed to create window\n");
1901     if (!d3d8 || !hwnd) goto cleanup;
1902
1903     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1904     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1905     d3dpp.Windowed         = TRUE;
1906     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1907     d3dpp.BackBufferWidth  = 800;
1908     d3dpp.BackBufferHeight = 600;
1909     d3dpp.BackBufferFormat = d3ddm.Format;
1910     d3dpp.EnableAutoDepthStencil = TRUE;
1911     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1912
1913     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1914                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
1915     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1916        "IDirect3D8_CreateDevice failed with %08x\n", hr);
1917     if(!device)
1918     {
1919         skip("Failed to create a d3d device\n");
1920         goto cleanup;
1921     }
1922
1923     memset(&caps, 0, sizeof(caps));
1924     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1925     ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
1926
1927     for(i = 1; i <= caps.MaxActiveLights; i++) {
1928         hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
1929         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1930         hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
1931         ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
1932             "GetLightEnable on light %u failed with %08x\n", i, hr);
1933         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1934     }
1935
1936     /* TODO: Test the rendering results in this situation */
1937     hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
1938     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
1939     hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
1940     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1941     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1942     hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
1943     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1944
1945     for(i = 1; i <= caps.MaxActiveLights; i++) {
1946         hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
1947         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
1948     }
1949
1950 cleanup:
1951     if (device)
1952     {
1953         UINT refcount = IDirect3DDevice8_Release(device);
1954         ok(!refcount, "Device has %u references left.\n", refcount);
1955     }
1956     if (d3d8) IDirect3D8_Release(d3d8);
1957     DestroyWindow(hwnd);
1958 }
1959
1960 static void test_render_zero_triangles(void)
1961 {
1962     D3DPRESENT_PARAMETERS d3dpp;
1963     IDirect3DDevice8 *device = NULL;
1964     IDirect3D8 *d3d8;
1965     HWND hwnd;
1966     HRESULT hr;
1967     D3DDISPLAYMODE               d3ddm;
1968
1969     struct nvertex
1970     {
1971         float x, y, z;
1972         float nx, ny, nz;
1973         DWORD diffuse;
1974     }  quad[] =
1975     {
1976         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1977         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1978         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1979         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1980     };
1981
1982     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1983     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1984     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1985     ok(hwnd != NULL, "Failed to create window\n");
1986     if (!d3d8 || !hwnd) goto cleanup;
1987
1988     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1989     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1990     d3dpp.Windowed         = TRUE;
1991     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1992     d3dpp.BackBufferWidth  = 800;
1993     d3dpp.BackBufferHeight = 600;
1994     d3dpp.BackBufferFormat = d3ddm.Format;
1995     d3dpp.EnableAutoDepthStencil = TRUE;
1996     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1997
1998     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1999                                   D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
2000     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2001        "IDirect3D8_CreateDevice failed with %08x\n", hr);
2002     if(!device)
2003     {
2004         skip("Failed to create a d3d device\n");
2005         goto cleanup;
2006     }
2007
2008     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2009     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2010
2011     hr = IDirect3DDevice8_BeginScene(device);
2012     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
2013     if(hr == D3D_OK)
2014     {
2015         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
2016                                                     0 /*PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
2017         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
2018
2019         hr = IDirect3DDevice8_EndScene(device);
2020         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
2021     }
2022
2023     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2024
2025 cleanup:
2026     if (device)
2027     {
2028         UINT refcount = IDirect3DDevice8_Release(device);
2029         ok(!refcount, "Device has %u references left.\n", refcount);
2030     }
2031     if (d3d8) IDirect3D8_Release(d3d8);
2032     DestroyWindow(hwnd);
2033 }
2034
2035 static void test_depth_stencil_reset(void)
2036 {
2037     D3DPRESENT_PARAMETERS present_parameters;
2038     D3DDISPLAYMODE display_mode;
2039     IDirect3DSurface8 *surface, *orig_rt;
2040     IDirect3DDevice8 *device = NULL;
2041     IDirect3D8 *d3d8;
2042     UINT refcount;
2043     HRESULT hr;
2044     HWND hwnd;
2045
2046     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2047     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2048     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2049     ok(hwnd != NULL, "Failed to create window\n");
2050     if (!d3d8 || !hwnd) goto cleanup;
2051
2052     IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
2053     memset(&present_parameters, 0, sizeof(present_parameters));
2054     present_parameters.Windowed               = TRUE;
2055     present_parameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
2056     present_parameters.BackBufferFormat       = display_mode.Format;
2057     present_parameters.EnableAutoDepthStencil = TRUE;
2058     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2059
2060     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2061             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
2062     if(FAILED(hr))
2063     {
2064         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2065         goto cleanup;
2066     }
2067
2068     hr = IDirect3DDevice8_GetRenderTarget(device, &orig_rt);
2069     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2070
2071     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2072     ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
2073
2074     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2075     ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
2076
2077     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
2078     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2079     ok(surface == orig_rt, "Render target is %p, should be %p\n", surface, orig_rt);
2080     if (surface) IDirect3DSurface8_Release(surface);
2081     IDirect3DSurface8_Release(orig_rt);
2082
2083     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2084     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2085     ok(surface == NULL, "Depth stencil should be NULL\n");
2086
2087     present_parameters.EnableAutoDepthStencil = TRUE;
2088     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2089     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2090     ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2091
2092     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2093     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2094     ok(surface != NULL, "Depth stencil should not be NULL\n");
2095     if (surface) IDirect3DSurface8_Release(surface);
2096
2097     present_parameters.EnableAutoDepthStencil = FALSE;
2098     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2099     ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2100
2101     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2102     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2103     ok(surface == NULL, "Depth stencil should be NULL\n");
2104
2105     refcount = IDirect3DDevice8_Release(device);
2106     ok(!refcount, "Device has %u references left.\n", refcount);
2107     device = NULL;
2108
2109     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
2110
2111     ZeroMemory( &present_parameters, sizeof(present_parameters) );
2112     present_parameters.Windowed         = TRUE;
2113     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2114     present_parameters.BackBufferFormat = display_mode.Format;
2115     present_parameters.EnableAutoDepthStencil = FALSE;
2116     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2117
2118     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2119                     D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2120
2121     if(FAILED(hr))
2122     {
2123         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2124         goto cleanup;
2125     }
2126
2127     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2128     ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
2129
2130     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2131     present_parameters.Windowed         = TRUE;
2132     present_parameters.BackBufferWidth  = 400;
2133     present_parameters.BackBufferHeight = 300;
2134     present_parameters.EnableAutoDepthStencil = TRUE;
2135     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2136
2137     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2138     ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
2139
2140     if (FAILED(hr)) goto cleanup;
2141
2142     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2143     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2144     ok(surface != NULL, "Depth stencil should not be NULL\n");
2145     if (surface) IDirect3DSurface8_Release(surface);
2146
2147 cleanup:
2148     if (device)
2149     {
2150         refcount = IDirect3DDevice8_Release(device);
2151         ok(!refcount, "Device has %u references left.\n", refcount);
2152     }
2153     if (d3d8) IDirect3D8_Release(d3d8);
2154     DestroyWindow(hwnd);
2155 }
2156
2157 static HWND filter_messages;
2158
2159 enum message_window
2160 {
2161     DEVICE_WINDOW,
2162     FOCUS_WINDOW,
2163 };
2164
2165 struct message
2166 {
2167     UINT message;
2168     enum message_window window;
2169 };
2170
2171 static const struct message *expect_messages;
2172 static HWND device_window, focus_window;
2173
2174 struct wndproc_thread_param
2175 {
2176     HWND dummy_window;
2177     HANDLE window_created;
2178     HANDLE test_finished;
2179     BOOL running_in_foreground;
2180 };
2181
2182 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2183 {
2184     if (filter_messages && filter_messages == hwnd)
2185     {
2186         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2187             todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2188     }
2189
2190     if (expect_messages)
2191     {
2192         HWND w;
2193
2194         switch (expect_messages->window)
2195         {
2196             case DEVICE_WINDOW:
2197                 w = device_window;
2198                 break;
2199
2200             case FOCUS_WINDOW:
2201                 w = focus_window;
2202                 break;
2203
2204             default:
2205                 w = NULL;
2206                 break;
2207         };
2208
2209         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2210     }
2211
2212     return DefWindowProcA(hwnd, message, wparam, lparam);
2213 }
2214
2215 static DWORD WINAPI wndproc_thread(void *param)
2216 {
2217     struct wndproc_thread_param *p = param;
2218     DWORD res;
2219     BOOL ret;
2220
2221     p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2222             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2223     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2224
2225     ret = SetEvent(p->window_created);
2226     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2227
2228     for (;;)
2229     {
2230         MSG msg;
2231
2232         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2233         res = WaitForSingleObject(p->test_finished, 100);
2234         if (res == WAIT_OBJECT_0) break;
2235         if (res != WAIT_TIMEOUT)
2236         {
2237             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2238             break;
2239         }
2240     }
2241
2242     DestroyWindow(p->dummy_window);
2243
2244     return 0;
2245 }
2246
2247 static void test_wndproc(void)
2248 {
2249     struct wndproc_thread_param thread_params;
2250     IDirect3DDevice8 *device;
2251     WNDCLASSA wc = {0};
2252     IDirect3D8 *d3d8;
2253     HANDLE thread;
2254     LONG_PTR proc;
2255     ULONG ref;
2256     DWORD res, tid;
2257     HWND tmp;
2258
2259     static const struct message messages[] =
2260     {
2261         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2262         {WM_ACTIVATE,           FOCUS_WINDOW},
2263         {WM_SETFOCUS,           FOCUS_WINDOW},
2264         {WM_WINDOWPOSCHANGING,  DEVICE_WINDOW},
2265         {WM_MOVE,               DEVICE_WINDOW},
2266         {WM_SIZE,               DEVICE_WINDOW},
2267         {0,                     0},
2268     };
2269
2270     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2271     {
2272         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2273         return;
2274     }
2275
2276     wc.lpfnWndProc = test_proc;
2277     wc.lpszClassName = "d3d8_test_wndproc_wc";
2278     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2279
2280     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2281     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2282     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2283     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2284
2285     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2286             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2287     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2288             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2289     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2290     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2291
2292     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2293     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2294
2295     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2296     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2297             (LONG_PTR)test_proc, proc);
2298     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2299     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2300             (LONG_PTR)test_proc, proc);
2301
2302     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2303             device_window, focus_window, thread_params.dummy_window);
2304
2305     tmp = GetFocus();
2306     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2307     if (thread_params.running_in_foreground)
2308     {
2309         tmp = GetForegroundWindow();
2310         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2311                 thread_params.dummy_window, tmp);
2312     }
2313     else
2314         skip("Not running in foreground, skip foreground window test\n");
2315
2316     flush_events();
2317
2318     expect_messages = messages;
2319
2320     device = create_device(d3d8, device_window, focus_window, FALSE);
2321     if (!device)
2322     {
2323         skip("Failed to create a D3D device, skipping tests.\n");
2324         goto done;
2325     }
2326
2327     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2328             expect_messages->message, expect_messages->window);
2329     expect_messages = NULL;
2330
2331     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2332     {
2333         tmp = GetFocus();
2334         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2335         tmp = GetForegroundWindow();
2336         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2337     }
2338     SetForegroundWindow(focus_window);
2339     flush_events();
2340
2341     filter_messages = focus_window;
2342
2343     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2344     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2345             (LONG_PTR)test_proc, proc);
2346
2347     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2348     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2349             (LONG_PTR)test_proc, proc);
2350
2351     ref = IDirect3DDevice8_Release(device);
2352     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2353
2354     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2355     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2356             (LONG_PTR)test_proc, proc);
2357
2358     device = create_device(d3d8, focus_window, focus_window, FALSE);
2359     if (!device)
2360     {
2361         skip("Failed to create a D3D device, skipping tests.\n");
2362         goto done;
2363     }
2364
2365     ref = IDirect3DDevice8_Release(device);
2366     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2367
2368     device = create_device(d3d8, device_window, focus_window, FALSE);
2369     if (!device)
2370     {
2371         skip("Failed to create a D3D device, skipping tests.\n");
2372         goto done;
2373     }
2374
2375     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2376     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2377             (LONG_PTR)test_proc, proc);
2378
2379     ref = IDirect3DDevice8_Release(device);
2380     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2381
2382     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2383     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2384             (LONG_PTR)DefWindowProcA, proc);
2385
2386 done:
2387     filter_messages = NULL;
2388     IDirect3D8_Release(d3d8);
2389
2390     SetEvent(thread_params.test_finished);
2391     WaitForSingleObject(thread, INFINITE);
2392     CloseHandle(thread_params.test_finished);
2393     CloseHandle(thread_params.window_created);
2394     CloseHandle(thread);
2395
2396     DestroyWindow(device_window);
2397     DestroyWindow(focus_window);
2398     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2399 }
2400
2401 static void test_wndproc_windowed(void)
2402 {
2403     struct wndproc_thread_param thread_params;
2404     IDirect3DDevice8 *device;
2405     WNDCLASSA wc = {0};
2406     IDirect3D8 *d3d8;
2407     HANDLE thread;
2408     LONG_PTR proc;
2409     HRESULT hr;
2410     ULONG ref;
2411     DWORD res, tid;
2412     HWND tmp;
2413
2414     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2415     {
2416         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2417         return;
2418     }
2419
2420     wc.lpfnWndProc = test_proc;
2421     wc.lpszClassName = "d3d8_test_wndproc_wc";
2422     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2423
2424     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2425     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2426     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2427     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2428
2429     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2430             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2431     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2432             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2433     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2434     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2435
2436     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2437     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2438
2439     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2440     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2441             (LONG_PTR)test_proc, proc);
2442     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2443     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2444             (LONG_PTR)test_proc, proc);
2445
2446     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2447             device_window, focus_window, thread_params.dummy_window);
2448
2449     tmp = GetFocus();
2450     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2451     if (thread_params.running_in_foreground)
2452     {
2453         tmp = GetForegroundWindow();
2454         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2455                 thread_params.dummy_window, tmp);
2456     }
2457     else
2458         skip("Not running in foreground, skip foreground window test\n");
2459
2460     filter_messages = focus_window;
2461
2462     device = create_device(d3d8, device_window, focus_window, TRUE);
2463     if (!device)
2464     {
2465         skip("Failed to create a D3D device, skipping tests.\n");
2466         goto done;
2467     }
2468
2469     tmp = GetFocus();
2470     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2471     tmp = GetForegroundWindow();
2472     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2473             thread_params.dummy_window, tmp);
2474
2475     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2476     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2477             (LONG_PTR)test_proc, proc);
2478
2479     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2480     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2481             (LONG_PTR)test_proc, proc);
2482
2483     filter_messages = NULL;
2484
2485     hr = reset_device(device, device_window, FALSE);
2486     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2487
2488     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2489     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2490             (LONG_PTR)test_proc, proc);
2491
2492     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2493     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2494             (LONG_PTR)test_proc, proc);
2495
2496     hr = reset_device(device, device_window, TRUE);
2497     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2498
2499     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2500     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2501             (LONG_PTR)test_proc, proc);
2502
2503     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2504     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2505             (LONG_PTR)test_proc, proc);
2506
2507     filter_messages = focus_window;
2508
2509     ref = IDirect3DDevice8_Release(device);
2510     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2511
2512     filter_messages = device_window;
2513
2514     device = create_device(d3d8, focus_window, focus_window, TRUE);
2515     if (!device)
2516     {
2517         skip("Failed to create a D3D device, skipping tests.\n");
2518         goto done;
2519     }
2520
2521     filter_messages = NULL;
2522
2523     hr = reset_device(device, focus_window, FALSE);
2524     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2525
2526     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2527     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2528             (LONG_PTR)test_proc, proc);
2529
2530     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2531     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2532             (LONG_PTR)test_proc, proc);
2533
2534     hr = reset_device(device, focus_window, TRUE);
2535     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2536
2537     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2538     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2539             (LONG_PTR)test_proc, proc);
2540
2541     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2542     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2543             (LONG_PTR)test_proc, proc);
2544
2545     filter_messages = device_window;
2546
2547     ref = IDirect3DDevice8_Release(device);
2548     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2549
2550     device = create_device(d3d8, device_window, focus_window, TRUE);
2551     if (!device)
2552     {
2553         skip("Failed to create a D3D device, skipping tests.\n");
2554         goto done;
2555     }
2556
2557     filter_messages = NULL;
2558
2559     hr = reset_device(device, device_window, FALSE);
2560     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2561
2562     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2563     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2564             (LONG_PTR)test_proc, proc);
2565
2566     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2567     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2568             (LONG_PTR)test_proc, proc);
2569
2570     hr = reset_device(device, device_window, TRUE);
2571     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2572
2573     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2574     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2575             (LONG_PTR)test_proc, proc);
2576
2577     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2578     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2579             (LONG_PTR)test_proc, proc);
2580
2581     filter_messages = device_window;
2582
2583     ref = IDirect3DDevice8_Release(device);
2584     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2585
2586 done:
2587     filter_messages = NULL;
2588     IDirect3D8_Release(d3d8);
2589
2590     SetEvent(thread_params.test_finished);
2591     WaitForSingleObject(thread, INFINITE);
2592     CloseHandle(thread_params.test_finished);
2593     CloseHandle(thread_params.window_created);
2594     CloseHandle(thread);
2595
2596     DestroyWindow(device_window);
2597     DestroyWindow(focus_window);
2598     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2599 }
2600
2601 static inline void set_fpu_cw(WORD cw)
2602 {
2603 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2604 #define D3D8_TEST_SET_FPU_CW 1
2605     __asm__ volatile ("fnclex");
2606     __asm__ volatile ("fldcw %0" : : "m" (cw));
2607 #elif defined(__i386__) && defined(_MSC_VER)
2608 #define D3D8_TEST_SET_FPU_CW 1
2609     __asm fnclex;
2610     __asm fldcw cw;
2611 #endif
2612 }
2613
2614 static inline WORD get_fpu_cw(void)
2615 {
2616     WORD cw = 0;
2617 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2618 #define D3D8_TEST_GET_FPU_CW 1
2619     __asm__ volatile ("fnstcw %0" : "=m" (cw));
2620 #elif defined(__i386__) && defined(_MSC_VER)
2621 #define D3D8_TEST_GET_FPU_CW 1
2622     __asm fnstcw cw;
2623 #endif
2624     return cw;
2625 }
2626
2627 static void test_fpu_setup(void)
2628 {
2629 #if defined(D3D8_TEST_SET_FPU_CW) && defined(D3D8_TEST_GET_FPU_CW)
2630     D3DPRESENT_PARAMETERS present_parameters;
2631     IDirect3DDevice8 *device;
2632     D3DDISPLAYMODE d3ddm;
2633     HWND window = NULL;
2634     IDirect3D8 *d3d8;
2635     HRESULT hr;
2636     WORD cw;
2637
2638     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2639     ok(!!d3d8, "Failed to create a d3d8 object.\n");
2640     if (!d3d8) return;
2641
2642     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2643     ok(!!window, "Failed to create a window.\n");
2644     if (!window) goto done;
2645
2646     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
2647     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
2648
2649     memset(&present_parameters, 0, sizeof(present_parameters));
2650     present_parameters.Windowed = TRUE;
2651     present_parameters.hDeviceWindow = window;
2652     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2653     present_parameters.BackBufferFormat = d3ddm.Format;
2654
2655     set_fpu_cw(0xf60);
2656     cw = get_fpu_cw();
2657     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2658
2659     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2660             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
2661     if (FAILED(hr))
2662     {
2663         skip("Failed to create a device, hr %#x.\n", hr);
2664         set_fpu_cw(0x37f);
2665         goto done;
2666     }
2667
2668     cw = get_fpu_cw();
2669     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2670
2671     IDirect3DDevice8_Release(device);
2672
2673     cw = get_fpu_cw();
2674     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2675     set_fpu_cw(0xf60);
2676     cw = get_fpu_cw();
2677     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2678
2679     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2680             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
2681     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
2682
2683     cw = get_fpu_cw();
2684     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2685     set_fpu_cw(0x37f);
2686
2687     IDirect3DDevice8_Release(device);
2688
2689 done:
2690     if (window) DestroyWindow(window);
2691     if (d3d8) IDirect3D8_Release(d3d8);
2692 #endif
2693 }
2694
2695 static void test_ApplyStateBlock(void)
2696 {
2697     D3DPRESENT_PARAMETERS d3dpp;
2698     IDirect3DDevice8 *device = NULL;
2699     IDirect3D8 *d3d8;
2700     HWND hwnd;
2701     HRESULT hr;
2702     D3DDISPLAYMODE d3ddm;
2703     DWORD received, token;
2704
2705     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2706     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2707     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2708     ok(hwnd != NULL, "Failed to create window\n");
2709     if (!d3d8 || !hwnd) goto cleanup;
2710
2711     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
2712     ZeroMemory( &d3dpp, sizeof(d3dpp) );
2713     d3dpp.Windowed         = TRUE;
2714     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2715     d3dpp.BackBufferWidth  = 800;
2716     d3dpp.BackBufferHeight  = 600;
2717     d3dpp.BackBufferFormat = d3ddm.Format;
2718     d3dpp.EnableAutoDepthStencil = TRUE;
2719     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2720
2721     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2722                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
2723     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2724        "IDirect3D8_CreateDevice failed with %#x\n", hr);
2725     if(!device)
2726     {
2727         skip("Failed to create a d3d device\n");
2728         goto cleanup;
2729     }
2730
2731     IDirect3DDevice8_BeginStateBlock(device);
2732     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
2733     IDirect3DDevice8_EndStateBlock(device, &token);
2734     ok(token, "Received zero stateblock handle.\n");
2735     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
2736
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, 0);
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 FALSE, received TRUE.\n");
2746
2747     hr = IDirect3DDevice8_ApplyStateBlock(device, token);
2748     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2749     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2750     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2751     ok(received, "Expected TRUE, received FALSE.\n");
2752
2753     IDirect3DDevice8_DeleteStateBlock(device, token);
2754     IDirect3DDevice8_Release(device);
2755 cleanup:
2756     if (d3d8) IDirect3D8_Release(d3d8);
2757     DestroyWindow(hwnd);
2758 }
2759
2760 static void test_depth_stencil_size(void)
2761 {
2762     IDirect3DDevice8 *device;
2763     IDirect3DSurface8 *ds, *rt, *ds_bigger, *ds_bigger2;
2764     IDirect3DSurface8 *surf;
2765     IDirect3D8 *d3d8;
2766     HRESULT hr;
2767     HWND hwnd;
2768
2769     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2770     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2771     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2772     ok(hwnd != NULL, "Failed to create window\n");
2773     if (!d3d8 || !hwnd) goto cleanup;
2774
2775     device = create_device(d3d8, hwnd, hwnd, TRUE);
2776     if (!device) goto cleanup;
2777
2778     hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
2779     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateRenderTarget failed, hr %#x.\n", hr);
2780     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds);
2781     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2782     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger);
2783     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2784     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger2);
2785     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2786
2787     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2788     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2789     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds_bigger);
2790     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2791
2792     /* try to set the small ds without changing the render target at the same time */
2793     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds);
2794     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2795     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds_bigger2);
2796     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2797
2798     hr = IDirect3DDevice8_GetRenderTarget(device, &surf);
2799     ok(hr == D3D_OK, "IDirect3DDevice8_GetRenderTarget failed, hr %#x.\n", hr);
2800     ok(surf == rt, "The render target is %p, expected %p\n", surf, rt);
2801     IDirect3DSurface8_Release(surf);
2802     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2803     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr %#x.\n", hr);
2804     ok(surf == ds_bigger2, "The depth stencil is %p, expected %p\n", surf, ds_bigger2);
2805     IDirect3DSurface8_Release(surf);
2806
2807     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2808     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2809     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2810     ok(FAILED(hr), "IDirect3DDevice8_GetDepthStencilSurface should have failed, hr %#x.\n", hr);
2811     ok(surf == NULL, "The depth stencil is %p, expected NULL\n", surf);
2812     if (surf) IDirect3DSurface8_Release(surf);
2813
2814     IDirect3DSurface8_Release(rt);
2815     IDirect3DSurface8_Release(ds);
2816     IDirect3DSurface8_Release(ds_bigger);
2817     IDirect3DSurface8_Release(ds_bigger2);
2818
2819 cleanup:
2820     if (d3d8) IDirect3D8_Release(d3d8);
2821     DestroyWindow(hwnd);
2822 }
2823
2824 static void test_window_style(void)
2825 {
2826     RECT focus_rect, fullscreen_rect, r;
2827     LONG device_style, device_exstyle;
2828     LONG focus_style, focus_exstyle;
2829     LONG style, expected_style;
2830     IDirect3DDevice8 *device;
2831     IDirect3D8 *d3d8;
2832     ULONG ref;
2833
2834
2835     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2836     {
2837         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2838         return;
2839     }
2840
2841     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2842             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2843     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2844             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2845
2846     device_style = GetWindowLongA(device_window, GWL_STYLE);
2847     device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
2848     focus_style = GetWindowLongA(focus_window, GWL_STYLE);
2849     focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
2850
2851     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
2852     GetWindowRect(focus_window, &focus_rect);
2853
2854     device = create_device(d3d8, device_window, focus_window, FALSE);
2855     if (!device)
2856     {
2857         skip("Failed to create a D3D device, skipping tests.\n");
2858         goto done;
2859     }
2860
2861     style = GetWindowLongA(device_window, GWL_STYLE);
2862     expected_style = device_style | WS_VISIBLE;
2863     todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
2864             expected_style, style);
2865     style = GetWindowLongA(device_window, GWL_EXSTYLE);
2866     expected_style = device_exstyle | WS_EX_TOPMOST;
2867     todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
2868             expected_style, style);
2869
2870     style = GetWindowLongA(focus_window, GWL_STYLE);
2871     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
2872             focus_style, style);
2873     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
2874     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
2875             focus_exstyle, style);
2876
2877     GetWindowRect(device_window, &r);
2878     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2879             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2880             r.left, r.top, r.right, r.bottom);
2881     GetClientRect(device_window, &r);
2882     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2883     GetWindowRect(focus_window, &r);
2884     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2885             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
2886             r.left, r.top, r.right, r.bottom);
2887
2888     ref = IDirect3DDevice8_Release(device);
2889     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2890
2891 done:
2892     IDirect3D8_Release(d3d8);
2893
2894     DestroyWindow(device_window);
2895     DestroyWindow(focus_window);
2896 }
2897
2898 static void test_wrong_shader(void)
2899 {
2900     HRESULT hr;
2901     HWND hwnd = NULL;
2902     IDirect3D8 *d3d = NULL;
2903     IDirect3DDevice8 *device = NULL;
2904     D3DPRESENT_PARAMETERS d3dpp;
2905     D3DDISPLAYMODE d3ddm;
2906     DWORD vs, ps;
2907
2908     static const DWORD vs_2_0[] =
2909     {
2910         0xfffe0200,                                         /* vs_2_0           */
2911         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
2912         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2913         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
2914         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
2915         0x0000ffff                                          /* end              */
2916     };
2917     static const DWORD ps_2_0[] =
2918     {
2919         0xffff0200,                                         /* ps_2_0           */
2920         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2921         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
2922         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
2923         0x0000ffff                                          /* end              */
2924     };
2925
2926     static const DWORD decl[] =
2927     {
2928         D3DVSD_STREAM(0),
2929         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
2930         D3DVSD_END()
2931     };
2932
2933     d3d = pDirect3DCreate8(D3D_SDK_VERSION);
2934     ok(d3d != NULL, "Failed to create IDirect3D8 object\n");
2935     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2936     ok(hwnd != NULL, "Failed to create window\n");
2937     if (!d3d || !hwnd)
2938         goto cleanup;
2939
2940     IDirect3D8_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2941     ZeroMemory(&d3dpp, sizeof(d3dpp));
2942     d3dpp.Windowed = TRUE;
2943     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2944     d3dpp.BackBufferWidth = 800;
2945     d3dpp.BackBufferHeight = 600;
2946     d3dpp.BackBufferFormat = d3ddm.Format;
2947
2948     hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2949             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
2950     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
2951     if (!device)
2952     {
2953         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
2954         goto cleanup;
2955     }
2956
2957     hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_ps, &vs, 0);
2958     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2959
2960     hr = IDirect3DDevice8_CreatePixelShader(device, simple_vs, &ps);
2961     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2962
2963     hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_2_0, &vs, 0);
2964     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2965
2966     hr = IDirect3DDevice8_CreatePixelShader(device, ps_2_0, &ps);
2967     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2968
2969 cleanup:
2970     if (device)
2971     {
2972         UINT refcount = IDirect3DDevice8_Release(device);
2973         ok(!refcount, "Device has %u references left.\n", refcount);
2974     }
2975     if (d3d)
2976         IDirect3D8_Release(d3d);
2977     DestroyWindow(hwnd);
2978 }
2979
2980 static void test_mode_change(void)
2981 {
2982     RECT fullscreen_rect, focus_rect, r;
2983     IDirect3DSurface8 *backbuffer;
2984     IDirect3DDevice8 *device;
2985     D3DSURFACE_DESC desc;
2986     IDirect3D8 *d3d8;
2987     DEVMODEW devmode;
2988     UINT refcount;
2989     HRESULT hr;
2990     DWORD ret;
2991
2992     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2993     {
2994         skip("Failed to create IDirect3D8 object, skipping mode change tests.\n");
2995         return;
2996     }
2997
2998     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2999             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3000     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3001             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3002
3003     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3004     GetWindowRect(focus_window, &focus_rect);
3005
3006     device = create_device(d3d8, device_window, focus_window, FALSE);
3007     if (!device)
3008     {
3009         skip("Failed to create a D3D device, skipping tests.\n");
3010         goto done;
3011     }
3012
3013     memset(&devmode, 0, sizeof(devmode));
3014     devmode.dmSize = sizeof(devmode);
3015     devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3016     devmode.dmPelsWidth = 640;
3017     devmode.dmPelsHeight = 480;
3018
3019     ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3020     ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3021
3022     memset(&devmode, 0, sizeof(devmode));
3023     devmode.dmSize = sizeof(devmode);
3024     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3025     ok(ret, "Failed to get display mode.\n");
3026     ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3027     ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3028
3029     GetWindowRect(device_window, &r);
3030     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3031             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3032             r.left, r.top, r.right, r.bottom);
3033     GetWindowRect(focus_window, &r);
3034     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3035             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3036             r.left, r.top, r.right, r.bottom);
3037
3038     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3039     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3040     hr = IDirect3DSurface8_GetDesc(backbuffer, &desc);
3041     ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3042     ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3043     ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3044     IDirect3DSurface8_Release(backbuffer);
3045
3046     refcount = IDirect3DDevice8_Release(device);
3047     ok(!refcount, "Device has %u references left.\n", refcount);
3048
3049     memset(&devmode, 0, sizeof(devmode));
3050     devmode.dmSize = sizeof(devmode);
3051     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3052     ok(ret, "Failed to get display mode.\n");
3053     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3054     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3055
3056 done:
3057     DestroyWindow(device_window);
3058     DestroyWindow(focus_window);
3059     if (d3d8)
3060         IDirect3D8_Release(d3d8);
3061
3062     memset(&devmode, 0, sizeof(devmode));
3063     devmode.dmSize = sizeof(devmode);
3064     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3065     ok(ret, "Failed to get display mode.\n");
3066     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3067     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3068 }
3069
3070 static void test_device_window_reset(void)
3071 {
3072     RECT fullscreen_rect, device_rect, r;
3073     IDirect3DDevice8 *device;
3074     WNDCLASSA wc = {0};
3075     IDirect3D8 *d3d8;
3076     LONG_PTR proc;
3077     HRESULT hr;
3078     ULONG ref;
3079
3080     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3081     {
3082         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3083         return;
3084     }
3085
3086     wc.lpfnWndProc = test_proc;
3087     wc.lpszClassName = "d3d8_test_wndproc_wc";
3088     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3089
3090     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3091             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3092     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3093             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3094
3095     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3096     GetWindowRect(device_window, &device_rect);
3097
3098     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3099     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3100             (LONG_PTR)test_proc, proc);
3101     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3102     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3103             (LONG_PTR)test_proc, proc);
3104
3105     device = create_device(d3d8, NULL, focus_window, FALSE);
3106     if (!device)
3107     {
3108         skip("Failed to create a D3D device, skipping tests.\n");
3109         goto done;
3110     }
3111
3112     GetWindowRect(focus_window, &r);
3113     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3114             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3115             r.left, r.top, r.right, r.bottom);
3116     GetWindowRect(device_window, &r);
3117     ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3118             device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3119             r.left, r.top, r.right, r.bottom);
3120
3121     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3122     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3123             (LONG_PTR)test_proc, proc);
3124     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3125     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3126             (LONG_PTR)test_proc, proc);
3127
3128     hr = reset_device(device, device_window, FALSE);
3129     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3130
3131     GetWindowRect(focus_window, &r);
3132     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3133             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3134             r.left, r.top, r.right, r.bottom);
3135     GetWindowRect(device_window, &r);
3136     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3137             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3138             r.left, r.top, r.right, r.bottom);
3139
3140     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3141     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3142             (LONG_PTR)test_proc, proc);
3143     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3144     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3145             (LONG_PTR)test_proc, proc);
3146
3147     ref = IDirect3DDevice8_Release(device);
3148     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3149
3150 done:
3151     IDirect3D8_Release(d3d8);
3152     DestroyWindow(device_window);
3153     DestroyWindow(focus_window);
3154     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3155 }
3156
3157 static void depth_blit_test(void)
3158 {
3159     HWND hwnd = NULL;
3160     IDirect3D8 *d3d8 = NULL;
3161     IDirect3DDevice8 *device = NULL;
3162     IDirect3DSurface8 *backbuffer, *ds1, *ds2, *ds3;
3163     RECT src_rect;
3164     const POINT dst_point = {0, 0};
3165     HRESULT hr;
3166
3167     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
3168     ok(d3d8 != NULL, "Direct3DCreate8 failed.\n");
3169     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
3170     ok(hwnd != NULL, "CreateWindow failed.\n");
3171     if (!d3d8 || !hwnd)
3172         goto done;
3173
3174     device = create_device(d3d8, hwnd, hwnd, TRUE);
3175     if (!device)
3176     {
3177         skip("Failed to create a D3D device, skipping tests.\n");
3178         goto done;
3179     }
3180
3181     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
3182     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
3183     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds1);
3184     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
3185     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds2);
3186     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3187     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds3);
3188     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3189
3190     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
3191     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
3192
3193     /* Partial blit. */
3194     SetRect(&src_rect, 0, 0, 320, 240);
3195     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3196     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3197     /* Flipped. */
3198     SetRect(&src_rect, 0, 480, 640, 0);
3199     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3200     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3201     /* Full, explicit. */
3202     SetRect(&src_rect, 0, 0, 640, 480);
3203     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3204     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3205     /* Depth -> color blit.*/
3206     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, backbuffer, &dst_point);
3207     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3208     /* Full, NULL rects, current depth stencil -> unbound depth stencil */
3209     hr = IDirect3DDevice8_CopyRects(device, ds1, NULL, 0, ds2, NULL);
3210     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3211     /* Full, NULL rects, unbound depth stencil -> current depth stencil */
3212     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds1, NULL);
3213     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3214     /* Full, NULL rects, unbound depth stencil -> unbound depth stencil */
3215     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds3, NULL);
3216     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3217
3218     IDirect3DSurface8_Release(backbuffer);
3219     IDirect3DSurface8_Release(ds3);
3220     IDirect3DSurface8_Release(ds2);
3221     IDirect3DSurface8_Release(ds1);
3222
3223 done:
3224     if (device) IDirect3DDevice8_Release(device);
3225     if (d3d8) IDirect3D8_Release(d3d8);
3226     if (hwnd) DestroyWindow(hwnd);
3227 }
3228
3229 static void test_reset_resources(void)
3230 {
3231     IDirect3DSurface8 *surface, *rt;
3232     IDirect3DTexture8 *texture;
3233     IDirect3DDevice8 *device;
3234     IDirect3D8 *d3d8;
3235     HWND window;
3236     HRESULT hr;
3237     ULONG ref;
3238
3239     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
3240             0, 0, 640, 480, 0, 0, 0, 0);
3241
3242     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3243     {
3244         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3245         DestroyWindow(window);
3246         return;
3247     }
3248
3249     if (!(device = create_device(d3d8, window, window, TRUE)))
3250     {
3251         skip("Failed to create a D3D device, skipping tests.\n");
3252         goto done;
3253     }
3254
3255     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_DEPTHSTENCIL,
3256             D3DFMT_D24S8, D3DPOOL_DEFAULT, &texture);
3257     ok(SUCCEEDED(hr), "Failed to create depth/stencil texture, hr %#x.\n", hr);
3258     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
3259     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3260     IDirect3DTexture8_Release(texture);
3261
3262     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3263             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3264     ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr);
3265     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &rt);
3266     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3267     IDirect3DTexture8_Release(texture);
3268
3269     hr = IDirect3DDevice8_SetRenderTarget(device, rt, surface);
3270     ok(SUCCEEDED(hr), "Failed to set render target surface, hr %#x.\n", hr);
3271     IDirect3DSurface8_Release(rt);
3272     IDirect3DSurface8_Release(surface);
3273
3274     hr = reset_device(device, device_window, TRUE);
3275     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3276
3277     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3278     ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3279     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3280     ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3281     ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3282     IDirect3DSurface8_Release(surface);
3283     IDirect3DSurface8_Release(rt);
3284
3285     ref = IDirect3DDevice8_Release(device);
3286     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3287
3288 done:
3289     IDirect3D8_Release(d3d8);
3290     DestroyWindow(window);
3291 }
3292
3293 static void test_set_rt_vp_scissor(void)
3294 {
3295     IDirect3DDevice8 *device;
3296     IDirect3DSurface8 *rt;
3297     IDirect3D8 *d3d8;
3298     DWORD stateblock;
3299     D3DVIEWPORT8 vp;
3300     UINT refcount;
3301     HWND window;
3302     HRESULT hr;
3303
3304     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3305     {
3306         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3307         return;
3308     }
3309
3310     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
3311             0, 0, 640, 480, 0, 0, 0, 0);
3312     if (!(device = create_device(d3d8, window, window, TRUE)))
3313     {
3314         skip("Failed to create a D3D device, skipping tests.\n");
3315         DestroyWindow(window);
3316         return;
3317     }
3318
3319     hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3320             D3DMULTISAMPLE_NONE, FALSE, &rt);
3321     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3322
3323     hr = IDirect3DDevice8_GetViewport(device, &vp);
3324     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3325     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3326     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3327     ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3328     ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3329     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3330     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3331
3332     hr = IDirect3DDevice8_BeginStateBlock(device);
3333     ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3334
3335     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3336     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3337
3338     hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
3339     ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3340     hr = IDirect3DDevice8_DeleteStateBlock(device, stateblock);
3341     ok(SUCCEEDED(hr), "Failed to delete stateblock, hr %#x.\n", hr);
3342
3343     hr = IDirect3DDevice8_GetViewport(device, &vp);
3344     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3345     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3346     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3347     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3348     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3349     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3350     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3351
3352     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3353     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3354
3355     vp.X = 10;
3356     vp.Y = 20;
3357     vp.Width = 30;
3358     vp.Height = 40;
3359     vp.MinZ = 0.25f;
3360     vp.MaxZ = 0.75f;
3361     hr = IDirect3DDevice8_SetViewport(device, &vp);
3362     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3363
3364     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3365     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3366
3367     hr = IDirect3DDevice8_GetViewport(device, &vp);
3368     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3369     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3370     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3371     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3372     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3373     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3374     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3375
3376     IDirect3DSurface8_Release(rt);
3377     refcount = IDirect3DDevice8_Release(device);
3378     ok(!refcount, "Device has %u references left.\n", refcount);
3379     IDirect3D8_Release(d3d8);
3380     DestroyWindow(window);
3381 }
3382
3383 static void test_validate_vs(void)
3384 {
3385     static DWORD vs[] =
3386     {
3387         0xfffe0101,                                                             /* vs_1_1                       */
3388         0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000,                         /* dp4 oPos.x, v0, c0           */
3389         0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001,                         /* dp4 oPos.y, v0, c1           */
3390         0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002,                         /* dp4 oPos.z, v0, c2           */
3391         0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003,                         /* dp4 oPos.w, v0, c3           */
3392         0x0000ffff,                                                             /* end                          */
3393     };
3394     HRESULT hr;
3395
3396     hr = ValidateVertexShader(0, 0, 0, 0, 0);
3397     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3398     hr = ValidateVertexShader(0, 0, 0, 1, 0);
3399     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3400     hr = ValidateVertexShader(vs, 0, 0, 0, 0);
3401     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3402
3403     hr = ValidateVertexShader(vs, 0, 0, 1, 0);
3404     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3405     /* Seems to do some version checking. */
3406     *vs = 0xfffe0100;                                                           /* vs_1_0                       */
3407     hr = ValidateVertexShader(vs, 0, 0, 0, 0);
3408     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3409
3410     *vs = 0xfffe0102;                                                           /* bogus version                */
3411     hr = ValidateVertexShader(vs, 0, 0, 1, 0);
3412     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3413     /* I've seen that applications always pass the 2nd and 3rd parameter as 0.
3414      * Simple test with non-zero parameters. */
3415     *vs = 0xfffe0101;                                                           /* vs_1_1                       */
3416     hr = ValidateVertexShader(vs, vs, 0, 1, 0);
3417     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3418
3419     hr = ValidateVertexShader(vs, 0, vs, 1, 0);
3420     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3421     /* I've seen the 4th parameter always passed as either 0 or 1, but passing
3422      * other values doesn't seem to hurt. */
3423     hr = ValidateVertexShader(vs, 0, 0, 12345, 0);
3424     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3425     /* What is the 5th parameter? The following seems to work ok. */
3426     hr = ValidateVertexShader(vs, 0, 0, 1, vs);
3427     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3428 }
3429
3430 static void test_validate_ps(void)
3431 {
3432     static DWORD ps[] =
3433     {
3434         0xffff0101,                                                             /* ps_1_1                       */
3435         0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
3436         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
3437         0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000,                         /* dp3 r0, c1, c0               */
3438         0x00000005, 0x800f0000, 0x90e40000, 0x80e40000,                         /* mul r0, v0, r0               */
3439         0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000,                         /* mul r0, t0, r0               */
3440         0x0000ffff,                                                             /* end                          */
3441     };
3442     HRESULT hr;
3443
3444     hr = ValidatePixelShader(0, 0, 0, 0);
3445     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3446     hr = ValidatePixelShader(0, 0, 1, 0);
3447     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3448     hr = ValidatePixelShader(ps, 0, 0, 0);
3449     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3450
3451     hr = ValidatePixelShader(ps, 0, 1, 0);
3452     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3453     /* Seems to do some version checking. */
3454     *ps = 0xffff0105;                                                           /* bogus version                */
3455     hr = ValidatePixelShader(ps, 0, 1, 0);
3456     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3457     /* I've seen that applications always pass the 2nd parameter as 0.
3458      * Simple test with a non-zero parameter. */
3459     *ps = 0xffff0101;                                                           /* ps_1_1                       */
3460     hr = ValidatePixelShader(ps, ps, 1, 0);
3461     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3462     /* I've seen th 3rd parameter always passed as either 0 or 1, but passing
3463      * other values doesn't seem to hurt. */
3464     hr = ValidatePixelShader(ps, 0, 12345, 0);
3465     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3466     /* What is the 4th parameter? The following seems to work ok. */
3467     hr = ValidatePixelShader(ps, 0, 1, ps);
3468     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3469 }
3470
3471 static void test_volume_get_container(void)
3472 {
3473     IDirect3DVolumeTexture8 *texture = NULL;
3474     IDirect3DVolume8 *volume = NULL;
3475     IDirect3DDevice8 *device;
3476     IUnknown *container;
3477     IDirect3D8 *d3d8;
3478     ULONG refcount;
3479     D3DCAPS8 caps;
3480     HWND window;
3481     HRESULT hr;
3482
3483     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3484     {
3485         skip("Failed to create d3d8 object, skipping tests.\n");
3486         return;
3487     }
3488
3489     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3490             0, 0, 640, 480, 0, 0, 0, 0);
3491     if (!(device = create_device(d3d8, window, window, TRUE)))
3492     {
3493         skip("Failed to create a D3D device, skipping tests.\n");
3494         IDirect3D8_Release(d3d8);
3495         DestroyWindow(window);
3496         return;
3497     }
3498
3499     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3500     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3501     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3502     {
3503         skip("No volume texture support, skipping tests.\n");
3504         IDirect3DDevice8_Release(device);
3505         IDirect3D8_Release(d3d8);
3506         DestroyWindow(window);
3507         return;
3508     }
3509
3510     hr = IDirect3DDevice8_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3511             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3512     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3513     ok(!!texture, "Got unexpected texture %p.\n", texture);
3514
3515     hr = IDirect3DVolumeTexture8_GetVolumeLevel(texture, 0, &volume);
3516     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3517     ok(!!volume, "Got unexpected volume %p.\n", volume);
3518
3519     /* These should work... */
3520     container = NULL;
3521     hr = IDirect3DVolume8_GetContainer(volume, &IID_IUnknown, (void **)&container);
3522     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3523     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3524     IUnknown_Release(container);
3525
3526     container = NULL;
3527     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DResource8, (void **)&container);
3528     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3529     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3530     IUnknown_Release(container);
3531
3532     container = NULL;
3533     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DBaseTexture8, (void **)&container);
3534     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3535     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3536     IUnknown_Release(container);
3537
3538     container = NULL;
3539     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolumeTexture8, (void **)&container);
3540     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3541     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3542     IUnknown_Release(container);
3543
3544     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3545     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolume8, (void **)&container);
3546     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3547     ok(!container, "Got unexpected container %p.\n", container);
3548
3549     IDirect3DVolume8_Release(volume);
3550     IDirect3DVolumeTexture8_Release(texture);
3551     refcount = IDirect3DDevice8_Release(device);
3552     ok(!refcount, "Device has %u references left.\n", refcount);
3553     IDirect3D8_Release(d3d8);
3554     DestroyWindow(window);
3555 }
3556
3557 static void test_vb_lock_flags(void)
3558 {
3559     static const struct
3560     {
3561         DWORD flags;
3562         const char *debug_string;
3563         HRESULT result;
3564     }
3565     test_data[] =
3566     {
3567         {D3DLOCK_READONLY,                          "D3DLOCK_READONLY",                         D3D_OK            },
3568         {D3DLOCK_DISCARD,                           "D3DLOCK_DISCARD",                          D3D_OK            },
3569         {D3DLOCK_NOOVERWRITE,                       "D3DLOCK_NOOVERWRITE",                      D3D_OK            },
3570         {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD,     "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD",    D3D_OK            },
3571         {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY,    "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY",   D3D_OK            },
3572         {D3DLOCK_READONLY    | D3DLOCK_DISCARD,     "D3DLOCK_READONLY | D3DLOCK_DISCARD",       D3D_OK            },
3573         /* Completely bogus flags aren't an error. */
3574         {0xdeadbeef,                                "0xdeadbeef",                               D3D_OK            },
3575     };
3576     IDirect3DVertexBuffer8 *buffer;
3577     IDirect3DDevice8 *device;
3578     IDirect3D8 *d3d8;
3579     unsigned int i;
3580     ULONG refcount;
3581     HWND window;
3582     HRESULT hr;
3583     BYTE *data;
3584
3585     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3586     {
3587         skip("Failed to create d3d8 object, skipping tests.\n");
3588         return;
3589     }
3590
3591     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3592             0, 0, 640, 480, 0, 0, 0, 0);
3593     if (!(device = create_device(d3d8, window, window, TRUE)))
3594     {
3595         skip("Failed to create a D3D device, skipping tests.\n");
3596         IDirect3D8_Release(d3d8);
3597         DestroyWindow(window);
3598         return;
3599     }
3600
3601     hr = IDirect3DDevice8_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer);
3602     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3603
3604     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
3605     {
3606         hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &data, test_data[i].flags);
3607         ok(hr == test_data[i].result, "Got unexpected hr %#x for %s.\n",
3608                 hr, test_data[i].debug_string);
3609         if (SUCCEEDED(hr))
3610         {
3611             ok(!!data, "Got unexpected data %p.\n", data);
3612             hr = IDirect3DVertexBuffer8_Unlock(buffer);
3613             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3614         }
3615     }
3616
3617     IDirect3DVertexBuffer8_Release(buffer);
3618     refcount = IDirect3DDevice8_Release(device);
3619     ok(!refcount, "Device has %u references left.\n", refcount);
3620     IDirect3D8_Release(d3d8);
3621     DestroyWindow(window);
3622 }
3623
3624 /* Test the default texture stage state values */
3625 static void test_texture_stage_states(void)
3626 {
3627     IDirect3DDevice8 *device;
3628     IDirect3D8 *d3d8;
3629     unsigned int i;
3630     ULONG refcount;
3631     D3DCAPS8 caps;
3632     DWORD value;
3633     HWND window;
3634     HRESULT hr;
3635
3636     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3637     {
3638         skip("Failed to create d3d8 object, skipping tests.\n");
3639         return;
3640     }
3641
3642     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3643             0, 0, 640, 480, 0, 0, 0, 0);
3644     if (!(device = create_device(d3d8, window, window, TRUE)))
3645     {
3646         skip("Failed to create a D3D device, skipping tests.\n");
3647         IDirect3D8_Release(d3d8);
3648         DestroyWindow(window);
3649         return;
3650     }
3651
3652     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3653     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3654
3655     for (i = 0; i < caps.MaxTextureBlendStages; ++i)
3656     {
3657         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
3658         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3659         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
3660                 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
3661         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
3662         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3663         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
3664         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
3665         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3666         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
3667         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
3668         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3669         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
3670                 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
3671         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
3672         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3673         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
3674         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
3675         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3676         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
3677         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
3678         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3679         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
3680         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
3681         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3682         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
3683         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
3684         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3685         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
3686         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
3687         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3688         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
3689         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
3690         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3691         ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
3692         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
3693         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3694         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
3695         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
3696         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3697         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
3698         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
3699         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3700         ok(value == D3DTTFF_DISABLE,
3701                 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
3702         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
3703         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3704         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
3705         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
3706         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3707         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
3708         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
3709         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3710         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
3711     }
3712
3713     refcount = IDirect3DDevice8_Release(device);
3714     ok(!refcount, "Device has %u references left.\n", refcount);
3715     IDirect3D8_Release(d3d8);
3716     DestroyWindow(window);
3717 }
3718
3719 static void test_cube_textures(void)
3720 {
3721     IDirect3DCubeTexture8 *texture;
3722     IDirect3DDevice8 *device;
3723     IDirect3D8 *d3d8;
3724     ULONG refcount;
3725     D3DCAPS8 caps;
3726     HWND window;
3727     HRESULT hr;
3728
3729     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3730     {
3731         skip("Failed to create d3d8 object, skipping tests.\n");
3732         return;
3733     }
3734
3735     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3736             0, 0, 640, 480, 0, 0, 0, 0);
3737     if (!(device = create_device(d3d8, window, window, TRUE)))
3738     {
3739         skip("Failed to create a D3D device, skipping tests.\n");
3740         IDirect3D8_Release(d3d8);
3741         DestroyWindow(window);
3742         return;
3743     }
3744
3745     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3746     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3747
3748     if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
3749     {
3750         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
3751         ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
3752         IDirect3DCubeTexture8_Release(texture);
3753         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
3754         ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
3755         IDirect3DCubeTexture8_Release(texture);
3756         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
3757         ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
3758         IDirect3DCubeTexture8_Release(texture);
3759     }
3760     else
3761     {
3762         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
3763         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
3764         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
3765         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
3766         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
3767         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
3768     }
3769     hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture);
3770     ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
3771     IDirect3DCubeTexture8_Release(texture);
3772
3773     refcount = IDirect3DDevice8_Release(device);
3774     ok(!refcount, "Device has %u references left.\n", refcount);
3775     IDirect3D8_Release(d3d8);
3776     DestroyWindow(window);
3777 }
3778
3779 /* Test the behaviour of the IDirect3DDevice8::CreateImageSurface() method.
3780  *
3781  * The expected behaviour (as documented in the original DX8 docs) is that the
3782  * call returns a surface in the SYSTEMMEM pool. Games like Max Payne 1 and 2
3783  * depend on this behaviour.
3784  *
3785  * A short remark in the DX9 docs however states that the pool of the returned
3786  * surface object is D3DPOOL_SCRATCH. This is misinformation and would result
3787  * in screenshots not appearing in the savegame loading menu of both games
3788  * mentioned above (engine tries to display a texture from the scratch pool).
3789  *
3790  * This test verifies that the behaviour described in the original d3d8 docs
3791  * is the correct one. For more information about this issue, see the MSDN:
3792  *     d3d9 docs: "Converting to Direct3D 9"
3793  *     d3d9 reference: "IDirect3DDevice9::CreateOffscreenPlainSurface"
3794  *     d3d8 reference: "IDirect3DDevice8::CreateImageSurface" */
3795 static void test_image_surface_pool(void)
3796 {
3797     IDirect3DSurface8 *surface;
3798     IDirect3DDevice8 *device;
3799     D3DSURFACE_DESC desc;
3800     IDirect3D8 *d3d8;
3801     ULONG refcount;
3802     HWND window;
3803     HRESULT hr;
3804
3805     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3806     {
3807         skip("Failed to create d3d8 object, skipping tests.\n");
3808         return;
3809     }
3810
3811     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3812             0, 0, 640, 480, 0, 0, 0, 0);
3813     if (!(device = create_device(d3d8, window, window, TRUE)))
3814     {
3815         skip("Failed to create a D3D device, skipping tests.\n");
3816         IDirect3D8_Release(d3d8);
3817         DestroyWindow(window);
3818         return;
3819     }
3820
3821     hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
3822     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3823     hr = IDirect3DSurface8_GetDesc(surface, &desc);
3824     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3825     ok(desc.Pool == D3DPOOL_SYSTEMMEM, "Got unexpected pool %#x.\n", desc.Pool);
3826     IDirect3DSurface8_Release(surface);
3827
3828     refcount = IDirect3DDevice8_Release(device);
3829     ok(!refcount, "Device has %u references left.\n", refcount);
3830     IDirect3D8_Release(d3d8);
3831     DestroyWindow(window);
3832 }
3833
3834 static void test_surface_get_container(void)
3835 {
3836     IDirect3DTexture8 *texture = NULL;
3837     IDirect3DSurface8 *surface = NULL;
3838     IDirect3DDevice8 *device;
3839     IUnknown *container;
3840     IDirect3D8 *d3d8;
3841     ULONG refcount;
3842     HWND window;
3843     HRESULT hr;
3844
3845     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3846     {
3847         skip("Failed to create d3d8 object, skipping tests.\n");
3848         return;
3849     }
3850
3851     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3852             0, 0, 640, 480, 0, 0, 0, 0);
3853     if (!(device = create_device(d3d8, window, window, TRUE)))
3854     {
3855         skip("Failed to create a D3D device, skipping tests.\n");
3856         IDirect3D8_Release(d3d8);
3857         DestroyWindow(window);
3858         return;
3859     }
3860
3861     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0,
3862             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3863     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
3864     ok(!!texture, "Got unexpected texture %p.\n", texture);
3865
3866     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
3867     ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
3868     ok(!!surface, "Got unexpected surface %p.\n", surface);
3869
3870     /* These should work... */
3871     container = NULL;
3872     hr = IDirect3DSurface8_GetContainer(surface, &IID_IUnknown, (void **)&container);
3873     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3874     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3875     IUnknown_Release(container);
3876
3877     container = NULL;
3878     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DResource8, (void **)&container);
3879     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3880     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3881     IUnknown_Release(container);
3882
3883     container = NULL;
3884     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DBaseTexture8, (void **)&container);
3885     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3886     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3887     IUnknown_Release(container);
3888
3889     container = NULL;
3890     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DTexture8, (void **)&container);
3891     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3892     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3893     IUnknown_Release(container);
3894
3895     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3896     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DSurface8, (void **)&container);
3897     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3898     ok(!container, "Got unexpected container %p.\n", container);
3899
3900     IDirect3DSurface8_Release(surface);
3901     IDirect3DTexture8_Release(texture);
3902     refcount = IDirect3DDevice8_Release(device);
3903     ok(!refcount, "Device has %u references left.\n", refcount);
3904     IDirect3D8_Release(d3d8);
3905     DestroyWindow(window);
3906 }
3907
3908 static void test_lockrect_invalid(void)
3909 {
3910     static const RECT valid[] =
3911     {
3912         {60, 60, 68, 68},
3913         {120, 60, 128, 68},
3914         {60, 120, 68, 128},
3915     };
3916     static const RECT invalid[] =
3917     {
3918         {60, 60, 60, 68},       /* 0 height */
3919         {60, 60, 68, 60},       /* 0 width */
3920         {68, 60, 60, 68},       /* left > right */
3921         {60, 68, 68, 60},       /* top > bottom */
3922         {-8, 60,  0, 68},       /* left < surface */
3923         {60, -8, 68,  0},       /* top < surface */
3924         {-16, 60, -8, 68},      /* right < surface */
3925         {60, -16, 68, -8},      /* bottom < surface */
3926         {60, 60, 136, 68},      /* right > surface */
3927         {60, 60, 68, 136},      /* bottom > surface */
3928         {136, 60, 144, 68},     /* left > surface */
3929         {60, 136, 68, 144},     /* top > surface */
3930     };
3931     IDirect3DSurface8 *surface = NULL;
3932     D3DLOCKED_RECT locked_rect;
3933     IDirect3DDevice8 *device;
3934     IDirect3D8 *d3d8;
3935     unsigned int i;
3936     ULONG refcount;
3937     HWND window;
3938     BYTE *base;
3939     HRESULT hr;
3940
3941     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3942     {
3943         skip("Failed to create d3d8 object, skipping tests.\n");
3944         return;
3945     }
3946
3947     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3948             0, 0, 640, 480, 0, 0, 0, 0);
3949     if (!(device = create_device(d3d8, window, window, TRUE)))
3950     {
3951         skip("Failed to create a D3D device, skipping tests.\n");
3952         IDirect3D8_Release(d3d8);
3953         DestroyWindow(window);
3954         return;
3955     }
3956
3957     hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
3958     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3959     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
3960     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3961     base = locked_rect.pBits;
3962     hr = IDirect3DSurface8_UnlockRect(surface);
3963     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3964
3965     for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
3966     {
3967         unsigned int offset, expected_offset;
3968         const RECT *rect = &valid[i];
3969
3970         locked_rect.pBits = (BYTE *)0xdeadbeef;
3971         locked_rect.Pitch = 0xdeadbeef;
3972
3973         hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
3974         ok(SUCCEEDED(hr), "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
3975                 rect->left, rect->top, rect->right, rect->bottom, hr);
3976
3977         offset = (BYTE *)locked_rect.pBits - base;
3978         expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
3979         ok(offset == expected_offset,
3980                 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
3981                 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
3982
3983         hr = IDirect3DSurface8_UnlockRect(surface);
3984         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3985     }
3986
3987     for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
3988     {
3989         const RECT *rect = &invalid[i];
3990
3991         hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
3992         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
3993                 hr, rect->left, rect->top, rect->right, rect->bottom);
3994     }
3995
3996     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
3997     ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
3998     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
3999     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4000     hr = IDirect3DSurface8_UnlockRect(surface);
4001     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4002
4003     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
4004     ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
4005             hr, valid[0].left, valid[0].top, valid[0].right, valid[0].bottom);
4006     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
4007     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
4008             hr, valid[0].left, valid[0].top, valid[0].right, valid[0].bottom);
4009     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[1], 0);
4010     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
4011             hr, valid[1].left, valid[1].top, valid[1].right, valid[1].bottom);
4012     hr = IDirect3DSurface8_UnlockRect(surface);
4013     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4014
4015     IDirect3DSurface8_Release(surface);
4016     refcount = IDirect3DDevice8_Release(device);
4017     ok(!refcount, "Device has %u references left.\n", refcount);
4018     IDirect3D8_Release(d3d8);
4019     DestroyWindow(window);
4020 }
4021
4022 static void test_private_data(void)
4023 {
4024     ULONG refcount, expected_refcount;
4025     IDirect3DSurface8 *surface;
4026     IDirect3DDevice8 *device;
4027     IDirect3D8 *d3d8;
4028     IUnknown *ptr;
4029     HWND window;
4030     HRESULT hr;
4031     DWORD size;
4032
4033     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4034     {
4035         skip("Failed to create d3d8 object, skipping tests.\n");
4036         return;
4037     }
4038
4039     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4040             0, 0, 640, 480, 0, 0, 0, 0);
4041     if (!(device = create_device(d3d8, window, window, TRUE)))
4042     {
4043         skip("Failed to create a D3D device, skipping tests.\n");
4044         IDirect3D8_Release(d3d8);
4045         DestroyWindow(window);
4046         return;
4047     }
4048
4049     hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_A8R8G8B8, &surface);
4050     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4051
4052     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4053             device, 0, D3DSPD_IUNKNOWN);
4054     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4055     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4056             device, 5, D3DSPD_IUNKNOWN);
4057     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4058     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4059             device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
4060     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4061
4062     refcount = get_refcount((IUnknown *)device);
4063     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4064             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4065     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4066     expected_refcount = refcount + 1;
4067     refcount = get_refcount((IUnknown *)device);
4068     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4069     hr = IDirect3DSurface8_FreePrivateData(surface, &IID_IDirect3DSurface8);
4070     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4071     expected_refcount = refcount - 1;
4072     refcount = get_refcount((IUnknown *)device);
4073     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4074
4075     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8,
4076             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4077     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4078     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8,
4079             surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4080     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4081     refcount = get_refcount((IUnknown *)device);
4082     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4083
4084     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8,
4085             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4086     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4087     size = sizeof(ptr);
4088     hr = IDirect3DSurface8_GetPrivateData(surface, &IID_IDirect3DSurface8, &ptr, &size);
4089     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4090     expected_refcount = refcount + 2;
4091     refcount = get_refcount((IUnknown *)device);
4092     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4093     ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
4094     IUnknown_Release(ptr);
4095
4096     /* Destroying the surface frees the held reference. */
4097     IDirect3DSurface8_Release(surface);
4098     expected_refcount = refcount - 3;
4099     refcount = get_refcount((IUnknown *)device);
4100     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4101
4102     refcount = IDirect3DDevice8_Release(device);
4103     ok(!refcount, "Device has %u references left.\n", refcount);
4104     IDirect3D8_Release(d3d8);
4105     DestroyWindow(window);
4106 }
4107
4108 static void test_surface_dimensions(void)
4109 {
4110     IDirect3DSurface8 *surface;
4111     IDirect3DDevice8 *device;
4112     IDirect3D8 *d3d8;
4113     ULONG refcount;
4114     HWND window;
4115     HRESULT hr;
4116
4117     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4118     {
4119         skip("Failed to create d3d8 object, skipping tests.\n");
4120         return;
4121     }
4122
4123     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4124             0, 0, 640, 480, 0, 0, 0, 0);
4125     if (!(device = create_device(d3d8, window, window, TRUE)))
4126     {
4127         skip("Failed to create a D3D device, skipping tests.\n");
4128         IDirect3D8_Release(d3d8);
4129         DestroyWindow(window);
4130         return;
4131     }
4132
4133     hr = IDirect3DDevice8_CreateImageSurface(device, 0, 1, D3DFMT_A8R8G8B8, &surface);
4134     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4135     hr = IDirect3DDevice8_CreateImageSurface(device, 1, 0, D3DFMT_A8R8G8B8, &surface);
4136     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4137
4138     refcount = IDirect3DDevice8_Release(device);
4139     ok(!refcount, "Device has %u references left.\n", refcount);
4140     IDirect3D8_Release(d3d8);
4141     DestroyWindow(window);
4142 }
4143
4144 static void test_surface_format_null(void)
4145 {
4146     static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
4147     IDirect3DTexture8 *texture;
4148     IDirect3DSurface8 *surface;
4149     IDirect3DSurface8 *rt, *ds;
4150     D3DLOCKED_RECT locked_rect;
4151     IDirect3DDevice8 *device;
4152     D3DSURFACE_DESC desc;
4153     IDirect3D8 *d3d;
4154     ULONG refcount;
4155     HWND window;
4156     HRESULT hr;
4157
4158     if (!(d3d = pDirect3DCreate8(D3D_SDK_VERSION)))
4159     {
4160         skip("Failed to create D3D object, skipping tests.\n");
4161         return;
4162     }
4163
4164     hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4165             D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
4166     if (hr != D3D_OK)
4167     {
4168         skip("No D3DFMT_NULL support, skipping test.\n");
4169         IDirect3D8_Release(d3d);
4170         return;
4171     }
4172
4173     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4174             0, 0, 640, 480, 0, 0, 0, 0);
4175     if (!(device = create_device(d3d, window, window, TRUE)))
4176     {
4177         skip("Failed to create a D3D device, skipping tests.\n");
4178         IDirect3D8_Release(d3d);
4179         DestroyWindow(window);
4180         return;
4181     }
4182
4183     hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4184             D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
4185     ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
4186
4187     hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4188             D3DFMT_NULL, D3DFMT_D24S8);
4189     ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
4190
4191     hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
4192             D3DMULTISAMPLE_NONE, TRUE, &surface);
4193     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4194
4195     hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
4196     ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
4197
4198     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds);
4199     ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
4200
4201     hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
4202     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4203
4204     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
4205     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
4206
4207     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
4208     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4209
4210     IDirect3DSurface8_Release(rt);
4211     IDirect3DSurface8_Release(ds);
4212
4213     hr = IDirect3DSurface8_GetDesc(surface, &desc);
4214     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4215     ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
4216     ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
4217
4218     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4219     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4220     ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
4221     ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
4222
4223     hr = IDirect3DSurface8_UnlockRect(surface);
4224     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4225
4226     IDirect3DSurface8_Release(surface);
4227
4228     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
4229             D3DFMT_NULL, D3DPOOL_DEFAULT, &texture);
4230     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4231     IDirect3DTexture8_Release(texture);
4232
4233     refcount = IDirect3DDevice8_Release(device);
4234     ok(!refcount, "Device has %u references left.\n", refcount);
4235     IDirect3D8_Release(d3d);
4236     DestroyWindow(window);
4237 }
4238
4239 static void test_surface_double_unlock(void)
4240 {
4241     static const D3DPOOL pools[] =
4242     {
4243         D3DPOOL_DEFAULT,
4244         D3DPOOL_SYSTEMMEM,
4245     };
4246     IDirect3DSurface8 *surface;
4247     IDirect3DDevice8 *device;
4248     D3DLOCKED_RECT lr;
4249     IDirect3D8 *d3d;
4250     unsigned int i;
4251     ULONG refcount;
4252     HWND window;
4253     HRESULT hr;
4254
4255     if (!(d3d = pDirect3DCreate8(D3D_SDK_VERSION)))
4256     {
4257         skip("Failed to create D3D object, skipping tests.\n");
4258         return;
4259     }
4260
4261     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4262             0, 0, 640, 480, 0, 0, 0, 0);
4263     if (!(device = create_device(d3d, window, window, TRUE)))
4264     {
4265         skip("Failed to create a D3D device, skipping tests.\n");
4266         IDirect3D8_Release(d3d);
4267         DestroyWindow(window);
4268         return;
4269     }
4270
4271     for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
4272     {
4273         switch (pools[i])
4274         {
4275             case D3DPOOL_DEFAULT:
4276                 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4277                         D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
4278                 if (FAILED(hr))
4279                 {
4280                     skip("D3DFMT_X8R8G8B8 render targets not supported, skipping double unlock DEFAULT pool test.\n");
4281                     continue;
4282                 }
4283
4284                 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_X8R8G8B8,
4285                         D3DMULTISAMPLE_NONE, TRUE, &surface);
4286                 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4287                 break;
4288
4289             case D3DPOOL_SYSTEMMEM:
4290                 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64, D3DFMT_X8R8G8B8, &surface);
4291                 ok(SUCCEEDED(hr), "Failed to create image surface, hr %#x.\n", hr);
4292                 break;
4293
4294             default:
4295                 break;
4296         }
4297
4298         hr = IDirect3DSurface8_UnlockRect(surface);
4299         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
4300         hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
4301         ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
4302         hr = IDirect3DSurface8_UnlockRect(surface);
4303         ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
4304         hr = IDirect3DSurface8_UnlockRect(surface);
4305         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
4306
4307         IDirect3DSurface8_Release(surface);
4308     }
4309
4310     refcount = IDirect3DDevice8_Release(device);
4311     ok(!refcount, "Device has %u references left.\n", refcount);
4312     IDirect3D8_Release(d3d);
4313     DestroyWindow(window);
4314 }
4315
4316 static void test_surface_lockrect_blocks(void)
4317 {
4318     static const struct
4319     {
4320         D3DFORMAT fmt;
4321         const char *name;
4322         unsigned int block_width;
4323         unsigned int block_height;
4324         BOOL broken;
4325     }
4326     formats[] =
4327     {
4328         {D3DFMT_DXT1,                 "D3DFMT_DXT1", 4, 4, FALSE},
4329         {D3DFMT_DXT2,                 "D3DFMT_DXT2", 4, 4, FALSE},
4330         {D3DFMT_DXT3,                 "D3DFMT_DXT3", 4, 4, FALSE},
4331         {D3DFMT_DXT4,                 "D3DFMT_DXT4", 4, 4, FALSE},
4332         {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, FALSE},
4333         /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
4334          * which doesn't match the format spec. On newer Nvidia cards
4335          * it has the correct 4x4 block size */
4336         {MAKEFOURCC('A','T','I','2'), "ATI2N",       4, 4, TRUE},
4337         /* YUY2 and UYVY are not supported in d3d8, there is no way
4338          * to use them with this API considering their restrictions */
4339     };
4340     static const struct
4341     {
4342         D3DPOOL pool;
4343         const char *name;
4344         /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
4345          * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
4346         BOOL success;
4347     }
4348     pools[] =
4349     {
4350         {D3DPOOL_DEFAULT,       "D3DPOOL_DEFAULT",  FALSE},
4351         {D3DPOOL_SCRATCH,       "D3DPOOL_SCRATCH",  TRUE},
4352         {D3DPOOL_SYSTEMMEM,     "D3DPOOL_SYSTEMMEM",TRUE},
4353         {D3DPOOL_MANAGED,       "D3DPOOL_MANAGED",  TRUE},
4354     };
4355     IDirect3DTexture8 *texture;
4356     IDirect3DSurface8 *surface;
4357     D3DLOCKED_RECT locked_rect;
4358     IDirect3DDevice8 *device;
4359     unsigned int i, j;
4360     IDirect3D8 *d3d;
4361     ULONG refcount;
4362     HWND window;
4363     HRESULT hr;
4364     RECT rect;
4365
4366     if (!(d3d = pDirect3DCreate8(D3D_SDK_VERSION)))
4367     {
4368         skip("Failed to create D3D object, skipping tests.\n");
4369         return;
4370     }
4371
4372     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4373             0, 0, 640, 480, 0, 0, 0, 0);
4374     if (!(device = create_device(d3d, window, window, TRUE)))
4375     {
4376         skip("Failed to create a D3D device, skipping tests.\n");
4377         IDirect3D8_Release(d3d);
4378         DestroyWindow(window);
4379         return;
4380     }
4381
4382     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
4383     {
4384         hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4385                 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
4386         if (FAILED(hr))
4387         {
4388             skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
4389             continue;
4390         }
4391
4392         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
4393         {
4394             hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1,
4395                     pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
4396                     formats[i].fmt, pools[j].pool, &texture);
4397             ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4398             hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
4399             ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
4400             IDirect3DTexture8_Release(texture);
4401
4402             if (formats[i].block_width > 1)
4403             {
4404                 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
4405                 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4406                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
4407                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
4408                         SUCCEEDED(hr) ? "succeeded" : "failed",
4409                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
4410                 if (SUCCEEDED(hr))
4411                 {
4412                     hr = IDirect3DSurface8_UnlockRect(surface);
4413                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4414                 }
4415
4416                 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
4417                 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4418                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
4419                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
4420                         SUCCEEDED(hr) ? "succeeded" : "failed",
4421                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
4422                 if (SUCCEEDED(hr))
4423                 {
4424                     hr = IDirect3DSurface8_UnlockRect(surface);
4425                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4426                 }
4427             }
4428
4429             if (formats[i].block_height > 1)
4430             {
4431                 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
4432                 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4433                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
4434                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
4435                         SUCCEEDED(hr) ? "succeeded" : "failed",
4436                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
4437                 if (SUCCEEDED(hr))
4438                 {
4439                     hr = IDirect3DSurface8_UnlockRect(surface);
4440                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4441                 }
4442
4443                 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
4444                 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4445                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
4446                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
4447                         SUCCEEDED(hr) ? "succeeded" : "failed",
4448                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
4449                 if (SUCCEEDED(hr))
4450                 {
4451                     hr = IDirect3DSurface8_UnlockRect(surface);
4452                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4453                 }
4454             }
4455
4456             SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
4457             hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4458             ok(hr == D3D_OK, "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
4459             hr = IDirect3DSurface8_UnlockRect(surface);
4460             ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4461
4462             IDirect3DSurface8_Release(surface);
4463         }
4464     }
4465
4466     refcount = IDirect3DDevice8_Release(device);
4467     ok(!refcount, "Device has %u references left.\n", refcount);
4468     IDirect3D8_Release(d3d);
4469     DestroyWindow(window);
4470 }
4471
4472 START_TEST(device)
4473 {
4474     HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
4475     WNDCLASS wc = {0};
4476     if (!d3d8_handle)
4477     {
4478         skip("Could not load d3d8.dll\n");
4479         return;
4480     }
4481
4482     wc.lpfnWndProc = DefWindowProc;
4483     wc.lpszClassName = "d3d8_test_wc";
4484     RegisterClass(&wc);
4485
4486     ValidateVertexShader = (void *)GetProcAddress(d3d8_handle, "ValidateVertexShader");
4487     ValidatePixelShader = (void *)GetProcAddress(d3d8_handle, "ValidatePixelShader");
4488     pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
4489     ok(pDirect3DCreate8 != NULL, "Failed to get address of Direct3DCreate8\n");
4490     if (pDirect3DCreate8)
4491     {
4492         IDirect3D8 *d3d8;
4493         d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
4494         if(!d3d8)
4495         {
4496             skip("could not create D3D8\n");
4497             return;
4498         }
4499         IDirect3D8_Release(d3d8);
4500
4501         screen_width = GetSystemMetrics(SM_CXSCREEN);
4502         screen_height = GetSystemMetrics(SM_CYSCREEN);
4503
4504         test_fpu_setup();
4505         test_display_modes();
4506         test_shader_versions();
4507         test_swapchain();
4508         test_refcount();
4509         test_mipmap_levels();
4510         test_cursor();
4511         test_cursor_pos();
4512         test_states();
4513         test_reset();
4514         test_scene();
4515         test_shader();
4516         test_limits();
4517         test_lights();
4518         test_ApplyStateBlock();
4519         test_render_zero_triangles();
4520         test_depth_stencil_reset();
4521         test_wndproc();
4522         test_wndproc_windowed();
4523         test_depth_stencil_size();
4524         test_window_style();
4525         test_wrong_shader();
4526         test_mode_change();
4527         test_device_window_reset();
4528         test_reset_resources();
4529         depth_blit_test();
4530         test_set_rt_vp_scissor();
4531         test_validate_vs();
4532         test_validate_ps();
4533         test_volume_get_container();
4534         test_vb_lock_flags();
4535         test_texture_stage_states();
4536         test_cube_textures();
4537         test_image_surface_pool();
4538         test_surface_get_container();
4539         test_lockrect_invalid();
4540         test_private_data();
4541         test_surface_dimensions();
4542         test_surface_format_null();
4543         test_surface_double_unlock();
4544         test_surface_lockrect_blocks();
4545     }
4546     UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));
4547 }