Release 1.5.29.
[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 2006-2007, 2011-2013 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         ok(vp.Width == 200, "D3DVIEWPORT->Width = %u, expected 200.\n", vp.Width);
1269         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     ok(surface_desc.Width == 200, "Back buffer width is %u, expected 200.\n", surface_desc.Width);
1279     ok(surface_desc.Height == 150, "Back buffer height is %u, expected 150.\n", surface_desc.Height);
1280     IDirect3DSurface8_Release(surface);
1281
1282     memset(&d3dpp, 0, sizeof(d3dpp));
1283     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1284     d3dpp.Windowed = TRUE;
1285     d3dpp.BackBufferWidth = 400;
1286     d3dpp.BackBufferHeight = 300;
1287     d3dpp.BackBufferFormat = d3ddm.Format;
1288
1289     /* Reset fails if there is a resource in the default pool. */
1290     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texture);
1291     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1292     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1293     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1294     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1295     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1296     IDirect3DTexture8_Release(texture);
1297     /* Reset again to get the device out of the lost state. */
1298     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1299     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1300     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1301     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1302
1303     if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1304     {
1305         IDirect3DVolumeTexture8 *volume_texture;
1306
1307         hr = IDirect3DDevice8_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1308                 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture);
1309         ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1310         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1311         ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1312         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1313         ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1314                 hr, D3DERR_DEVICENOTRESET);
1315         IDirect3DVolumeTexture8_Release(volume_texture);
1316         hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1317         ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1318         hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1319         ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1320     }
1321     else
1322     {
1323         skip("Volume textures not supported.\n");
1324     }
1325
1326     /* Scratch, sysmem and managed pool resources are fine. */
1327     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1328     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1329     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1330     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1331     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1332     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1333     IDirect3DTexture8_Release(texture);
1334
1335     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1336     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1337     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1338     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1339     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1340     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1341     IDirect3DTexture8_Release(texture);
1342
1343     /* The depth stencil should get reset to the auto depth stencil when present. */
1344     hr = IDirect3DDevice8_SetRenderTarget(device1, NULL, NULL);
1345     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1346
1347     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1348     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1349     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1350
1351     d3dpp.EnableAutoDepthStencil = TRUE;
1352     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1353     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1354     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1355
1356     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1357     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1358     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1359     if (surface) IDirect3DSurface8_Release(surface);
1360
1361     d3dpp.EnableAutoDepthStencil = FALSE;
1362     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1363     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1364
1365     hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1366     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1367     ok(!surface, "Depth / stencil buffer should be NULL.\n");
1368
1369     /* Will a sysmem or scratch resource survive while locked? */
1370     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1371     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1372     hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1373     ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1374     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1375     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1376     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1377     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1378     IDirect3DTexture8_UnlockRect(texture, 0);
1379     IDirect3DTexture8_Release(texture);
1380
1381     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1382     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1383     hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1384     ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1385     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1386     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1387     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1388     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1389     IDirect3DTexture8_UnlockRect(texture, 0);
1390     IDirect3DTexture8_Release(texture);
1391
1392     hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture);
1393     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1394     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1395     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1396     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1397     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1398     IDirect3DTexture8_Release(texture);
1399
1400     /* A reference held to an implicit surface causes failures as well. */
1401     hr = IDirect3DDevice8_GetBackBuffer(device1, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1402     ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
1403     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1404     ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1405     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1406     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1407     IDirect3DSurface8_Release(surface);
1408     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1409     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1410     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1411     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1412
1413     /* Shaders are fine as well. */
1414     hr = IDirect3DDevice8_CreateVertexShader(device1, decl, simple_vs, &shader, 0);
1415     ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
1416     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1417     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1418     hr = IDirect3DDevice8_DeleteVertexShader(device1, shader);
1419     ok(SUCCEEDED(hr), "DeleteVertexShader failed, hr %#x.\n", hr);
1420
1421     /* Try setting invalid modes. */
1422     memset(&d3dpp, 0, sizeof(d3dpp));
1423     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1424     d3dpp.Windowed = FALSE;
1425     d3dpp.BackBufferWidth = 32;
1426     d3dpp.BackBufferHeight = 32;
1427     d3dpp.BackBufferFormat = d3ddm.Format;
1428     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1429     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1430     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1431     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1432
1433     memset(&d3dpp, 0, sizeof(d3dpp));
1434     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1435     d3dpp.Windowed = FALSE;
1436     d3dpp.BackBufferWidth = 801;
1437     d3dpp.BackBufferHeight = 600;
1438     d3dpp.BackBufferFormat = d3ddm.Format;
1439     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1440     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1441     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1442     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1443
1444     memset(&d3dpp, 0, sizeof(d3dpp));
1445     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1446     d3dpp.Windowed = FALSE;
1447     d3dpp.BackBufferWidth = 0;
1448     d3dpp.BackBufferHeight = 0;
1449     d3dpp.BackBufferFormat = d3ddm.Format;
1450     hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1451     ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1452     hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1453     ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1454
1455     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1456     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1457
1458     memset(&d3dpp, 0, sizeof(d3dpp));
1459     d3dpp.Windowed = TRUE;
1460     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1461     d3dpp.BackBufferFormat = d3ddm.Format;
1462     d3dpp.EnableAutoDepthStencil = FALSE;
1463     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1464
1465     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1466             window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1467     if (FAILED(hr))
1468     {
1469         skip("Failed to create device, hr %#x.\n", hr);
1470         goto cleanup;
1471     }
1472
1473     hr = IDirect3DDevice8_TestCooperativeLevel(device2);
1474     ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1475
1476     d3dpp.Windowed = TRUE;
1477     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1478     d3dpp.BackBufferWidth = 400;
1479     d3dpp.BackBufferHeight = 300;
1480     d3dpp.BackBufferFormat = d3ddm.Format;
1481     d3dpp.EnableAutoDepthStencil = TRUE;
1482     d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1483
1484     hr = IDirect3DDevice8_Reset(device2, &d3dpp);
1485     ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1486     if (FAILED(hr))
1487         goto cleanup;
1488
1489     hr = IDirect3DDevice8_GetDepthStencilSurface(device2, &surface);
1490     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1491     ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1492     if (surface)
1493         IDirect3DSurface8_Release(surface);
1494
1495 cleanup:
1496     HeapFree(GetProcessHeap(), 0, modes);
1497     if (device2)
1498         IDirect3DDevice8_Release(device2);
1499     if (device1)
1500         IDirect3DDevice8_Release(device1);
1501     if (d3d8)
1502         IDirect3D8_Release(d3d8);
1503     if (window)
1504         DestroyWindow(window);
1505 }
1506
1507 static void test_scene(void)
1508 {
1509     HRESULT                      hr;
1510     HWND                         hwnd               = NULL;
1511     IDirect3D8                  *pD3d               = NULL;
1512     IDirect3DDevice8            *pDevice            = NULL;
1513     D3DPRESENT_PARAMETERS        d3dpp;
1514     D3DDISPLAYMODE               d3ddm;
1515
1516     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1517     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1518     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1519     ok(hwnd != NULL, "Failed to create window\n");
1520     if (!pD3d || !hwnd) goto cleanup;
1521
1522     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1523     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1524     d3dpp.Windowed         = TRUE;
1525     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1526     d3dpp.BackBufferWidth  = 800;
1527     d3dpp.BackBufferHeight = 600;
1528     d3dpp.BackBufferFormat = d3ddm.Format;
1529
1530
1531     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1532                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1533     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1534     if(!pDevice)
1535     {
1536         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1537         goto cleanup;
1538     }
1539
1540     /* Test an EndScene without BeginScene. Should return an error */
1541     hr = IDirect3DDevice8_EndScene(pDevice);
1542     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1543
1544     /* Test a normal BeginScene / EndScene pair, this should work */
1545     hr = IDirect3DDevice8_BeginScene(pDevice);
1546     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1547     if(SUCCEEDED(hr))
1548     {
1549         hr = IDirect3DDevice8_EndScene(pDevice);
1550         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1551     }
1552
1553     /* Test another EndScene without having begun a new scene. Should return an error */
1554     hr = IDirect3DDevice8_EndScene(pDevice);
1555     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1556
1557     /* Two nested BeginScene and EndScene calls */
1558     hr = IDirect3DDevice8_BeginScene(pDevice);
1559     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1560     hr = IDirect3DDevice8_BeginScene(pDevice);
1561     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1562     hr = IDirect3DDevice8_EndScene(pDevice);
1563     ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1564     hr = IDirect3DDevice8_EndScene(pDevice);
1565     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1566
1567     /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
1568
1569 cleanup:
1570     if (pDevice)
1571     {
1572         UINT refcount = IDirect3DDevice8_Release(pDevice);
1573         ok(!refcount, "Device has %u references left.\n", refcount);
1574     }
1575     if (pD3d) IDirect3D8_Release(pD3d);
1576     DestroyWindow(hwnd);
1577 }
1578
1579 static void test_shader(void)
1580 {
1581     HRESULT                      hr;
1582     HWND                         hwnd               = NULL;
1583     IDirect3D8                  *pD3d               = NULL;
1584     IDirect3DDevice8            *pDevice            = NULL;
1585     D3DPRESENT_PARAMETERS        d3dpp;
1586     D3DDISPLAYMODE               d3ddm;
1587     DWORD                        hPixelShader = 0, hVertexShader = 0;
1588     DWORD                        hPixelShader2 = 0, hVertexShader2 = 0;
1589     DWORD                        hTempHandle;
1590     D3DCAPS8                     caps;
1591     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
1592     DWORD data_size;
1593     void *data;
1594
1595     static DWORD dwVertexDecl[] =
1596     {
1597         D3DVSD_STREAM(0),
1598         D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT3),
1599         D3DVSD_END()
1600     };
1601     DWORD decl_normal_float2[] =
1602     {
1603         D3DVSD_STREAM(0),
1604         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1605         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT2),  /* D3DVSDE_NORMAL,   Register v1 */
1606         D3DVSD_END()
1607     };
1608     DWORD decl_normal_float4[] =
1609     {
1610         D3DVSD_STREAM(0),
1611         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1612         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_FLOAT4),  /* D3DVSDE_NORMAL,   Register v1 */
1613         D3DVSD_END()
1614     };
1615     DWORD decl_normal_d3dcolor[] =
1616     {
1617         D3DVSD_STREAM(0),
1618         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1619         D3DVSD_REG(D3DVSDE_NORMAL,   D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL,   Register v1 */
1620         D3DVSD_END()
1621     };
1622     const DWORD vertex_decl_size = sizeof(dwVertexDecl);
1623     const DWORD simple_vs_size = sizeof(simple_vs);
1624     const DWORD simple_ps_size = sizeof(simple_ps);
1625
1626     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1627     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1628     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1629     ok(hwnd != NULL, "Failed to create window\n");
1630     if (!pD3d || !hwnd) goto cleanup;
1631
1632     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1633     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1634     d3dpp.Windowed         = TRUE;
1635     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1636     d3dpp.BackBufferWidth  = 800;
1637     d3dpp.BackBufferHeight = 600;
1638     d3dpp.BackBufferFormat = d3ddm.Format;
1639
1640
1641     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1642                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1643     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1644     if(!pDevice)
1645     {
1646         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1647         goto cleanup;
1648     }
1649     IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
1650
1651     /* Test setting and retrieving a FVF */
1652     hr = IDirect3DDevice8_SetVertexShader(pDevice, fvf);
1653     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1654     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1655     ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1656     ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
1657
1658     /* First create a vertex shader */
1659     hr = IDirect3DDevice8_SetVertexShader(pDevice, 0);
1660     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1661     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, simple_vs, &hVertexShader, 0);
1662     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1663     /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
1664     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1665     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1666     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1667     /* Assign the shader, then verify that GetVertexShader works */
1668     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1669     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1670     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1671     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1672     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1673     /* Verify that we can retrieve the declaration */
1674     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, NULL, &data_size);
1675     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1676     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1677     data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
1678     data_size = 1;
1679     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1680     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
1681             "expected D3DERR_INVALIDCALL\n", hr);
1682     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1683     data_size = vertex_decl_size;
1684     hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1685     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1686     ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1687     ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
1688     HeapFree(GetProcessHeap(), 0, data);
1689     /* Verify that we can retrieve the shader function */
1690     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, NULL, &data_size);
1691     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1692     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1693     data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
1694     data_size = 1;
1695     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1696     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
1697             "expected D3DERR_INVALIDCALL\n", hr);
1698     ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1699     data_size = simple_vs_size;
1700     hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1701     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1702     ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1703     ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
1704     HeapFree(GetProcessHeap(), 0, data);
1705     /* Delete the assigned shader. This is supposed to work */
1706     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1707     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1708     /* The shader should be unset now */
1709     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1710     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1711     ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1712
1713     /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
1714      * First try the fixed function shader function, then a custom one
1715      */
1716     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, 0, &hVertexShader, 0);
1717     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1718     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1719     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float4, 0, &hVertexShader, 0);
1720     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1721     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1722     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_d3dcolor, 0, &hVertexShader, 0);
1723     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1724     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1725
1726     hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, simple_vs, &hVertexShader, 0);
1727     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1728     if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1729
1730     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
1731     {
1732         /* The same with a pixel shader */
1733         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1734         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1735         /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
1736         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1737         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1738         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1739         /* Assign the shader, then verify that GetPixelShader works */
1740         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1741         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1742         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1743         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1744         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1745         /* Verify that we can retrieve the shader function */
1746         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, NULL, &data_size);
1747         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1748         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1749         data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
1750         data_size = 1;
1751         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1752         ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
1753                 "expected D3DERR_INVALIDCALL\n", hr);
1754         ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1755         data_size = simple_ps_size;
1756         hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1757         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1758         ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1759         ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
1760         HeapFree(GetProcessHeap(), 0, data);
1761         /* Delete the assigned shader. This is supposed to work */
1762         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1763         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1764         /* The shader should be unset now */
1765         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1766         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1767         ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1768
1769         /* What happens if a non-bound shader is deleted? */
1770         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1771         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1772         hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader2);
1773         ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1774
1775         hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1776         ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1777         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1778         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1779         hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1780         ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1781         ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1782         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1783         ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1784
1785         /* Check for double delete. */
1786         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1787         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1788         hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1789         ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1790     }
1791     else
1792     {
1793         skip("Pixel shaders not supported\n");
1794     }
1795
1796     /* What happens if a non-bound shader is deleted? */
1797     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader, 0);
1798     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1799     hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader2, 0);
1800     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1801
1802     hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1803     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1804     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1805     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1806     hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1807     ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1808     ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1809     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1810     ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1811
1812     /* Check for double delete. */
1813     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1814     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1815     hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1816     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1817
1818 cleanup:
1819     if (pDevice)
1820     {
1821         UINT refcount = IDirect3DDevice8_Release(pDevice);
1822         ok(!refcount, "Device has %u references left.\n", refcount);
1823     }
1824     if (pD3d) IDirect3D8_Release(pD3d);
1825     DestroyWindow(hwnd);
1826 }
1827
1828 static void test_limits(void)
1829 {
1830     HRESULT                      hr;
1831     HWND                         hwnd               = NULL;
1832     IDirect3D8                  *pD3d               = NULL;
1833     IDirect3DDevice8            *pDevice            = NULL;
1834     D3DPRESENT_PARAMETERS        d3dpp;
1835     D3DDISPLAYMODE               d3ddm;
1836     IDirect3DTexture8           *pTexture           = NULL;
1837     int i;
1838
1839     pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1840     ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1841     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1842     ok(hwnd != NULL, "Failed to create window\n");
1843     if (!pD3d || !hwnd) goto cleanup;
1844
1845     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1846     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1847     d3dpp.Windowed         = TRUE;
1848     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1849     d3dpp.BackBufferWidth  = 800;
1850     d3dpp.BackBufferHeight = 600;
1851     d3dpp.BackBufferFormat = d3ddm.Format;
1852     d3dpp.EnableAutoDepthStencil = TRUE;
1853     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1854
1855     hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1856                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1857     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1858     if(!pDevice)
1859     {
1860         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1861         goto cleanup;
1862     }
1863
1864     hr = IDirect3DDevice8_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture);
1865     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
1866     if(!pTexture) goto cleanup;
1867
1868     /* There are 8 texture stages. We should be able to access all of them */
1869     for(i = 0; i < 8; i++) {
1870         hr = IDirect3DDevice8_SetTexture(pDevice, i, (IDirect3DBaseTexture8 *) pTexture);
1871         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1872         hr = IDirect3DDevice8_SetTexture(pDevice, i, NULL);
1873         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1874         hr = IDirect3DDevice8_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1875         ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
1876     }
1877
1878     /* Investigations show that accessing higher textures stage states does not return an error either. Writing
1879      * to too high texture stages(approximately texture 40) causes memory corruption in windows, so there is no
1880      * bounds checking but how do I test that?
1881      */
1882
1883 cleanup:
1884     if(pTexture) IDirect3DTexture8_Release(pTexture);
1885     if (pDevice)
1886     {
1887         UINT refcount = IDirect3DDevice8_Release(pDevice);
1888         ok(!refcount, "Device has %u references left.\n", refcount);
1889     }
1890     if (pD3d) IDirect3D8_Release(pD3d);
1891     DestroyWindow(hwnd);
1892 }
1893
1894 static void test_lights(void)
1895 {
1896     D3DPRESENT_PARAMETERS d3dpp;
1897     IDirect3DDevice8 *device = NULL;
1898     IDirect3D8 *d3d8;
1899     HWND hwnd;
1900     HRESULT hr;
1901     unsigned int i;
1902     BOOL enabled;
1903     D3DCAPS8 caps;
1904     D3DDISPLAYMODE               d3ddm;
1905
1906     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1907     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1908     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1909     ok(hwnd != NULL, "Failed to create window\n");
1910     if (!d3d8 || !hwnd) goto cleanup;
1911
1912     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1913     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1914     d3dpp.Windowed         = TRUE;
1915     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
1916     d3dpp.BackBufferWidth  = 800;
1917     d3dpp.BackBufferHeight = 600;
1918     d3dpp.BackBufferFormat = d3ddm.Format;
1919     d3dpp.EnableAutoDepthStencil = TRUE;
1920     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1921
1922     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1923                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
1924     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1925        "IDirect3D8_CreateDevice failed with %08x\n", hr);
1926     if(!device)
1927     {
1928         skip("Failed to create a d3d device\n");
1929         goto cleanup;
1930     }
1931
1932     memset(&caps, 0, sizeof(caps));
1933     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1934     ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
1935
1936     for(i = 1; i <= caps.MaxActiveLights; i++) {
1937         hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
1938         ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1939         hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
1940         ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
1941             "GetLightEnable on light %u failed with %08x\n", i, hr);
1942         ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1943     }
1944
1945     /* TODO: Test the rendering results in this situation */
1946     hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
1947     ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
1948     hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
1949     ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1950     ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1951     hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
1952     ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1953
1954     for(i = 1; i <= caps.MaxActiveLights; i++) {
1955         hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
1956         ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
1957     }
1958
1959 cleanup:
1960     if (device)
1961     {
1962         UINT refcount = IDirect3DDevice8_Release(device);
1963         ok(!refcount, "Device has %u references left.\n", refcount);
1964     }
1965     if (d3d8) IDirect3D8_Release(d3d8);
1966     DestroyWindow(hwnd);
1967 }
1968
1969 static void test_render_zero_triangles(void)
1970 {
1971     D3DPRESENT_PARAMETERS d3dpp;
1972     IDirect3DDevice8 *device = NULL;
1973     IDirect3D8 *d3d8;
1974     HWND hwnd;
1975     HRESULT hr;
1976     D3DDISPLAYMODE               d3ddm;
1977
1978     struct nvertex
1979     {
1980         float x, y, z;
1981         float nx, ny, nz;
1982         DWORD diffuse;
1983     }  quad[] =
1984     {
1985         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1986         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1987         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1988         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
1989     };
1990
1991     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1992     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1993     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1994     ok(hwnd != NULL, "Failed to create window\n");
1995     if (!d3d8 || !hwnd) goto cleanup;
1996
1997     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1998     ZeroMemory( &d3dpp, sizeof(d3dpp) );
1999     d3dpp.Windowed         = TRUE;
2000     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2001     d3dpp.BackBufferWidth  = 800;
2002     d3dpp.BackBufferHeight = 600;
2003     d3dpp.BackBufferFormat = d3ddm.Format;
2004     d3dpp.EnableAutoDepthStencil = TRUE;
2005     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2006
2007     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
2008                                   D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
2009     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2010        "IDirect3D8_CreateDevice failed with %08x\n", hr);
2011     if(!device)
2012     {
2013         skip("Failed to create a d3d device\n");
2014         goto cleanup;
2015     }
2016
2017     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2018     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2019
2020     hr = IDirect3DDevice8_BeginScene(device);
2021     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
2022     if(hr == D3D_OK)
2023     {
2024         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
2025                                                     0 /*PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
2026         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
2027
2028         hr = IDirect3DDevice8_EndScene(device);
2029         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
2030     }
2031
2032     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2033
2034 cleanup:
2035     if (device)
2036     {
2037         UINT refcount = IDirect3DDevice8_Release(device);
2038         ok(!refcount, "Device has %u references left.\n", refcount);
2039     }
2040     if (d3d8) IDirect3D8_Release(d3d8);
2041     DestroyWindow(hwnd);
2042 }
2043
2044 static void test_depth_stencil_reset(void)
2045 {
2046     D3DPRESENT_PARAMETERS present_parameters;
2047     D3DDISPLAYMODE display_mode;
2048     IDirect3DSurface8 *surface, *orig_rt;
2049     IDirect3DDevice8 *device = NULL;
2050     IDirect3D8 *d3d8;
2051     UINT refcount;
2052     HRESULT hr;
2053     HWND hwnd;
2054
2055     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2056     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2057     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2058     ok(hwnd != NULL, "Failed to create window\n");
2059     if (!d3d8 || !hwnd) goto cleanup;
2060
2061     IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
2062     memset(&present_parameters, 0, sizeof(present_parameters));
2063     present_parameters.Windowed               = TRUE;
2064     present_parameters.SwapEffect             = D3DSWAPEFFECT_DISCARD;
2065     present_parameters.BackBufferFormat       = display_mode.Format;
2066     present_parameters.EnableAutoDepthStencil = TRUE;
2067     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2068
2069     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2070             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
2071     if(FAILED(hr))
2072     {
2073         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2074         goto cleanup;
2075     }
2076
2077     hr = IDirect3DDevice8_GetRenderTarget(device, &orig_rt);
2078     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2079
2080     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2081     ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
2082
2083     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2084     ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
2085
2086     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
2087     ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2088     ok(surface == orig_rt, "Render target is %p, should be %p\n", surface, orig_rt);
2089     if (surface) IDirect3DSurface8_Release(surface);
2090     IDirect3DSurface8_Release(orig_rt);
2091
2092     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2093     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2094     ok(surface == NULL, "Depth stencil should be NULL\n");
2095
2096     present_parameters.EnableAutoDepthStencil = TRUE;
2097     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
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 == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2103     ok(surface != NULL, "Depth stencil should not be NULL\n");
2104     if (surface) IDirect3DSurface8_Release(surface);
2105
2106     present_parameters.EnableAutoDepthStencil = FALSE;
2107     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2108     ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2109
2110     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2111     ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2112     ok(surface == NULL, "Depth stencil should be NULL\n");
2113
2114     refcount = IDirect3DDevice8_Release(device);
2115     ok(!refcount, "Device has %u references left.\n", refcount);
2116     device = NULL;
2117
2118     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
2119
2120     ZeroMemory( &present_parameters, sizeof(present_parameters) );
2121     present_parameters.Windowed         = TRUE;
2122     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2123     present_parameters.BackBufferFormat = display_mode.Format;
2124     present_parameters.EnableAutoDepthStencil = FALSE;
2125     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2126
2127     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2128                     D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2129
2130     if(FAILED(hr))
2131     {
2132         skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2133         goto cleanup;
2134     }
2135
2136     hr = IDirect3DDevice8_TestCooperativeLevel(device);
2137     ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
2138
2139     present_parameters.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2140     present_parameters.Windowed         = TRUE;
2141     present_parameters.BackBufferWidth  = 400;
2142     present_parameters.BackBufferHeight = 300;
2143     present_parameters.EnableAutoDepthStencil = TRUE;
2144     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2145
2146     hr = IDirect3DDevice8_Reset(device, &present_parameters);
2147     ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
2148
2149     if (FAILED(hr)) goto cleanup;
2150
2151     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2152     ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2153     ok(surface != NULL, "Depth stencil should not be NULL\n");
2154     if (surface) IDirect3DSurface8_Release(surface);
2155
2156 cleanup:
2157     if (device)
2158     {
2159         refcount = IDirect3DDevice8_Release(device);
2160         ok(!refcount, "Device has %u references left.\n", refcount);
2161     }
2162     if (d3d8) IDirect3D8_Release(d3d8);
2163     DestroyWindow(hwnd);
2164 }
2165
2166 static HWND filter_messages;
2167
2168 enum message_window
2169 {
2170     DEVICE_WINDOW,
2171     FOCUS_WINDOW,
2172 };
2173
2174 struct message
2175 {
2176     UINT message;
2177     enum message_window window;
2178 };
2179
2180 static const struct message *expect_messages;
2181 static HWND device_window, focus_window;
2182
2183 struct wndproc_thread_param
2184 {
2185     HWND dummy_window;
2186     HANDLE window_created;
2187     HANDLE test_finished;
2188     BOOL running_in_foreground;
2189 };
2190
2191 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2192 {
2193     if (filter_messages && filter_messages == hwnd)
2194     {
2195         if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2196             todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2197     }
2198
2199     if (expect_messages)
2200     {
2201         HWND w;
2202
2203         switch (expect_messages->window)
2204         {
2205             case DEVICE_WINDOW:
2206                 w = device_window;
2207                 break;
2208
2209             case FOCUS_WINDOW:
2210                 w = focus_window;
2211                 break;
2212
2213             default:
2214                 w = NULL;
2215                 break;
2216         };
2217
2218         if (hwnd == w && expect_messages->message == message) ++expect_messages;
2219     }
2220
2221     return DefWindowProcA(hwnd, message, wparam, lparam);
2222 }
2223
2224 static DWORD WINAPI wndproc_thread(void *param)
2225 {
2226     struct wndproc_thread_param *p = param;
2227     DWORD res;
2228     BOOL ret;
2229
2230     p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2231             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2232     p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2233
2234     ret = SetEvent(p->window_created);
2235     ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2236
2237     for (;;)
2238     {
2239         MSG msg;
2240
2241         while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2242         res = WaitForSingleObject(p->test_finished, 100);
2243         if (res == WAIT_OBJECT_0) break;
2244         if (res != WAIT_TIMEOUT)
2245         {
2246             ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2247             break;
2248         }
2249     }
2250
2251     DestroyWindow(p->dummy_window);
2252
2253     return 0;
2254 }
2255
2256 static void test_wndproc(void)
2257 {
2258     struct wndproc_thread_param thread_params;
2259     IDirect3DDevice8 *device;
2260     WNDCLASSA wc = {0};
2261     IDirect3D8 *d3d8;
2262     HANDLE thread;
2263     LONG_PTR proc;
2264     ULONG ref;
2265     DWORD res, tid;
2266     HWND tmp;
2267
2268     static const struct message messages[] =
2269     {
2270         {WM_WINDOWPOSCHANGING,  FOCUS_WINDOW},
2271         {WM_ACTIVATE,           FOCUS_WINDOW},
2272         {WM_SETFOCUS,           FOCUS_WINDOW},
2273         {WM_WINDOWPOSCHANGING,  DEVICE_WINDOW},
2274         {WM_MOVE,               DEVICE_WINDOW},
2275         {WM_SIZE,               DEVICE_WINDOW},
2276         {0,                     0},
2277     };
2278
2279     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2280     {
2281         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2282         return;
2283     }
2284
2285     wc.lpfnWndProc = test_proc;
2286     wc.lpszClassName = "d3d8_test_wndproc_wc";
2287     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2288
2289     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2290     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2291     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2292     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2293
2294     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2295             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2296     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2297             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2298     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2299     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2300
2301     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2302     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2303
2304     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2305     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2306             (LONG_PTR)test_proc, proc);
2307     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2308     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2309             (LONG_PTR)test_proc, proc);
2310
2311     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2312             device_window, focus_window, thread_params.dummy_window);
2313
2314     tmp = GetFocus();
2315     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2316     if (thread_params.running_in_foreground)
2317     {
2318         tmp = GetForegroundWindow();
2319         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2320                 thread_params.dummy_window, tmp);
2321     }
2322     else
2323         skip("Not running in foreground, skip foreground window test\n");
2324
2325     flush_events();
2326
2327     expect_messages = messages;
2328
2329     device = create_device(d3d8, device_window, focus_window, FALSE);
2330     if (!device)
2331     {
2332         skip("Failed to create a D3D device, skipping tests.\n");
2333         goto done;
2334     }
2335
2336     ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2337             expect_messages->message, expect_messages->window);
2338     expect_messages = NULL;
2339
2340     if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2341     {
2342         tmp = GetFocus();
2343         ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2344         tmp = GetForegroundWindow();
2345         ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2346     }
2347     SetForegroundWindow(focus_window);
2348     flush_events();
2349
2350     filter_messages = focus_window;
2351
2352     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2353     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2354             (LONG_PTR)test_proc, proc);
2355
2356     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2357     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2358             (LONG_PTR)test_proc, proc);
2359
2360     ref = IDirect3DDevice8_Release(device);
2361     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2362
2363     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2364     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2365             (LONG_PTR)test_proc, proc);
2366
2367     device = create_device(d3d8, focus_window, focus_window, FALSE);
2368     if (!device)
2369     {
2370         skip("Failed to create a D3D device, skipping tests.\n");
2371         goto done;
2372     }
2373
2374     ref = IDirect3DDevice8_Release(device);
2375     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2376
2377     device = create_device(d3d8, device_window, focus_window, FALSE);
2378     if (!device)
2379     {
2380         skip("Failed to create a D3D device, skipping tests.\n");
2381         goto done;
2382     }
2383
2384     proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2385     ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2386             (LONG_PTR)test_proc, proc);
2387
2388     ref = IDirect3DDevice8_Release(device);
2389     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2390
2391     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2392     ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2393             (LONG_PTR)DefWindowProcA, proc);
2394
2395 done:
2396     filter_messages = NULL;
2397     IDirect3D8_Release(d3d8);
2398
2399     SetEvent(thread_params.test_finished);
2400     WaitForSingleObject(thread, INFINITE);
2401     CloseHandle(thread_params.test_finished);
2402     CloseHandle(thread_params.window_created);
2403     CloseHandle(thread);
2404
2405     DestroyWindow(device_window);
2406     DestroyWindow(focus_window);
2407     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2408 }
2409
2410 static void test_wndproc_windowed(void)
2411 {
2412     struct wndproc_thread_param thread_params;
2413     IDirect3DDevice8 *device;
2414     WNDCLASSA wc = {0};
2415     IDirect3D8 *d3d8;
2416     HANDLE thread;
2417     LONG_PTR proc;
2418     HRESULT hr;
2419     ULONG ref;
2420     DWORD res, tid;
2421     HWND tmp;
2422
2423     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2424     {
2425         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2426         return;
2427     }
2428
2429     wc.lpfnWndProc = test_proc;
2430     wc.lpszClassName = "d3d8_test_wndproc_wc";
2431     ok(RegisterClassA(&wc), "Failed to register window class.\n");
2432
2433     thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2434     ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2435     thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2436     ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2437
2438     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2439             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2440     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2441             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2442     thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2443     ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2444
2445     res = WaitForSingleObject(thread_params.window_created, INFINITE);
2446     ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2447
2448     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2449     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2450             (LONG_PTR)test_proc, proc);
2451     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2452     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2453             (LONG_PTR)test_proc, proc);
2454
2455     trace("device_window %p, focus_window %p, dummy_window %p.\n",
2456             device_window, focus_window, thread_params.dummy_window);
2457
2458     tmp = GetFocus();
2459     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2460     if (thread_params.running_in_foreground)
2461     {
2462         tmp = GetForegroundWindow();
2463         ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2464                 thread_params.dummy_window, tmp);
2465     }
2466     else
2467         skip("Not running in foreground, skip foreground window test\n");
2468
2469     filter_messages = focus_window;
2470
2471     device = create_device(d3d8, device_window, focus_window, TRUE);
2472     if (!device)
2473     {
2474         skip("Failed to create a D3D device, skipping tests.\n");
2475         goto done;
2476     }
2477
2478     tmp = GetFocus();
2479     ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2480     tmp = GetForegroundWindow();
2481     ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2482             thread_params.dummy_window, tmp);
2483
2484     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2485     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2486             (LONG_PTR)test_proc, proc);
2487
2488     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2489     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2490             (LONG_PTR)test_proc, proc);
2491
2492     filter_messages = NULL;
2493
2494     hr = reset_device(device, device_window, FALSE);
2495     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2496
2497     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2498     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2499             (LONG_PTR)test_proc, proc);
2500
2501     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2502     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2503             (LONG_PTR)test_proc, proc);
2504
2505     hr = reset_device(device, device_window, TRUE);
2506     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2507
2508     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2509     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2510             (LONG_PTR)test_proc, proc);
2511
2512     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2513     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2514             (LONG_PTR)test_proc, proc);
2515
2516     filter_messages = focus_window;
2517
2518     ref = IDirect3DDevice8_Release(device);
2519     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2520
2521     filter_messages = device_window;
2522
2523     device = create_device(d3d8, focus_window, focus_window, TRUE);
2524     if (!device)
2525     {
2526         skip("Failed to create a D3D device, skipping tests.\n");
2527         goto done;
2528     }
2529
2530     filter_messages = NULL;
2531
2532     hr = reset_device(device, focus_window, FALSE);
2533     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2534
2535     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2536     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2537             (LONG_PTR)test_proc, proc);
2538
2539     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2540     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2541             (LONG_PTR)test_proc, proc);
2542
2543     hr = reset_device(device, focus_window, TRUE);
2544     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2545
2546     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2547     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2548             (LONG_PTR)test_proc, proc);
2549
2550     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2551     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2552             (LONG_PTR)test_proc, proc);
2553
2554     filter_messages = device_window;
2555
2556     ref = IDirect3DDevice8_Release(device);
2557     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2558
2559     device = create_device(d3d8, device_window, focus_window, TRUE);
2560     if (!device)
2561     {
2562         skip("Failed to create a D3D device, skipping tests.\n");
2563         goto done;
2564     }
2565
2566     filter_messages = NULL;
2567
2568     hr = reset_device(device, device_window, FALSE);
2569     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2570
2571     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2572     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2573             (LONG_PTR)test_proc, proc);
2574
2575     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2576     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2577             (LONG_PTR)test_proc, proc);
2578
2579     hr = reset_device(device, device_window, TRUE);
2580     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2581
2582     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2583     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2584             (LONG_PTR)test_proc, proc);
2585
2586     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2587     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2588             (LONG_PTR)test_proc, proc);
2589
2590     filter_messages = device_window;
2591
2592     ref = IDirect3DDevice8_Release(device);
2593     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2594
2595 done:
2596     filter_messages = NULL;
2597     IDirect3D8_Release(d3d8);
2598
2599     SetEvent(thread_params.test_finished);
2600     WaitForSingleObject(thread, INFINITE);
2601     CloseHandle(thread_params.test_finished);
2602     CloseHandle(thread_params.window_created);
2603     CloseHandle(thread);
2604
2605     DestroyWindow(device_window);
2606     DestroyWindow(focus_window);
2607     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
2608 }
2609
2610 static inline void set_fpu_cw(WORD cw)
2611 {
2612 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2613 #define D3D8_TEST_SET_FPU_CW 1
2614     __asm__ volatile ("fnclex");
2615     __asm__ volatile ("fldcw %0" : : "m" (cw));
2616 #elif defined(__i386__) && defined(_MSC_VER)
2617 #define D3D8_TEST_SET_FPU_CW 1
2618     __asm fnclex;
2619     __asm fldcw cw;
2620 #endif
2621 }
2622
2623 static inline WORD get_fpu_cw(void)
2624 {
2625     WORD cw = 0;
2626 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
2627 #define D3D8_TEST_GET_FPU_CW 1
2628     __asm__ volatile ("fnstcw %0" : "=m" (cw));
2629 #elif defined(__i386__) && defined(_MSC_VER)
2630 #define D3D8_TEST_GET_FPU_CW 1
2631     __asm fnstcw cw;
2632 #endif
2633     return cw;
2634 }
2635
2636 static void test_fpu_setup(void)
2637 {
2638 #if defined(D3D8_TEST_SET_FPU_CW) && defined(D3D8_TEST_GET_FPU_CW)
2639     D3DPRESENT_PARAMETERS present_parameters;
2640     IDirect3DDevice8 *device;
2641     D3DDISPLAYMODE d3ddm;
2642     HWND window = NULL;
2643     IDirect3D8 *d3d8;
2644     HRESULT hr;
2645     WORD cw;
2646
2647     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
2648     ok(!!d3d8, "Failed to create a d3d8 object.\n");
2649     if (!d3d8) return;
2650
2651     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2652     ok(!!window, "Failed to create a window.\n");
2653     if (!window) goto done;
2654
2655     hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
2656     ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
2657
2658     memset(&present_parameters, 0, sizeof(present_parameters));
2659     present_parameters.Windowed = TRUE;
2660     present_parameters.hDeviceWindow = window;
2661     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2662     present_parameters.BackBufferFormat = d3ddm.Format;
2663
2664     set_fpu_cw(0xf60);
2665     cw = get_fpu_cw();
2666     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2667
2668     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2669             D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
2670     if (FAILED(hr))
2671     {
2672         skip("Failed to create a device, hr %#x.\n", hr);
2673         set_fpu_cw(0x37f);
2674         goto done;
2675     }
2676
2677     cw = get_fpu_cw();
2678     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2679
2680     IDirect3DDevice8_Release(device);
2681
2682     cw = get_fpu_cw();
2683     ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
2684     set_fpu_cw(0xf60);
2685     cw = get_fpu_cw();
2686     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2687
2688     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
2689             D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
2690     ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
2691
2692     cw = get_fpu_cw();
2693     ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
2694     set_fpu_cw(0x37f);
2695
2696     IDirect3DDevice8_Release(device);
2697
2698 done:
2699     if (window) DestroyWindow(window);
2700     if (d3d8) IDirect3D8_Release(d3d8);
2701 #endif
2702 }
2703
2704 static void test_ApplyStateBlock(void)
2705 {
2706     D3DPRESENT_PARAMETERS d3dpp;
2707     IDirect3DDevice8 *device = NULL;
2708     IDirect3D8 *d3d8;
2709     HWND hwnd;
2710     HRESULT hr;
2711     D3DDISPLAYMODE d3ddm;
2712     DWORD received, token;
2713
2714     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2715     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2716     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2717     ok(hwnd != NULL, "Failed to create window\n");
2718     if (!d3d8 || !hwnd) goto cleanup;
2719
2720     IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
2721     ZeroMemory( &d3dpp, sizeof(d3dpp) );
2722     d3dpp.Windowed         = TRUE;
2723     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
2724     d3dpp.BackBufferWidth  = 800;
2725     d3dpp.BackBufferHeight  = 600;
2726     d3dpp.BackBufferFormat = d3ddm.Format;
2727     d3dpp.EnableAutoDepthStencil = TRUE;
2728     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2729
2730     hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2731                                   D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device );
2732     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2733        "IDirect3D8_CreateDevice failed with %#x\n", hr);
2734     if(!device)
2735     {
2736         skip("Failed to create a d3d device\n");
2737         goto cleanup;
2738     }
2739
2740     IDirect3DDevice8_BeginStateBlock(device);
2741     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
2742     IDirect3DDevice8_EndStateBlock(device, &token);
2743     ok(token, "Received zero stateblock handle.\n");
2744     IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
2745
2746     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2747     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2748     ok(!received, "Expected = FALSE, received TRUE.\n");
2749
2750     hr = IDirect3DDevice8_ApplyStateBlock(device, 0);
2751     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2752     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2753     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2754     ok(!received, "Expected FALSE, received TRUE.\n");
2755
2756     hr = IDirect3DDevice8_ApplyStateBlock(device, token);
2757     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2758     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
2759     ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
2760     ok(received, "Expected TRUE, received FALSE.\n");
2761
2762     IDirect3DDevice8_DeleteStateBlock(device, token);
2763     IDirect3DDevice8_Release(device);
2764 cleanup:
2765     if (d3d8) IDirect3D8_Release(d3d8);
2766     DestroyWindow(hwnd);
2767 }
2768
2769 static void test_depth_stencil_size(void)
2770 {
2771     IDirect3DDevice8 *device;
2772     IDirect3DSurface8 *ds, *rt, *ds_bigger, *ds_bigger2;
2773     IDirect3DSurface8 *surf;
2774     IDirect3D8 *d3d8;
2775     HRESULT hr;
2776     HWND hwnd;
2777
2778     d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
2779     ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
2780     hwnd = CreateWindow( "d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2781     ok(hwnd != NULL, "Failed to create window\n");
2782     if (!d3d8 || !hwnd) goto cleanup;
2783
2784     device = create_device(d3d8, hwnd, hwnd, TRUE);
2785     if (!device) goto cleanup;
2786
2787     hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
2788     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateRenderTarget failed, hr %#x.\n", hr);
2789     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds);
2790     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2791     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger);
2792     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2793     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger2);
2794     ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
2795
2796     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2797     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2798     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds_bigger);
2799     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2800
2801     /* try to set the small ds without changing the render target at the same time */
2802     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds);
2803     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
2804     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds_bigger2);
2805     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2806
2807     hr = IDirect3DDevice8_GetRenderTarget(device, &surf);
2808     ok(hr == D3D_OK, "IDirect3DDevice8_GetRenderTarget failed, hr %#x.\n", hr);
2809     ok(surf == rt, "The render target is %p, expected %p\n", surf, rt);
2810     IDirect3DSurface8_Release(surf);
2811     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2812     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr %#x.\n", hr);
2813     ok(surf == ds_bigger2, "The depth stencil is %p, expected %p\n", surf, ds_bigger2);
2814     IDirect3DSurface8_Release(surf);
2815
2816     hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2817     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
2818     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
2819     ok(FAILED(hr), "IDirect3DDevice8_GetDepthStencilSurface should have failed, hr %#x.\n", hr);
2820     ok(surf == NULL, "The depth stencil is %p, expected NULL\n", surf);
2821     if (surf) IDirect3DSurface8_Release(surf);
2822
2823     IDirect3DSurface8_Release(rt);
2824     IDirect3DSurface8_Release(ds);
2825     IDirect3DSurface8_Release(ds_bigger);
2826     IDirect3DSurface8_Release(ds_bigger2);
2827
2828 cleanup:
2829     if (d3d8) IDirect3D8_Release(d3d8);
2830     DestroyWindow(hwnd);
2831 }
2832
2833 static void test_window_style(void)
2834 {
2835     RECT focus_rect, fullscreen_rect, r;
2836     LONG device_style, device_exstyle;
2837     LONG focus_style, focus_exstyle;
2838     LONG style, expected_style;
2839     IDirect3DDevice8 *device;
2840     IDirect3D8 *d3d8;
2841     HRESULT hr;
2842     ULONG ref;
2843
2844
2845     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
2846     {
2847         skip("Failed to create IDirect3D8 object, skipping tests.\n");
2848         return;
2849     }
2850
2851     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2852             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2853     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2854             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
2855
2856     device_style = GetWindowLongA(device_window, GWL_STYLE);
2857     device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
2858     focus_style = GetWindowLongA(focus_window, GWL_STYLE);
2859     focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
2860
2861     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
2862     GetWindowRect(focus_window, &focus_rect);
2863
2864     device = create_device(d3d8, device_window, focus_window, FALSE);
2865     if (!device)
2866     {
2867         skip("Failed to create a D3D device, skipping tests.\n");
2868         goto done;
2869     }
2870
2871     style = GetWindowLongA(device_window, GWL_STYLE);
2872     expected_style = device_style | WS_VISIBLE;
2873     todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
2874             expected_style, style);
2875     style = GetWindowLongA(device_window, GWL_EXSTYLE);
2876     expected_style = device_exstyle | WS_EX_TOPMOST;
2877     todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
2878             expected_style, style);
2879
2880     style = GetWindowLongA(focus_window, GWL_STYLE);
2881     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
2882             focus_style, style);
2883     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
2884     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
2885             focus_exstyle, style);
2886
2887     GetWindowRect(device_window, &r);
2888     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2889             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
2890             r.left, r.top, r.right, r.bottom);
2891     GetClientRect(device_window, &r);
2892     todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
2893     GetWindowRect(focus_window, &r);
2894     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
2895             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
2896             r.left, r.top, r.right, r.bottom);
2897
2898     hr = reset_device(device, device_window, TRUE);
2899     ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2900
2901     style = GetWindowLongA(device_window, GWL_STYLE);
2902     expected_style = device_style | WS_VISIBLE;
2903     ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
2904             expected_style, style);
2905     style = GetWindowLongA(device_window, GWL_EXSTYLE);
2906     expected_style = device_exstyle | WS_EX_TOPMOST;
2907     ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
2908             expected_style, style);
2909
2910     style = GetWindowLongA(focus_window, GWL_STYLE);
2911     ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
2912             focus_style, style);
2913     style = GetWindowLongA(focus_window, GWL_EXSTYLE);
2914     ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
2915             focus_exstyle, style);
2916
2917
2918     ref = IDirect3DDevice8_Release(device);
2919     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2920
2921 done:
2922     IDirect3D8_Release(d3d8);
2923
2924     DestroyWindow(device_window);
2925     DestroyWindow(focus_window);
2926 }
2927
2928 static void test_wrong_shader(void)
2929 {
2930     HRESULT hr;
2931     HWND hwnd = NULL;
2932     IDirect3D8 *d3d = NULL;
2933     IDirect3DDevice8 *device = NULL;
2934     D3DPRESENT_PARAMETERS d3dpp;
2935     D3DDISPLAYMODE d3ddm;
2936     DWORD vs, ps;
2937
2938     static const DWORD vs_2_0[] =
2939     {
2940         0xfffe0200,                                         /* vs_2_0           */
2941         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
2942         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2943         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
2944         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
2945         0x0000ffff                                          /* end              */
2946     };
2947     static const DWORD ps_2_0[] =
2948     {
2949         0xffff0200,                                         /* ps_2_0           */
2950         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
2951         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
2952         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
2953         0x0000ffff                                          /* end              */
2954     };
2955
2956     static const DWORD decl[] =
2957     {
2958         D3DVSD_STREAM(0),
2959         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
2960         D3DVSD_END()
2961     };
2962
2963     d3d = pDirect3DCreate8(D3D_SDK_VERSION);
2964     ok(d3d != NULL, "Failed to create IDirect3D8 object\n");
2965     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2966     ok(hwnd != NULL, "Failed to create window\n");
2967     if (!d3d || !hwnd)
2968         goto cleanup;
2969
2970     IDirect3D8_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2971     ZeroMemory(&d3dpp, sizeof(d3dpp));
2972     d3dpp.Windowed = TRUE;
2973     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2974     d3dpp.BackBufferWidth = 800;
2975     d3dpp.BackBufferHeight = 600;
2976     d3dpp.BackBufferFormat = d3ddm.Format;
2977
2978     hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2979             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
2980     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
2981     if (!device)
2982     {
2983         skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
2984         goto cleanup;
2985     }
2986
2987     hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_ps, &vs, 0);
2988     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2989
2990     hr = IDirect3DDevice8_CreatePixelShader(device, simple_vs, &ps);
2991     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2992
2993     hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_2_0, &vs, 0);
2994     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2995
2996     hr = IDirect3DDevice8_CreatePixelShader(device, ps_2_0, &ps);
2997     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2998
2999 cleanup:
3000     if (device)
3001     {
3002         UINT refcount = IDirect3DDevice8_Release(device);
3003         ok(!refcount, "Device has %u references left.\n", refcount);
3004     }
3005     if (d3d)
3006         IDirect3D8_Release(d3d);
3007     DestroyWindow(hwnd);
3008 }
3009
3010 static void test_mode_change(void)
3011 {
3012     RECT fullscreen_rect, focus_rect, r;
3013     IDirect3DSurface8 *backbuffer;
3014     IDirect3DDevice8 *device;
3015     D3DSURFACE_DESC desc;
3016     IDirect3D8 *d3d8;
3017     DEVMODEW devmode;
3018     UINT refcount;
3019     HRESULT hr;
3020     DWORD ret;
3021
3022     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3023     {
3024         skip("Failed to create IDirect3D8 object, skipping mode change tests.\n");
3025         return;
3026     }
3027
3028     focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3029             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3030     device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3031             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3032
3033     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3034     GetWindowRect(focus_window, &focus_rect);
3035
3036     device = create_device(d3d8, device_window, focus_window, FALSE);
3037     if (!device)
3038     {
3039         skip("Failed to create a D3D device, skipping tests.\n");
3040         goto done;
3041     }
3042
3043     memset(&devmode, 0, sizeof(devmode));
3044     devmode.dmSize = sizeof(devmode);
3045     devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3046     devmode.dmPelsWidth = 640;
3047     devmode.dmPelsHeight = 480;
3048
3049     ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3050     ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3051
3052     memset(&devmode, 0, sizeof(devmode));
3053     devmode.dmSize = sizeof(devmode);
3054     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3055     ok(ret, "Failed to get display mode.\n");
3056     ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3057     ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3058
3059     GetWindowRect(device_window, &r);
3060     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3061             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3062             r.left, r.top, r.right, r.bottom);
3063     GetWindowRect(focus_window, &r);
3064     ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3065             focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3066             r.left, r.top, r.right, r.bottom);
3067
3068     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3069     ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3070     hr = IDirect3DSurface8_GetDesc(backbuffer, &desc);
3071     ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3072     ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3073     ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3074     IDirect3DSurface8_Release(backbuffer);
3075
3076     refcount = IDirect3DDevice8_Release(device);
3077     ok(!refcount, "Device has %u references left.\n", refcount);
3078
3079     memset(&devmode, 0, sizeof(devmode));
3080     devmode.dmSize = sizeof(devmode);
3081     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3082     ok(ret, "Failed to get display mode.\n");
3083     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3084     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3085
3086 done:
3087     DestroyWindow(device_window);
3088     DestroyWindow(focus_window);
3089     if (d3d8)
3090         IDirect3D8_Release(d3d8);
3091
3092     memset(&devmode, 0, sizeof(devmode));
3093     devmode.dmSize = sizeof(devmode);
3094     ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3095     ok(ret, "Failed to get display mode.\n");
3096     ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3097     ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3098 }
3099
3100 static void test_device_window_reset(void)
3101 {
3102     RECT fullscreen_rect, device_rect, r;
3103     IDirect3DDevice8 *device;
3104     WNDCLASSA wc = {0};
3105     IDirect3D8 *d3d8;
3106     LONG_PTR proc;
3107     HRESULT hr;
3108     ULONG ref;
3109
3110     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3111     {
3112         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3113         return;
3114     }
3115
3116     wc.lpfnWndProc = test_proc;
3117     wc.lpszClassName = "d3d8_test_wndproc_wc";
3118     ok(RegisterClassA(&wc), "Failed to register window class.\n");
3119
3120     focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3121             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3122     device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3123             0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3124
3125     SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3126     GetWindowRect(device_window, &device_rect);
3127
3128     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3129     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3130             (LONG_PTR)test_proc, proc);
3131     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3132     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3133             (LONG_PTR)test_proc, proc);
3134
3135     device = create_device(d3d8, NULL, focus_window, FALSE);
3136     if (!device)
3137     {
3138         skip("Failed to create a D3D device, skipping tests.\n");
3139         goto done;
3140     }
3141
3142     GetWindowRect(focus_window, &r);
3143     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3144             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3145             r.left, r.top, r.right, r.bottom);
3146     GetWindowRect(device_window, &r);
3147     ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3148             device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3149             r.left, r.top, r.right, r.bottom);
3150
3151     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3152     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3153             (LONG_PTR)test_proc, proc);
3154     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3155     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3156             (LONG_PTR)test_proc, proc);
3157
3158     hr = reset_device(device, device_window, FALSE);
3159     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3160
3161     GetWindowRect(focus_window, &r);
3162     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3163             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3164             r.left, r.top, r.right, r.bottom);
3165     GetWindowRect(device_window, &r);
3166     ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3167             fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3168             r.left, r.top, r.right, r.bottom);
3169
3170     proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3171     ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3172             (LONG_PTR)test_proc, proc);
3173     proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3174     ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3175             (LONG_PTR)test_proc, proc);
3176
3177     ref = IDirect3DDevice8_Release(device);
3178     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3179
3180 done:
3181     IDirect3D8_Release(d3d8);
3182     DestroyWindow(device_window);
3183     DestroyWindow(focus_window);
3184     UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3185 }
3186
3187 static void depth_blit_test(void)
3188 {
3189     HWND hwnd = NULL;
3190     IDirect3D8 *d3d8 = NULL;
3191     IDirect3DDevice8 *device = NULL;
3192     IDirect3DSurface8 *backbuffer, *ds1, *ds2, *ds3;
3193     RECT src_rect;
3194     const POINT dst_point = {0, 0};
3195     HRESULT hr;
3196
3197     d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
3198     ok(d3d8 != NULL, "Direct3DCreate8 failed.\n");
3199     hwnd = CreateWindow("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
3200     ok(hwnd != NULL, "CreateWindow failed.\n");
3201     if (!d3d8 || !hwnd)
3202         goto done;
3203
3204     device = create_device(d3d8, hwnd, hwnd, TRUE);
3205     if (!device)
3206     {
3207         skip("Failed to create a D3D device, skipping tests.\n");
3208         goto done;
3209     }
3210
3211     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
3212     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
3213     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds1);
3214     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
3215     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds2);
3216     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3217     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds3);
3218     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
3219
3220     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
3221     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
3222
3223     /* Partial blit. */
3224     SetRect(&src_rect, 0, 0, 320, 240);
3225     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3226     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3227     /* Flipped. */
3228     SetRect(&src_rect, 0, 480, 640, 0);
3229     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3230     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3231     /* Full, explicit. */
3232     SetRect(&src_rect, 0, 0, 640, 480);
3233     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
3234     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3235     /* Depth -> color blit.*/
3236     hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, backbuffer, &dst_point);
3237     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3238     /* Full, NULL rects, current depth stencil -> unbound depth stencil */
3239     hr = IDirect3DDevice8_CopyRects(device, ds1, NULL, 0, ds2, NULL);
3240     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3241     /* Full, NULL rects, unbound depth stencil -> current depth stencil */
3242     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds1, NULL);
3243     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3244     /* Full, NULL rects, unbound depth stencil -> unbound depth stencil */
3245     hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds3, NULL);
3246     ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
3247
3248     IDirect3DSurface8_Release(backbuffer);
3249     IDirect3DSurface8_Release(ds3);
3250     IDirect3DSurface8_Release(ds2);
3251     IDirect3DSurface8_Release(ds1);
3252
3253 done:
3254     if (device) IDirect3DDevice8_Release(device);
3255     if (d3d8) IDirect3D8_Release(d3d8);
3256     if (hwnd) DestroyWindow(hwnd);
3257 }
3258
3259 static void test_reset_resources(void)
3260 {
3261     IDirect3DSurface8 *surface, *rt;
3262     IDirect3DTexture8 *texture;
3263     IDirect3DDevice8 *device;
3264     IDirect3D8 *d3d8;
3265     HWND window;
3266     HRESULT hr;
3267     ULONG ref;
3268
3269     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
3270             0, 0, 640, 480, 0, 0, 0, 0);
3271
3272     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3273     {
3274         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3275         DestroyWindow(window);
3276         return;
3277     }
3278
3279     if (!(device = create_device(d3d8, window, window, TRUE)))
3280     {
3281         skip("Failed to create a D3D device, skipping tests.\n");
3282         goto done;
3283     }
3284
3285     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24S8,
3286             D3DMULTISAMPLE_NONE, &surface);
3287     ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
3288
3289     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3290             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3291     ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr);
3292     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &rt);
3293     ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
3294     IDirect3DTexture8_Release(texture);
3295
3296     hr = IDirect3DDevice8_SetRenderTarget(device, rt, surface);
3297     ok(SUCCEEDED(hr), "Failed to set render target surface, hr %#x.\n", hr);
3298     IDirect3DSurface8_Release(rt);
3299     IDirect3DSurface8_Release(surface);
3300
3301     hr = reset_device(device, device_window, TRUE);
3302     ok(SUCCEEDED(hr), "Failed to reset device.\n");
3303
3304     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3305     ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3306     hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3307     ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3308     ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3309     IDirect3DSurface8_Release(surface);
3310     IDirect3DSurface8_Release(rt);
3311
3312     ref = IDirect3DDevice8_Release(device);
3313     ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3314
3315 done:
3316     IDirect3D8_Release(d3d8);
3317     DestroyWindow(window);
3318 }
3319
3320 static void test_set_rt_vp_scissor(void)
3321 {
3322     IDirect3DDevice8 *device;
3323     IDirect3DSurface8 *rt;
3324     IDirect3D8 *d3d8;
3325     DWORD stateblock;
3326     D3DVIEWPORT8 vp;
3327     UINT refcount;
3328     HWND window;
3329     HRESULT hr;
3330
3331     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3332     {
3333         skip("Failed to create IDirect3D8 object, skipping tests.\n");
3334         return;
3335     }
3336
3337     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
3338             0, 0, 640, 480, 0, 0, 0, 0);
3339     if (!(device = create_device(d3d8, window, window, TRUE)))
3340     {
3341         skip("Failed to create a D3D device, skipping tests.\n");
3342         DestroyWindow(window);
3343         return;
3344     }
3345
3346     hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3347             D3DMULTISAMPLE_NONE, FALSE, &rt);
3348     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3349
3350     hr = IDirect3DDevice8_GetViewport(device, &vp);
3351     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3352     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3353     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3354     ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3355     ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3356     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3357     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3358
3359     hr = IDirect3DDevice8_BeginStateBlock(device);
3360     ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3361
3362     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3363     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3364
3365     hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
3366     ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3367     hr = IDirect3DDevice8_DeleteStateBlock(device, stateblock);
3368     ok(SUCCEEDED(hr), "Failed to delete stateblock, hr %#x.\n", hr);
3369
3370     hr = IDirect3DDevice8_GetViewport(device, &vp);
3371     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3372     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3373     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3374     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3375     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3376     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3377     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3378
3379     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3380     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3381
3382     vp.X = 10;
3383     vp.Y = 20;
3384     vp.Width = 30;
3385     vp.Height = 40;
3386     vp.MinZ = 0.25f;
3387     vp.MaxZ = 0.75f;
3388     hr = IDirect3DDevice8_SetViewport(device, &vp);
3389     ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3390
3391     hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
3392     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3393
3394     hr = IDirect3DDevice8_GetViewport(device, &vp);
3395     ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3396     ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3397     ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3398     ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3399     ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3400     ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3401     ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3402
3403     IDirect3DSurface8_Release(rt);
3404     refcount = IDirect3DDevice8_Release(device);
3405     ok(!refcount, "Device has %u references left.\n", refcount);
3406     IDirect3D8_Release(d3d8);
3407     DestroyWindow(window);
3408 }
3409
3410 static void test_validate_vs(void)
3411 {
3412     static DWORD vs[] =
3413     {
3414         0xfffe0101,                                                             /* vs_1_1                       */
3415         0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000,                         /* dp4 oPos.x, v0, c0           */
3416         0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001,                         /* dp4 oPos.y, v0, c1           */
3417         0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002,                         /* dp4 oPos.z, v0, c2           */
3418         0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003,                         /* dp4 oPos.w, v0, c3           */
3419         0x0000ffff,                                                             /* end                          */
3420     };
3421     HRESULT hr;
3422
3423     hr = ValidateVertexShader(0, 0, 0, 0, 0);
3424     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3425     hr = ValidateVertexShader(0, 0, 0, 1, 0);
3426     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3427     hr = ValidateVertexShader(vs, 0, 0, 0, 0);
3428     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3429
3430     hr = ValidateVertexShader(vs, 0, 0, 1, 0);
3431     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3432     /* Seems to do some version checking. */
3433     *vs = 0xfffe0100;                                                           /* vs_1_0                       */
3434     hr = ValidateVertexShader(vs, 0, 0, 0, 0);
3435     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3436
3437     *vs = 0xfffe0102;                                                           /* bogus version                */
3438     hr = ValidateVertexShader(vs, 0, 0, 1, 0);
3439     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3440     /* I've seen that applications always pass the 2nd and 3rd parameter as 0.
3441      * Simple test with non-zero parameters. */
3442     *vs = 0xfffe0101;                                                           /* vs_1_1                       */
3443     hr = ValidateVertexShader(vs, vs, 0, 1, 0);
3444     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3445
3446     hr = ValidateVertexShader(vs, 0, vs, 1, 0);
3447     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3448     /* I've seen the 4th parameter always passed as either 0 or 1, but passing
3449      * other values doesn't seem to hurt. */
3450     hr = ValidateVertexShader(vs, 0, 0, 12345, 0);
3451     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3452     /* What is the 5th parameter? The following seems to work ok. */
3453     hr = ValidateVertexShader(vs, 0, 0, 1, vs);
3454     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3455 }
3456
3457 static void test_validate_ps(void)
3458 {
3459     static DWORD ps[] =
3460     {
3461         0xffff0101,                                                             /* ps_1_1                       */
3462         0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
3463         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
3464         0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000,                         /* dp3 r0, c1, c0               */
3465         0x00000005, 0x800f0000, 0x90e40000, 0x80e40000,                         /* mul r0, v0, r0               */
3466         0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000,                         /* mul r0, t0, r0               */
3467         0x0000ffff,                                                             /* end                          */
3468     };
3469     HRESULT hr;
3470
3471     hr = ValidatePixelShader(0, 0, 0, 0);
3472     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3473     hr = ValidatePixelShader(0, 0, 1, 0);
3474     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3475     hr = ValidatePixelShader(ps, 0, 0, 0);
3476     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3477
3478     hr = ValidatePixelShader(ps, 0, 1, 0);
3479     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3480     /* Seems to do some version checking. */
3481     *ps = 0xffff0105;                                                           /* bogus version                */
3482     hr = ValidatePixelShader(ps, 0, 1, 0);
3483     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3484     /* I've seen that applications always pass the 2nd parameter as 0.
3485      * Simple test with a non-zero parameter. */
3486     *ps = 0xffff0101;                                                           /* ps_1_1                       */
3487     hr = ValidatePixelShader(ps, ps, 1, 0);
3488     ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
3489     /* I've seen th 3rd parameter always passed as either 0 or 1, but passing
3490      * other values doesn't seem to hurt. */
3491     hr = ValidatePixelShader(ps, 0, 12345, 0);
3492     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3493     /* What is the 4th parameter? The following seems to work ok. */
3494     hr = ValidatePixelShader(ps, 0, 1, ps);
3495     ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3496 }
3497
3498 static void test_volume_get_container(void)
3499 {
3500     IDirect3DVolumeTexture8 *texture = NULL;
3501     IDirect3DVolume8 *volume = NULL;
3502     IDirect3DDevice8 *device;
3503     IUnknown *container;
3504     IDirect3D8 *d3d8;
3505     ULONG refcount;
3506     D3DCAPS8 caps;
3507     HWND window;
3508     HRESULT hr;
3509
3510     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3511     {
3512         skip("Failed to create d3d8 object, skipping tests.\n");
3513         return;
3514     }
3515
3516     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3517             0, 0, 640, 480, 0, 0, 0, 0);
3518     if (!(device = create_device(d3d8, window, window, TRUE)))
3519     {
3520         skip("Failed to create a D3D device, skipping tests.\n");
3521         IDirect3D8_Release(d3d8);
3522         DestroyWindow(window);
3523         return;
3524     }
3525
3526     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3527     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3528     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3529     {
3530         skip("No volume texture support, skipping tests.\n");
3531         IDirect3DDevice8_Release(device);
3532         IDirect3D8_Release(d3d8);
3533         DestroyWindow(window);
3534         return;
3535     }
3536
3537     hr = IDirect3DDevice8_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3538             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3539     ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3540     ok(!!texture, "Got unexpected texture %p.\n", texture);
3541
3542     hr = IDirect3DVolumeTexture8_GetVolumeLevel(texture, 0, &volume);
3543     ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3544     ok(!!volume, "Got unexpected volume %p.\n", volume);
3545
3546     /* These should work... */
3547     container = NULL;
3548     hr = IDirect3DVolume8_GetContainer(volume, &IID_IUnknown, (void **)&container);
3549     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3550     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3551     IUnknown_Release(container);
3552
3553     container = NULL;
3554     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DResource8, (void **)&container);
3555     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3556     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3557     IUnknown_Release(container);
3558
3559     container = NULL;
3560     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DBaseTexture8, (void **)&container);
3561     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3562     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3563     IUnknown_Release(container);
3564
3565     container = NULL;
3566     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolumeTexture8, (void **)&container);
3567     ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3568     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3569     IUnknown_Release(container);
3570
3571     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3572     hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolume8, (void **)&container);
3573     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3574     ok(!container, "Got unexpected container %p.\n", container);
3575
3576     IDirect3DVolume8_Release(volume);
3577     IDirect3DVolumeTexture8_Release(texture);
3578     refcount = IDirect3DDevice8_Release(device);
3579     ok(!refcount, "Device has %u references left.\n", refcount);
3580     IDirect3D8_Release(d3d8);
3581     DestroyWindow(window);
3582 }
3583
3584 static void test_vb_lock_flags(void)
3585 {
3586     static const struct
3587     {
3588         DWORD flags;
3589         const char *debug_string;
3590         HRESULT result;
3591     }
3592     test_data[] =
3593     {
3594         {D3DLOCK_READONLY,                          "D3DLOCK_READONLY",                         D3D_OK            },
3595         {D3DLOCK_DISCARD,                           "D3DLOCK_DISCARD",                          D3D_OK            },
3596         {D3DLOCK_NOOVERWRITE,                       "D3DLOCK_NOOVERWRITE",                      D3D_OK            },
3597         {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD,     "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD",    D3D_OK            },
3598         {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY,    "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY",   D3D_OK            },
3599         {D3DLOCK_READONLY    | D3DLOCK_DISCARD,     "D3DLOCK_READONLY | D3DLOCK_DISCARD",       D3D_OK            },
3600         /* Completely bogus flags aren't an error. */
3601         {0xdeadbeef,                                "0xdeadbeef",                               D3D_OK            },
3602     };
3603     IDirect3DVertexBuffer8 *buffer;
3604     IDirect3DDevice8 *device;
3605     IDirect3D8 *d3d8;
3606     unsigned int i;
3607     ULONG refcount;
3608     HWND window;
3609     HRESULT hr;
3610     BYTE *data;
3611
3612     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3613     {
3614         skip("Failed to create d3d8 object, skipping tests.\n");
3615         return;
3616     }
3617
3618     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3619             0, 0, 640, 480, 0, 0, 0, 0);
3620     if (!(device = create_device(d3d8, window, window, TRUE)))
3621     {
3622         skip("Failed to create a D3D device, skipping tests.\n");
3623         IDirect3D8_Release(d3d8);
3624         DestroyWindow(window);
3625         return;
3626     }
3627
3628     hr = IDirect3DDevice8_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer);
3629     ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3630
3631     for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
3632     {
3633         hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &data, test_data[i].flags);
3634         ok(hr == test_data[i].result, "Got unexpected hr %#x for %s.\n",
3635                 hr, test_data[i].debug_string);
3636         if (SUCCEEDED(hr))
3637         {
3638             ok(!!data, "Got unexpected data %p.\n", data);
3639             hr = IDirect3DVertexBuffer8_Unlock(buffer);
3640             ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3641         }
3642     }
3643
3644     IDirect3DVertexBuffer8_Release(buffer);
3645     refcount = IDirect3DDevice8_Release(device);
3646     ok(!refcount, "Device has %u references left.\n", refcount);
3647     IDirect3D8_Release(d3d8);
3648     DestroyWindow(window);
3649 }
3650
3651 /* Test the default texture stage state values */
3652 static void test_texture_stage_states(void)
3653 {
3654     IDirect3DDevice8 *device;
3655     IDirect3D8 *d3d8;
3656     unsigned int i;
3657     ULONG refcount;
3658     D3DCAPS8 caps;
3659     DWORD value;
3660     HWND window;
3661     HRESULT hr;
3662
3663     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3664     {
3665         skip("Failed to create d3d8 object, skipping tests.\n");
3666         return;
3667     }
3668
3669     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3670             0, 0, 640, 480, 0, 0, 0, 0);
3671     if (!(device = create_device(d3d8, window, window, TRUE)))
3672     {
3673         skip("Failed to create a D3D device, skipping tests.\n");
3674         IDirect3D8_Release(d3d8);
3675         DestroyWindow(window);
3676         return;
3677     }
3678
3679     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3680     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3681
3682     for (i = 0; i < caps.MaxTextureBlendStages; ++i)
3683     {
3684         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
3685         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3686         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
3687                 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
3688         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
3689         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3690         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
3691         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
3692         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3693         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
3694         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
3695         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3696         ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
3697                 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
3698         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
3699         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3700         ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
3701         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
3702         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3703         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
3704         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
3705         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3706         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
3707         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
3708         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3709         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
3710         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
3711         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3712         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
3713         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
3714         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3715         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
3716         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
3717         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3718         ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
3719         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
3720         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3721         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
3722         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
3723         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3724         ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
3725         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
3726         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3727         ok(value == D3DTTFF_DISABLE,
3728                 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
3729         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
3730         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3731         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
3732         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
3733         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3734         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
3735         hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
3736         ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
3737         ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
3738     }
3739
3740     refcount = IDirect3DDevice8_Release(device);
3741     ok(!refcount, "Device has %u references left.\n", refcount);
3742     IDirect3D8_Release(d3d8);
3743     DestroyWindow(window);
3744 }
3745
3746 static void test_cube_textures(void)
3747 {
3748     IDirect3DCubeTexture8 *texture;
3749     IDirect3DDevice8 *device;
3750     IDirect3D8 *d3d8;
3751     ULONG refcount;
3752     D3DCAPS8 caps;
3753     HWND window;
3754     HRESULT hr;
3755
3756     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3757     {
3758         skip("Failed to create d3d8 object, skipping tests.\n");
3759         return;
3760     }
3761
3762     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3763             0, 0, 640, 480, 0, 0, 0, 0);
3764     if (!(device = create_device(d3d8, window, window, TRUE)))
3765     {
3766         skip("Failed to create a D3D device, skipping tests.\n");
3767         IDirect3D8_Release(d3d8);
3768         DestroyWindow(window);
3769         return;
3770     }
3771
3772     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3773     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3774
3775     if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
3776     {
3777         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
3778         ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
3779         IDirect3DCubeTexture8_Release(texture);
3780         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
3781         ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
3782         IDirect3DCubeTexture8_Release(texture);
3783         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
3784         ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
3785         IDirect3DCubeTexture8_Release(texture);
3786     }
3787     else
3788     {
3789         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
3790         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
3791         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
3792         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
3793         hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
3794         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
3795     }
3796     hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture);
3797     ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
3798     IDirect3DCubeTexture8_Release(texture);
3799
3800     refcount = IDirect3DDevice8_Release(device);
3801     ok(!refcount, "Device has %u references left.\n", refcount);
3802     IDirect3D8_Release(d3d8);
3803     DestroyWindow(window);
3804 }
3805
3806 /* Test the behaviour of the IDirect3DDevice8::CreateImageSurface() method.
3807  *
3808  * The expected behaviour (as documented in the original DX8 docs) is that the
3809  * call returns a surface in the SYSTEMMEM pool. Games like Max Payne 1 and 2
3810  * depend on this behaviour.
3811  *
3812  * A short remark in the DX9 docs however states that the pool of the returned
3813  * surface object is D3DPOOL_SCRATCH. This is misinformation and would result
3814  * in screenshots not appearing in the savegame loading menu of both games
3815  * mentioned above (engine tries to display a texture from the scratch pool).
3816  *
3817  * This test verifies that the behaviour described in the original d3d8 docs
3818  * is the correct one. For more information about this issue, see the MSDN:
3819  *     d3d9 docs: "Converting to Direct3D 9"
3820  *     d3d9 reference: "IDirect3DDevice9::CreateOffscreenPlainSurface"
3821  *     d3d8 reference: "IDirect3DDevice8::CreateImageSurface" */
3822 static void test_image_surface_pool(void)
3823 {
3824     IDirect3DSurface8 *surface;
3825     IDirect3DDevice8 *device;
3826     D3DSURFACE_DESC desc;
3827     IDirect3D8 *d3d8;
3828     ULONG refcount;
3829     HWND window;
3830     HRESULT hr;
3831
3832     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3833     {
3834         skip("Failed to create d3d8 object, skipping tests.\n");
3835         return;
3836     }
3837
3838     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3839             0, 0, 640, 480, 0, 0, 0, 0);
3840     if (!(device = create_device(d3d8, window, window, TRUE)))
3841     {
3842         skip("Failed to create a D3D device, skipping tests.\n");
3843         IDirect3D8_Release(d3d8);
3844         DestroyWindow(window);
3845         return;
3846     }
3847
3848     hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
3849     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3850     hr = IDirect3DSurface8_GetDesc(surface, &desc);
3851     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3852     ok(desc.Pool == D3DPOOL_SYSTEMMEM, "Got unexpected pool %#x.\n", desc.Pool);
3853     IDirect3DSurface8_Release(surface);
3854
3855     refcount = IDirect3DDevice8_Release(device);
3856     ok(!refcount, "Device has %u references left.\n", refcount);
3857     IDirect3D8_Release(d3d8);
3858     DestroyWindow(window);
3859 }
3860
3861 static void test_surface_get_container(void)
3862 {
3863     IDirect3DTexture8 *texture = NULL;
3864     IDirect3DSurface8 *surface = NULL;
3865     IDirect3DDevice8 *device;
3866     IUnknown *container;
3867     IDirect3D8 *d3d8;
3868     ULONG refcount;
3869     HWND window;
3870     HRESULT hr;
3871
3872     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3873     {
3874         skip("Failed to create d3d8 object, skipping tests.\n");
3875         return;
3876     }
3877
3878     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3879             0, 0, 640, 480, 0, 0, 0, 0);
3880     if (!(device = create_device(d3d8, window, window, TRUE)))
3881     {
3882         skip("Failed to create a D3D device, skipping tests.\n");
3883         IDirect3D8_Release(d3d8);
3884         DestroyWindow(window);
3885         return;
3886     }
3887
3888     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0,
3889             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
3890     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
3891     ok(!!texture, "Got unexpected texture %p.\n", texture);
3892
3893     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
3894     ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
3895     ok(!!surface, "Got unexpected surface %p.\n", surface);
3896
3897     /* These should work... */
3898     container = NULL;
3899     hr = IDirect3DSurface8_GetContainer(surface, &IID_IUnknown, (void **)&container);
3900     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3901     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3902     IUnknown_Release(container);
3903
3904     container = NULL;
3905     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DResource8, (void **)&container);
3906     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3907     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3908     IUnknown_Release(container);
3909
3910     container = NULL;
3911     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DBaseTexture8, (void **)&container);
3912     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3913     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3914     IUnknown_Release(container);
3915
3916     container = NULL;
3917     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DTexture8, (void **)&container);
3918     ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
3919     ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3920     IUnknown_Release(container);
3921
3922     /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3923     hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DSurface8, (void **)&container);
3924     ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3925     ok(!container, "Got unexpected container %p.\n", container);
3926
3927     IDirect3DSurface8_Release(surface);
3928     IDirect3DTexture8_Release(texture);
3929     refcount = IDirect3DDevice8_Release(device);
3930     ok(!refcount, "Device has %u references left.\n", refcount);
3931     IDirect3D8_Release(d3d8);
3932     DestroyWindow(window);
3933 }
3934
3935 static void test_lockrect_invalid(void)
3936 {
3937     static const RECT valid[] =
3938     {
3939         {60, 60, 68, 68},
3940         {120, 60, 128, 68},
3941         {60, 120, 68, 128},
3942     };
3943     static const RECT invalid[] =
3944     {
3945         {60, 60, 60, 68},       /* 0 height */
3946         {60, 60, 68, 60},       /* 0 width */
3947         {68, 60, 60, 68},       /* left > right */
3948         {60, 68, 68, 60},       /* top > bottom */
3949         {-8, 60,  0, 68},       /* left < surface */
3950         {60, -8, 68,  0},       /* top < surface */
3951         {-16, 60, -8, 68},      /* right < surface */
3952         {60, -16, 68, -8},      /* bottom < surface */
3953         {60, 60, 136, 68},      /* right > surface */
3954         {60, 60, 68, 136},      /* bottom > surface */
3955         {136, 60, 144, 68},     /* left > surface */
3956         {60, 136, 68, 144},     /* top > surface */
3957     };
3958     IDirect3DSurface8 *surface = NULL;
3959     D3DLOCKED_RECT locked_rect;
3960     IDirect3DDevice8 *device;
3961     IDirect3D8 *d3d8;
3962     unsigned int i;
3963     ULONG refcount;
3964     HWND window;
3965     BYTE *base;
3966     HRESULT hr;
3967
3968     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
3969     {
3970         skip("Failed to create d3d8 object, skipping tests.\n");
3971         return;
3972     }
3973
3974     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3975             0, 0, 640, 480, 0, 0, 0, 0);
3976     if (!(device = create_device(d3d8, window, window, TRUE)))
3977     {
3978         skip("Failed to create a D3D device, skipping tests.\n");
3979         IDirect3D8_Release(d3d8);
3980         DestroyWindow(window);
3981         return;
3982     }
3983
3984     hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
3985     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
3986     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
3987     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
3988     base = locked_rect.pBits;
3989     hr = IDirect3DSurface8_UnlockRect(surface);
3990     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
3991
3992     for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
3993     {
3994         unsigned int offset, expected_offset;
3995         const RECT *rect = &valid[i];
3996
3997         locked_rect.pBits = (BYTE *)0xdeadbeef;
3998         locked_rect.Pitch = 0xdeadbeef;
3999
4000         hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
4001         ok(SUCCEEDED(hr), "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
4002                 rect->left, rect->top, rect->right, rect->bottom, hr);
4003
4004         offset = (BYTE *)locked_rect.pBits - base;
4005         expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
4006         ok(offset == expected_offset,
4007                 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
4008                 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
4009
4010         hr = IDirect3DSurface8_UnlockRect(surface);
4011         ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4012     }
4013
4014     for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
4015     {
4016         const RECT *rect = &invalid[i];
4017
4018         hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
4019         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
4020                 hr, rect->left, rect->top, rect->right, rect->bottom);
4021     }
4022
4023     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4024     ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
4025     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4026     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4027     hr = IDirect3DSurface8_UnlockRect(surface);
4028     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4029
4030     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
4031     ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
4032             hr, valid[0].left, valid[0].top, valid[0].right, valid[0].bottom);
4033     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
4034     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
4035             hr, valid[0].left, valid[0].top, valid[0].right, valid[0].bottom);
4036     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[1], 0);
4037     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
4038             hr, valid[1].left, valid[1].top, valid[1].right, valid[1].bottom);
4039     hr = IDirect3DSurface8_UnlockRect(surface);
4040     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4041
4042     IDirect3DSurface8_Release(surface);
4043     refcount = IDirect3DDevice8_Release(device);
4044     ok(!refcount, "Device has %u references left.\n", refcount);
4045     IDirect3D8_Release(d3d8);
4046     DestroyWindow(window);
4047 }
4048
4049 static void test_private_data(void)
4050 {
4051     ULONG refcount, expected_refcount;
4052     IDirect3DSurface8 *surface;
4053     IDirect3DDevice8 *device;
4054     IDirect3D8 *d3d8;
4055     IUnknown *ptr;
4056     HWND window;
4057     HRESULT hr;
4058     DWORD size;
4059
4060     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4061     {
4062         skip("Failed to create d3d8 object, skipping tests.\n");
4063         return;
4064     }
4065
4066     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4067             0, 0, 640, 480, 0, 0, 0, 0);
4068     if (!(device = create_device(d3d8, window, window, TRUE)))
4069     {
4070         skip("Failed to create a D3D device, skipping tests.\n");
4071         IDirect3D8_Release(d3d8);
4072         DestroyWindow(window);
4073         return;
4074     }
4075
4076     hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_A8R8G8B8, &surface);
4077     ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4078
4079     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4080             device, 0, D3DSPD_IUNKNOWN);
4081     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4082     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4083             device, 5, D3DSPD_IUNKNOWN);
4084     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4085     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4086             device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
4087     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4088
4089     refcount = get_refcount((IUnknown *)device);
4090     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8 /* Abuse this tag */,
4091             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4092     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4093     expected_refcount = refcount + 1;
4094     refcount = get_refcount((IUnknown *)device);
4095     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4096     hr = IDirect3DSurface8_FreePrivateData(surface, &IID_IDirect3DSurface8);
4097     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4098     expected_refcount = refcount - 1;
4099     refcount = get_refcount((IUnknown *)device);
4100     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4101
4102     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8,
4103             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4104     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4105     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8,
4106             surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4107     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4108     refcount = get_refcount((IUnknown *)device);
4109     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4110
4111     hr = IDirect3DSurface8_SetPrivateData(surface, &IID_IDirect3DSurface8,
4112             device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4113     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4114     size = sizeof(ptr);
4115     hr = IDirect3DSurface8_GetPrivateData(surface, &IID_IDirect3DSurface8, &ptr, &size);
4116     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4117     expected_refcount = refcount + 2;
4118     refcount = get_refcount((IUnknown *)device);
4119     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4120     ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
4121     IUnknown_Release(ptr);
4122
4123     /* Destroying the surface frees the held reference. */
4124     IDirect3DSurface8_Release(surface);
4125     expected_refcount = refcount - 3;
4126     refcount = get_refcount((IUnknown *)device);
4127     ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
4128
4129     refcount = IDirect3DDevice8_Release(device);
4130     ok(!refcount, "Device has %u references left.\n", refcount);
4131     IDirect3D8_Release(d3d8);
4132     DestroyWindow(window);
4133 }
4134
4135 static void test_surface_dimensions(void)
4136 {
4137     IDirect3DSurface8 *surface;
4138     IDirect3DDevice8 *device;
4139     IDirect3D8 *d3d8;
4140     ULONG refcount;
4141     HWND window;
4142     HRESULT hr;
4143
4144     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4145     {
4146         skip("Failed to create d3d8 object, skipping tests.\n");
4147         return;
4148     }
4149
4150     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4151             0, 0, 640, 480, 0, 0, 0, 0);
4152     if (!(device = create_device(d3d8, window, window, TRUE)))
4153     {
4154         skip("Failed to create a D3D device, skipping tests.\n");
4155         IDirect3D8_Release(d3d8);
4156         DestroyWindow(window);
4157         return;
4158     }
4159
4160     hr = IDirect3DDevice8_CreateImageSurface(device, 0, 1, D3DFMT_A8R8G8B8, &surface);
4161     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4162     hr = IDirect3DDevice8_CreateImageSurface(device, 1, 0, D3DFMT_A8R8G8B8, &surface);
4163     ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4164
4165     refcount = IDirect3DDevice8_Release(device);
4166     ok(!refcount, "Device has %u references left.\n", refcount);
4167     IDirect3D8_Release(d3d8);
4168     DestroyWindow(window);
4169 }
4170
4171 static void test_surface_format_null(void)
4172 {
4173     static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
4174     IDirect3DTexture8 *texture;
4175     IDirect3DSurface8 *surface;
4176     IDirect3DSurface8 *rt, *ds;
4177     D3DLOCKED_RECT locked_rect;
4178     IDirect3DDevice8 *device;
4179     D3DSURFACE_DESC desc;
4180     IDirect3D8 *d3d;
4181     ULONG refcount;
4182     HWND window;
4183     HRESULT hr;
4184
4185     if (!(d3d = pDirect3DCreate8(D3D_SDK_VERSION)))
4186     {
4187         skip("Failed to create D3D object, skipping tests.\n");
4188         return;
4189     }
4190
4191     hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4192             D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
4193     if (hr != D3D_OK)
4194     {
4195         skip("No D3DFMT_NULL support, skipping test.\n");
4196         IDirect3D8_Release(d3d);
4197         return;
4198     }
4199
4200     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4201             0, 0, 640, 480, 0, 0, 0, 0);
4202     if (!(device = create_device(d3d, window, window, TRUE)))
4203     {
4204         skip("Failed to create a D3D device, skipping tests.\n");
4205         IDirect3D8_Release(d3d);
4206         DestroyWindow(window);
4207         return;
4208     }
4209
4210     hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4211             D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
4212     ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
4213
4214     hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4215             D3DFMT_NULL, D3DFMT_D24S8);
4216     ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
4217
4218     hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
4219             D3DMULTISAMPLE_NONE, TRUE, &surface);
4220     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4221
4222     hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
4223     ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
4224
4225     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds);
4226     ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
4227
4228     hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
4229     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4230
4231     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
4232     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
4233
4234     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
4235     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4236
4237     IDirect3DSurface8_Release(rt);
4238     IDirect3DSurface8_Release(ds);
4239
4240     hr = IDirect3DSurface8_GetDesc(surface, &desc);
4241     ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4242     ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
4243     ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
4244
4245     hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4246     ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
4247     ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
4248     ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
4249
4250     hr = IDirect3DSurface8_UnlockRect(surface);
4251     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4252
4253     IDirect3DSurface8_Release(surface);
4254
4255     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
4256             D3DFMT_NULL, D3DPOOL_DEFAULT, &texture);
4257     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4258     IDirect3DTexture8_Release(texture);
4259
4260     refcount = IDirect3DDevice8_Release(device);
4261     ok(!refcount, "Device has %u references left.\n", refcount);
4262     IDirect3D8_Release(d3d);
4263     DestroyWindow(window);
4264 }
4265
4266 static void test_surface_double_unlock(void)
4267 {
4268     static const D3DPOOL pools[] =
4269     {
4270         D3DPOOL_DEFAULT,
4271         D3DPOOL_SYSTEMMEM,
4272     };
4273     IDirect3DSurface8 *surface;
4274     IDirect3DDevice8 *device;
4275     D3DLOCKED_RECT lr;
4276     IDirect3D8 *d3d;
4277     unsigned int i;
4278     ULONG refcount;
4279     HWND window;
4280     HRESULT hr;
4281
4282     if (!(d3d = pDirect3DCreate8(D3D_SDK_VERSION)))
4283     {
4284         skip("Failed to create D3D object, skipping tests.\n");
4285         return;
4286     }
4287
4288     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4289             0, 0, 640, 480, 0, 0, 0, 0);
4290     if (!(device = create_device(d3d, window, window, TRUE)))
4291     {
4292         skip("Failed to create a D3D device, skipping tests.\n");
4293         IDirect3D8_Release(d3d);
4294         DestroyWindow(window);
4295         return;
4296     }
4297
4298     for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
4299     {
4300         switch (pools[i])
4301         {
4302             case D3DPOOL_DEFAULT:
4303                 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4304                         D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
4305                 if (FAILED(hr))
4306                 {
4307                     skip("D3DFMT_X8R8G8B8 render targets not supported, skipping double unlock DEFAULT pool test.\n");
4308                     continue;
4309                 }
4310
4311                 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_X8R8G8B8,
4312                         D3DMULTISAMPLE_NONE, TRUE, &surface);
4313                 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4314                 break;
4315
4316             case D3DPOOL_SYSTEMMEM:
4317                 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64, D3DFMT_X8R8G8B8, &surface);
4318                 ok(SUCCEEDED(hr), "Failed to create image surface, hr %#x.\n", hr);
4319                 break;
4320
4321             default:
4322                 break;
4323         }
4324
4325         hr = IDirect3DSurface8_UnlockRect(surface);
4326         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
4327         hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
4328         ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
4329         hr = IDirect3DSurface8_UnlockRect(surface);
4330         ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
4331         hr = IDirect3DSurface8_UnlockRect(surface);
4332         ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
4333
4334         IDirect3DSurface8_Release(surface);
4335     }
4336
4337     refcount = IDirect3DDevice8_Release(device);
4338     ok(!refcount, "Device has %u references left.\n", refcount);
4339     IDirect3D8_Release(d3d);
4340     DestroyWindow(window);
4341 }
4342
4343 static void test_surface_lockrect_blocks(void)
4344 {
4345     static const struct
4346     {
4347         D3DFORMAT fmt;
4348         const char *name;
4349         unsigned int block_width;
4350         unsigned int block_height;
4351         BOOL broken;
4352     }
4353     formats[] =
4354     {
4355         {D3DFMT_DXT1,                 "D3DFMT_DXT1", 4, 4, FALSE},
4356         {D3DFMT_DXT2,                 "D3DFMT_DXT2", 4, 4, FALSE},
4357         {D3DFMT_DXT3,                 "D3DFMT_DXT3", 4, 4, FALSE},
4358         {D3DFMT_DXT4,                 "D3DFMT_DXT4", 4, 4, FALSE},
4359         {D3DFMT_DXT5,                 "D3DFMT_DXT5", 4, 4, FALSE},
4360         /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
4361          * which doesn't match the format spec. On newer Nvidia cards
4362          * it has the correct 4x4 block size */
4363         {MAKEFOURCC('A','T','I','2'), "ATI2N",       4, 4, TRUE},
4364         /* YUY2 and UYVY are not supported in d3d8, there is no way
4365          * to use them with this API considering their restrictions */
4366     };
4367     static const struct
4368     {
4369         D3DPOOL pool;
4370         const char *name;
4371         /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
4372          * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
4373         BOOL success;
4374     }
4375     pools[] =
4376     {
4377         {D3DPOOL_DEFAULT,       "D3DPOOL_DEFAULT",  FALSE},
4378         {D3DPOOL_SCRATCH,       "D3DPOOL_SCRATCH",  TRUE},
4379         {D3DPOOL_SYSTEMMEM,     "D3DPOOL_SYSTEMMEM",TRUE},
4380         {D3DPOOL_MANAGED,       "D3DPOOL_MANAGED",  TRUE},
4381     };
4382     IDirect3DTexture8 *texture;
4383     IDirect3DSurface8 *surface;
4384     D3DLOCKED_RECT locked_rect;
4385     IDirect3DDevice8 *device;
4386     unsigned int i, j;
4387     IDirect3D8 *d3d;
4388     ULONG refcount;
4389     HWND window;
4390     HRESULT hr;
4391     RECT rect;
4392
4393     if (!(d3d = pDirect3DCreate8(D3D_SDK_VERSION)))
4394     {
4395         skip("Failed to create D3D object, skipping tests.\n");
4396         return;
4397     }
4398
4399     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4400             0, 0, 640, 480, 0, 0, 0, 0);
4401     if (!(device = create_device(d3d, window, window, TRUE)))
4402     {
4403         skip("Failed to create a D3D device, skipping tests.\n");
4404         IDirect3D8_Release(d3d);
4405         DestroyWindow(window);
4406         return;
4407     }
4408
4409     for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
4410     {
4411         hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4412                 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
4413         if (FAILED(hr))
4414         {
4415             skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
4416             continue;
4417         }
4418
4419         for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
4420         {
4421             hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1,
4422                     pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
4423                     formats[i].fmt, pools[j].pool, &texture);
4424             ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4425             hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
4426             ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
4427             IDirect3DTexture8_Release(texture);
4428
4429             if (formats[i].block_width > 1)
4430             {
4431                 SetRect(&rect, formats[i].block_width >> 1, 0, 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 >> 1, formats[i].block_height);
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             if (formats[i].block_height > 1)
4457             {
4458                 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
4459                 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4460                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
4461                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
4462                         SUCCEEDED(hr) ? "succeeded" : "failed",
4463                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
4464                 if (SUCCEEDED(hr))
4465                 {
4466                     hr = IDirect3DSurface8_UnlockRect(surface);
4467                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4468                 }
4469
4470                 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
4471                 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4472                 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
4473                         "Partial block lock %s, expected %s, format %s, pool %s.\n",
4474                         SUCCEEDED(hr) ? "succeeded" : "failed",
4475                         pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
4476                 if (SUCCEEDED(hr))
4477                 {
4478                     hr = IDirect3DSurface8_UnlockRect(surface);
4479                     ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4480                 }
4481             }
4482
4483             SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
4484             hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
4485             ok(hr == D3D_OK, "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
4486             hr = IDirect3DSurface8_UnlockRect(surface);
4487             ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
4488
4489             IDirect3DSurface8_Release(surface);
4490         }
4491     }
4492
4493     refcount = IDirect3DDevice8_Release(device);
4494     ok(!refcount, "Device has %u references left.\n", refcount);
4495     IDirect3D8_Release(d3d);
4496     DestroyWindow(window);
4497 }
4498
4499 static void test_set_palette(void)
4500 {
4501     IDirect3DDevice8 *device;
4502     IDirect3D8 *d3d8;
4503     UINT refcount;
4504     HWND window;
4505     HRESULT hr;
4506     PALETTEENTRY pal[256];
4507     unsigned int i;
4508     D3DCAPS8 caps;
4509
4510     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4511     {
4512         skip("Failed to create d3d8 object, skipping tests.\n");
4513         return;
4514     }
4515
4516     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4517             0, 0, 640, 480, 0, 0, 0, 0);
4518     if (!(device = create_device(d3d8, window, window, TRUE)))
4519     {
4520         skip("Failed to create a D3D device, skipping tests.\n");
4521         IDirect3D8_Release(d3d8);
4522         DestroyWindow(window);
4523         return;
4524     }
4525
4526     for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
4527     {
4528         pal[i].peRed = i;
4529         pal[i].peGreen = i;
4530         pal[i].peBlue = i;
4531         pal[i].peFlags = 0xff;
4532     }
4533     hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
4534     ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
4535
4536     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4537     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4538     for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
4539     {
4540         pal[i].peRed = i;
4541         pal[i].peGreen = i;
4542         pal[i].peBlue = i;
4543         pal[i].peFlags = i;
4544     }
4545     if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
4546     {
4547         hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
4548         ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
4549     }
4550     else
4551     {
4552         hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
4553         ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
4554     }
4555
4556     refcount = IDirect3DDevice8_Release(device);
4557     ok(!refcount, "Device has %u references left.\n", refcount);
4558     IDirect3D8_Release(d3d8);
4559     DestroyWindow(window);
4560 }
4561
4562 static void test_swvp_buffer(void)
4563 {
4564     IDirect3DDevice8 *device;
4565     IDirect3D8 *d3d8;
4566     UINT refcount;
4567     HWND window;
4568     HRESULT hr;
4569     unsigned int i;
4570     IDirect3DVertexBuffer8 *buffer;
4571     static const unsigned int bufsize = 1024;
4572     D3DVERTEXBUFFER_DESC desc;
4573     D3DPRESENT_PARAMETERS present_parameters = {0};
4574     struct
4575     {
4576         float x, y, z;
4577     } *ptr, *ptr2;
4578
4579     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4580     {
4581         skip("Failed to create d3d8 object, skipping tests.\n");
4582         return;
4583     }
4584
4585     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4586             0, 0, 640, 480, 0, 0, 0, 0);
4587
4588     present_parameters.Windowed = TRUE;
4589     present_parameters.hDeviceWindow = window;
4590     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
4591     present_parameters.BackBufferWidth = screen_width;
4592     present_parameters.BackBufferHeight = screen_height;
4593     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
4594     present_parameters.EnableAutoDepthStencil = FALSE;
4595     if (FAILED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
4596             D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
4597     {
4598         skip("Failed to create a D3D device, skipping tests.\n");
4599         IDirect3D8_Release(d3d8);
4600         DestroyWindow(window);
4601         return;
4602     }
4603
4604     hr = IDirect3DDevice8_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
4605             D3DPOOL_DEFAULT, &buffer);
4606     ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
4607     hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
4608     ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
4609     ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
4610     ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
4611             "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
4612
4613     hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
4614     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
4615     for (i = 0; i < bufsize; i++)
4616     {
4617         ptr[i].x = i * 1.0f;
4618         ptr[i].y = i * 2.0f;
4619         ptr[i].z = i * 3.0f;
4620     }
4621     hr = IDirect3DVertexBuffer8_Unlock(buffer);
4622     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
4623
4624     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
4625     ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
4626     hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
4627     ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
4628     hr = IDirect3DDevice8_BeginScene(device);
4629     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4630     hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
4631     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4632     hr = IDirect3DDevice8_EndScene(device);
4633     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4634
4635     hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
4636     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
4637     ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
4638     for (i = 0; i < bufsize; i++)
4639     {
4640         if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
4641         {
4642             ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
4643                     ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
4644             break;
4645         }
4646     }
4647     hr = IDirect3DVertexBuffer8_Unlock(buffer);
4648     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
4649
4650     IDirect3DVertexBuffer8_Release(buffer);
4651     refcount = IDirect3DDevice8_Release(device);
4652     ok(!refcount, "Device has %u references left.\n", refcount);
4653     IDirect3D8_Release(d3d8);
4654     DestroyWindow(window);
4655 }
4656
4657 static void test_rtpatch(void)
4658 {
4659     IDirect3DDevice8 *device;
4660     IDirect3D8 *d3d8;
4661     UINT refcount;
4662     HWND window;
4663     HRESULT hr;
4664     IDirect3DVertexBuffer8 *buffer;
4665     DWORD shader;
4666     static const unsigned int bufsize = 16;
4667     struct
4668     {
4669         float x, y, z;
4670     } *data;
4671     D3DRECTPATCH_INFO patch;
4672     static const float num_segs[] = {1.0f, 1.0f, 1.0f, 1.0f};
4673     UINT handle = 0x1234;
4674     D3DCAPS8 caps;
4675
4676     /* Position input, this generates tesselated positions, but do not generate normals
4677      * or texture coordinates. The d3d documentation isn't clear on how to do this */
4678     static const DWORD decl[] =
4679     {
4680         D3DVSD_STREAM(0),
4681         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
4682         D3DVSD_END()
4683     };
4684
4685     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4686     {
4687         skip("Failed to create d3d8 object, skipping tests.\n");
4688         return;
4689     }
4690
4691     window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4692             0, 0, 640, 480, 0, 0, 0, 0);
4693     if (!(device = create_device(d3d8, window, window, TRUE)))
4694     {
4695         skip("Failed to create a D3D device, skipping tests.\n");
4696         IDirect3D8_Release(d3d8);
4697         DestroyWindow(window);
4698         return;
4699     }
4700
4701     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4702     ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4703     if (caps.DevCaps & D3DDEVCAPS_RTPATCHES)
4704     {
4705         /* The draw methods return the same values, but the patch handle support
4706          * is different on the refrast, which is the only d3d implementation
4707          * known to support tri/rect patches */
4708         skip("Device supports patches, skipping unsupported patch test\n");
4709         IDirect3DDevice8_Release(device);
4710         IDirect3D8_Release(d3d8);
4711         DestroyWindow(window);
4712         return;
4713     }
4714
4715     hr = IDirect3DDevice8_CreateVertexShader(device, decl, NULL, &shader, 0);
4716     ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr);
4717     hr = IDirect3DDevice8_SetVertexShader(device, shader);
4718     ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
4719
4720     hr = IDirect3DDevice8_CreateVertexBuffer(device, bufsize * sizeof(*data), D3DUSAGE_RTPATCHES, 0,
4721             D3DPOOL_MANAGED, &buffer);
4722     ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
4723     hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, (BYTE **)&data, 0);
4724     ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
4725     memset(data, 0, bufsize * sizeof(*data));
4726     hr = IDirect3DVertexBuffer8_Unlock(buffer);
4727     ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
4728
4729     hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*data));
4730     ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
4731     hr = IDirect3DDevice8_BeginScene(device);
4732     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4733
4734     patch.StartVertexOffsetWidth = 0;
4735     patch.StartVertexOffsetHeight = 0;
4736     patch.Width = 4;
4737     patch.Height = 4;
4738     patch.Stride = 4;
4739     patch.Basis = D3DBASIS_BEZIER;
4740     patch.Order = D3DORDER_CUBIC;
4741     hr = IDirect3DDevice8_DrawRectPatch(device, handle, num_segs, NULL);
4742     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
4743     hr = IDirect3DDevice8_DrawRectPatch(device, handle, num_segs, &patch);
4744     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
4745     hr = IDirect3DDevice8_DrawRectPatch(device, handle, num_segs, NULL);
4746     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
4747     hr = IDirect3DDevice8_DrawRectPatch(device, 0, num_segs, NULL);
4748     ok(SUCCEEDED(hr), "Failed to draw rect patch, hr %#x.\n", hr);
4749
4750     hr = IDirect3DDevice8_EndScene(device);
4751     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4752
4753     hr = IDirect3DDevice8_DrawRectPatch(device, 0, num_segs, &patch);
4754     ok(SUCCEEDED(hr), "Failed to draw rect patch outside scene, hr %#x.\n", hr);
4755
4756     hr = IDirect3DDevice8_DeletePatch(device, handle);
4757     ok(hr == D3DERR_INVALIDCALL, "DeletePatch returned hr %#x.\n", hr);
4758     hr = IDirect3DDevice8_DeletePatch(device, 0);
4759     ok(hr == D3DERR_INVALIDCALL, "DeletePatch returned hr %#x.\n", hr);
4760     hr = IDirect3DDevice8_DeletePatch(device, 0x1235);
4761     ok(hr == D3DERR_INVALIDCALL, "DeletePatch returned hr %#x.\n", hr);
4762
4763     IDirect3DDevice8_DeleteVertexShader(device, shader);
4764     IDirect3DVertexBuffer8_Release(buffer);
4765     refcount = IDirect3DDevice8_Release(device);
4766     ok(!refcount, "Device has %u references left.\n", refcount);
4767     IDirect3D8_Release(d3d8);
4768     DestroyWindow(window);
4769 }
4770
4771 static void test_npot_textures(void)
4772 {
4773     IDirect3DDevice8 *device = NULL;
4774     IDirect3D8 *d3d8;
4775     ULONG refcount;
4776     HWND window = NULL;
4777     HRESULT hr;
4778     D3DCAPS8 caps;
4779     IDirect3DTexture8 *texture;
4780     IDirect3DCubeTexture8 *cube_texture;
4781     IDirect3DVolumeTexture8 *volume_texture;
4782     struct
4783     {
4784         D3DPOOL pool;
4785         const char *pool_name;
4786         HRESULT hr;
4787     }
4788     pools[] =
4789     {
4790         { D3DPOOL_DEFAULT,    "D3DPOOL_DEFAULT",    D3DERR_INVALIDCALL },
4791         { D3DPOOL_MANAGED,    "D3DPOOL_MANAGED",    D3DERR_INVALIDCALL },
4792         { D3DPOOL_SYSTEMMEM,  "D3DPOOL_SYSTEMMEM",  D3DERR_INVALIDCALL },
4793         { D3DPOOL_SCRATCH,    "D3DPOOL_SCRATCH",    D3D_OK             },
4794     };
4795     unsigned int i, levels;
4796     BOOL tex_pow2, cube_pow2, vol_pow2;
4797
4798     if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
4799     {
4800         skip("Failed to create IDirect3D8 object, skipping tests.\n");
4801         return;
4802     }
4803
4804     window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
4805             0, 0, 640, 480, 0, 0, 0, 0);
4806     if (!(device = create_device(d3d8, window, window, TRUE)))
4807     {
4808         skip("Failed to create a D3D device, skipping tests.\n");
4809         goto done;
4810     }
4811
4812     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4813     ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
4814     tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
4815     cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
4816     vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
4817     ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
4818     ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
4819
4820     for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
4821     {
4822         for (levels = 0; levels <= 2; levels++)
4823         {
4824             HRESULT expected;
4825
4826             hr = IDirect3DDevice8_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
4827                     pools[i].pool, &texture);
4828             if (!tex_pow2)
4829             {
4830                 expected = D3D_OK;
4831             }
4832             else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
4833             {
4834                 if (levels == 1)
4835                     expected = D3D_OK;
4836                 else
4837                     expected = pools[i].hr;
4838             }
4839             else
4840             {
4841                 expected = pools[i].hr;
4842             }
4843             ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
4844                     pools[i].pool_name, levels, hr, expected);
4845
4846             if (SUCCEEDED(hr))
4847                 IDirect3DTexture8_Release(texture);
4848         }
4849
4850         hr = IDirect3DDevice8_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8,
4851                 pools[i].pool, &cube_texture);
4852         if (tex_pow2)
4853         {
4854             ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
4855                     pools[i].pool_name, hr, pools[i].hr);
4856         }
4857         else
4858         {
4859             ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
4860                     pools[i].pool_name, hr, D3D_OK);
4861         }
4862
4863         if (SUCCEEDED(hr))
4864             IDirect3DCubeTexture8_Release(cube_texture);
4865
4866         hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8,
4867                 pools[i].pool, &volume_texture);
4868         if (tex_pow2)
4869         {
4870             ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
4871                     pools[i].pool_name, hr, pools[i].hr);
4872         }
4873         else
4874         {
4875             ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
4876                     pools[i].pool_name, hr, D3D_OK);
4877         }
4878
4879         if (SUCCEEDED(hr))
4880             IDirect3DVolumeTexture8_Release(volume_texture);
4881     }
4882
4883 done:
4884     if (device)
4885     {
4886         refcount = IDirect3DDevice8_Release(device);
4887         ok(!refcount, "Device has %u references left.\n", refcount);
4888     }
4889     IDirect3D8_Release(d3d8);
4890     DestroyWindow(window);
4891
4892 }
4893
4894 START_TEST(device)
4895 {
4896     HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
4897     WNDCLASS wc = {0};
4898     if (!d3d8_handle)
4899     {
4900         skip("Could not load d3d8.dll\n");
4901         return;
4902     }
4903
4904     wc.lpfnWndProc = DefWindowProc;
4905     wc.lpszClassName = "d3d8_test_wc";
4906     RegisterClass(&wc);
4907
4908     ValidateVertexShader = (void *)GetProcAddress(d3d8_handle, "ValidateVertexShader");
4909     ValidatePixelShader = (void *)GetProcAddress(d3d8_handle, "ValidatePixelShader");
4910     pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
4911     ok(pDirect3DCreate8 != NULL, "Failed to get address of Direct3DCreate8\n");
4912     if (pDirect3DCreate8)
4913     {
4914         IDirect3D8 *d3d8;
4915         d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
4916         if(!d3d8)
4917         {
4918             skip("could not create D3D8\n");
4919             return;
4920         }
4921         IDirect3D8_Release(d3d8);
4922
4923         screen_width = GetSystemMetrics(SM_CXSCREEN);
4924         screen_height = GetSystemMetrics(SM_CYSCREEN);
4925
4926         test_fpu_setup();
4927         test_display_modes();
4928         test_shader_versions();
4929         test_swapchain();
4930         test_refcount();
4931         test_mipmap_levels();
4932         test_cursor();
4933         test_cursor_pos();
4934         test_states();
4935         test_reset();
4936         test_scene();
4937         test_shader();
4938         test_limits();
4939         test_lights();
4940         test_ApplyStateBlock();
4941         test_render_zero_triangles();
4942         test_depth_stencil_reset();
4943         test_wndproc();
4944         test_wndproc_windowed();
4945         test_depth_stencil_size();
4946         test_window_style();
4947         test_wrong_shader();
4948         test_mode_change();
4949         test_device_window_reset();
4950         test_reset_resources();
4951         depth_blit_test();
4952         test_set_rt_vp_scissor();
4953         test_validate_vs();
4954         test_validate_ps();
4955         test_volume_get_container();
4956         test_vb_lock_flags();
4957         test_texture_stage_states();
4958         test_cube_textures();
4959         test_image_surface_pool();
4960         test_surface_get_container();
4961         test_lockrect_invalid();
4962         test_private_data();
4963         test_surface_dimensions();
4964         test_surface_format_null();
4965         test_surface_double_unlock();
4966         test_surface_lockrect_blocks();
4967         test_set_palette();
4968         test_swvp_buffer();
4969         test_rtpatch();
4970         test_npot_textures();
4971     }
4972     UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));
4973 }