configure: Changes from running autconf after previous patch.
[wine/hacks.git] / dlls / d3d8 / tests / device.c
blobbaf78e1156d471173c6918b2befd4923a3d1ee9e
1 /*
2 * Copyright (C) 2006 Vitaliy Margolen
3 * Copyright (C) 2006 Chris Robinson
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
21 #include <initguid.h>
22 #include <d3d8.h>
23 #include "wine/test.h"
25 static IDirect3D8 *(WINAPI *pDirect3DCreate8)(UINT);
27 static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
29 static const DWORD simple_vs[] = {0xFFFE0101, /* vs_1_1 */
30 0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0 */
31 0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1 */
32 0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2 */
33 0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3 */
34 0x0000FFFF}; /* END */
35 static const DWORD simple_ps[] = {0xFFFF0101, /* ps_1_1 */
36 0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
37 0x00000042, 0xB00F0000, /* tex t0 */
38 0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000, /* dp3 r0, c1, c0 */
39 0x00000005, 0x800F0000, 0x90E40000, 0x80E40000, /* mul r0, v0, r0 */
40 0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000, /* mul r0, t0, r0 */
41 0x0000FFFF}; /* END */
43 static int get_refcount(IUnknown *object)
45 IUnknown_AddRef( object );
46 return IUnknown_Release( object );
49 /* try to make sure pending X events have been processed before continuing */
50 static void flush_events(void)
52 MSG msg;
53 int diff = 200;
54 int min_timeout = 100;
55 DWORD time = GetTickCount() + diff;
57 while (diff > 0)
59 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
60 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
61 diff = time - GetTickCount();
65 static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND device_window, HWND focus_window, BOOL windowed)
67 D3DPRESENT_PARAMETERS present_parameters = {0};
68 IDirect3DDevice8 *device;
70 present_parameters.Windowed = windowed;
71 present_parameters.hDeviceWindow = device_window;
72 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
73 present_parameters.BackBufferWidth = 640;
74 present_parameters.BackBufferHeight = 480;
75 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
76 present_parameters.EnableAutoDepthStencil = TRUE;
77 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
79 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
80 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
82 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
83 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
84 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
86 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
87 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
89 return NULL;
92 #define CHECK_CALL(r,c,d,rc) \
93 if (SUCCEEDED(r)) {\
94 int tmp1 = get_refcount( (IUnknown *)d ); \
95 int rc_new = rc; \
96 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
97 } else {\
98 trace("%s failed: %#08x\n", c, r); \
101 #define CHECK_RELEASE(obj,d,rc) \
102 if (obj) { \
103 int tmp1, rc_new = rc; \
104 IUnknown_Release( obj ); \
105 tmp1 = get_refcount( (IUnknown *)d ); \
106 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
109 #define CHECK_REFCOUNT(obj,rc) \
111 int rc_new = rc; \
112 int count = get_refcount( (IUnknown *)obj ); \
113 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
116 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
118 int rc_new = rc; \
119 int count = IUnknown_Release( (IUnknown *)obj ); \
120 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
123 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
125 int rc_new = rc; \
126 int count = IUnknown_AddRef( (IUnknown *)obj ); \
127 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
130 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
132 void *container_ptr = (void *)0x1337c0d3; \
133 hr = IDirect3DSurface8_GetContainer(obj, &iid, &container_ptr); \
134 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#08x, container_ptr %p. " \
135 "Expected hr %#08x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
136 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
139 static void check_mipmap_levels(IDirect3DDevice8 *device, UINT width, UINT height, UINT count)
141 IDirect3DBaseTexture8* texture = NULL;
142 HRESULT hr = IDirect3DDevice8_CreateTexture( device, width, height, 0, 0,
143 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture8**) &texture );
145 if (SUCCEEDED(hr)) {
146 DWORD levels = IDirect3DBaseTexture8_GetLevelCount(texture);
147 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
148 } else
149 trace("CreateTexture failed: %#08x\n", hr);
151 if (texture) IUnknown_Release( texture );
154 static void test_mipmap_levels(void)
157 HRESULT hr;
158 HWND hwnd = NULL;
160 IDirect3D8 *pD3d = NULL;
161 IDirect3DDevice8 *pDevice = NULL;
162 D3DPRESENT_PARAMETERS d3dpp;
163 D3DDISPLAYMODE d3ddm;
165 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
166 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
167 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
168 ok(hwnd != NULL, "Failed to create window\n");
169 if (!pD3d || !hwnd) goto cleanup;
171 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
172 ZeroMemory( &d3dpp, sizeof(d3dpp) );
173 d3dpp.Windowed = TRUE;
174 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
175 d3dpp.BackBufferFormat = d3ddm.Format;
177 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
178 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
179 if(FAILED(hr))
181 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
182 goto cleanup;
185 check_mipmap_levels(pDevice, 32, 32, 6);
186 check_mipmap_levels(pDevice, 256, 1, 9);
187 check_mipmap_levels(pDevice, 1, 256, 9);
188 check_mipmap_levels(pDevice, 1, 1, 1);
190 cleanup:
191 if (pDevice)
193 UINT refcount = IUnknown_Release( pDevice );
194 ok(!refcount, "Device has %u references left.\n", refcount);
196 if (pD3d) IUnknown_Release( pD3d );
197 DestroyWindow( hwnd );
200 static void test_swapchain(void)
202 HRESULT hr;
203 HWND hwnd = NULL;
204 IDirect3D8 *pD3d = NULL;
205 IDirect3DDevice8 *pDevice = NULL;
206 IDirect3DSwapChain8 *swapchain1 = NULL;
207 IDirect3DSwapChain8 *swapchain2 = NULL;
208 IDirect3DSwapChain8 *swapchain3 = NULL;
209 IDirect3DSurface8 *backbuffer = NULL;
210 D3DPRESENT_PARAMETERS d3dpp;
211 D3DDISPLAYMODE d3ddm;
213 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
214 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
215 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
216 ok(hwnd != NULL, "Failed to create window\n");
217 if (!pD3d || !hwnd) goto cleanup;
219 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
220 ZeroMemory( &d3dpp, sizeof(d3dpp) );
221 d3dpp.Windowed = TRUE;
222 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
223 d3dpp.BackBufferFormat = d3ddm.Format;
224 d3dpp.BackBufferCount = 0;
226 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
227 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
228 if(FAILED(hr))
230 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
231 goto cleanup;
234 /* Check if the back buffer count was modified */
235 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
237 /* Create a bunch of swapchains */
238 d3dpp.BackBufferCount = 0;
239 hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
240 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
241 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
243 d3dpp.BackBufferCount = 1;
244 hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
245 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
247 d3dpp.BackBufferCount = 2;
248 hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
249 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
250 if(SUCCEEDED(hr)) {
251 /* Swapchain 3, created with backbuffercount 2 */
252 backbuffer = (void *) 0xdeadbeef;
253 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
254 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%#08x)\n", hr);
255 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
256 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
258 backbuffer = (void *) 0xdeadbeef;
259 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
260 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%#08x)\n", hr);
261 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
262 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
264 backbuffer = (void *) 0xdeadbeef;
265 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
266 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
267 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
268 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
270 backbuffer = (void *) 0xdeadbeef;
271 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
272 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
273 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
274 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
277 /* Check the back buffers of the swapchains */
278 /* Swapchain 1, created with backbuffercount 0 */
279 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
280 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
281 ok(backbuffer != NULL, "The back buffer is NULL (%#08x)\n", hr);
282 if(backbuffer) IDirect3DSurface8_Release(backbuffer);
284 backbuffer = (void *) 0xdeadbeef;
285 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
286 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
287 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
288 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
290 /* Swapchain 2 - created with backbuffercount 1 */
291 backbuffer = (void *) 0xdeadbeef;
292 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
293 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
294 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
295 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
297 backbuffer = (void *) 0xdeadbeef;
298 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
299 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
300 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
301 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
303 backbuffer = (void *) 0xdeadbeef;
304 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
305 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
306 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
307 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
309 cleanup:
310 if(swapchain1) IDirect3DSwapChain8_Release(swapchain1);
311 if(swapchain2) IDirect3DSwapChain8_Release(swapchain2);
312 if(swapchain3) IDirect3DSwapChain8_Release(swapchain3);
313 if (pDevice)
315 UINT refcount = IDirect3DDevice8_Release(pDevice);
316 ok(!refcount, "Device has %u references left.\n", refcount);
318 if (pD3d) IDirect3D8_Release(pD3d);
319 DestroyWindow( hwnd );
322 static void test_refcount(void)
324 HRESULT hr;
325 HWND hwnd = NULL;
326 IDirect3D8 *pD3d = NULL;
327 IDirect3DDevice8 *pDevice = NULL;
328 IDirect3DVertexBuffer8 *pVertexBuffer = NULL;
329 IDirect3DIndexBuffer8 *pIndexBuffer = NULL;
330 DWORD dVertexShader = -1;
331 DWORD dPixelShader = -1;
332 IDirect3DCubeTexture8 *pCubeTexture = NULL;
333 IDirect3DTexture8 *pTexture = NULL;
334 IDirect3DVolumeTexture8 *pVolumeTexture = NULL;
335 IDirect3DVolume8 *pVolumeLevel = NULL;
336 IDirect3DSurface8 *pStencilSurface = NULL;
337 IDirect3DSurface8 *pImageSurface = NULL;
338 IDirect3DSurface8 *pRenderTarget = NULL;
339 IDirect3DSurface8 *pRenderTarget2 = NULL;
340 IDirect3DSurface8 *pRenderTarget3 = NULL;
341 IDirect3DSurface8 *pTextureLevel = NULL;
342 IDirect3DSurface8 *pBackBuffer = NULL;
343 DWORD dStateBlock = -1;
344 IDirect3DSwapChain8 *pSwapChain = NULL;
345 D3DCAPS8 caps;
347 D3DPRESENT_PARAMETERS d3dpp;
348 D3DDISPLAYMODE d3ddm;
349 int refcount = 0, tmp;
351 DWORD decl[] =
353 D3DVSD_STREAM(0),
354 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
355 D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
356 D3DVSD_END()
359 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
360 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
361 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
362 ok(hwnd != NULL, "Failed to create window\n");
363 if (!pD3d || !hwnd) goto cleanup;
365 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
366 ZeroMemory( &d3dpp, sizeof(d3dpp) );
367 d3dpp.Windowed = TRUE;
368 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
369 d3dpp.BackBufferFormat = d3ddm.Format;
370 d3dpp.EnableAutoDepthStencil = TRUE;
371 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
373 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
374 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
375 if(FAILED(hr))
377 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
378 goto cleanup;
380 IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
382 refcount = get_refcount( (IUnknown *)pDevice );
383 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
386 * Check refcount of implicit surfaces. Findings:
387 * - the container is the device
388 * - they hold a reference to the device
389 * - they are created with a refcount of 0 (Get/Release returns original refcount)
390 * - they are not freed if refcount reaches 0.
391 * - the refcount is not forwarded to the container.
393 hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
394 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
395 if(pRenderTarget)
397 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DDevice8, pDevice);
398 CHECK_REFCOUNT( pRenderTarget, 1);
400 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
401 CHECK_REFCOUNT(pDevice, refcount);
402 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
403 CHECK_REFCOUNT(pDevice, refcount);
405 hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
406 CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
407 CHECK_REFCOUNT( pRenderTarget, 2);
408 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
409 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
410 CHECK_REFCOUNT( pDevice, --refcount);
412 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
413 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
414 CHECK_REFCOUNT(pDevice, ++refcount);
415 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
416 CHECK_REFCOUNT(pDevice, --refcount);
419 /* Render target and back buffer are identical. */
420 hr = IDirect3DDevice8_GetBackBuffer(pDevice, 0, 0, &pBackBuffer);
421 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
422 if(pBackBuffer)
424 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
425 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
426 pRenderTarget, pBackBuffer);
427 pBackBuffer = NULL;
429 CHECK_REFCOUNT( pDevice, --refcount);
431 hr = IDirect3DDevice8_GetDepthStencilSurface(pDevice, &pStencilSurface);
432 CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
433 if(pStencilSurface)
435 CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice8, pDevice);
436 CHECK_REFCOUNT( pStencilSurface, 1);
438 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
439 CHECK_REFCOUNT(pDevice, refcount);
440 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
441 CHECK_REFCOUNT(pDevice, refcount);
443 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
444 CHECK_REFCOUNT( pDevice, --refcount);
446 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
447 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
448 CHECK_REFCOUNT(pDevice, ++refcount);
449 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
450 CHECK_REFCOUNT(pDevice, --refcount);
451 pStencilSurface = NULL;
454 /* Buffers */
455 hr = IDirect3DDevice8_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer );
456 CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
457 if(pIndexBuffer)
459 tmp = get_refcount( (IUnknown *)pIndexBuffer );
461 hr = IDirect3DDevice8_SetIndices(pDevice, pIndexBuffer, 0);
462 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
463 hr = IDirect3DDevice8_SetIndices(pDevice, NULL, 0);
464 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
467 hr = IDirect3DDevice8_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer );
468 CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
469 if(pVertexBuffer)
471 IDirect3DVertexBuffer8 *pVBuf = (void*)~0;
472 UINT stride = ~0;
474 tmp = get_refcount( (IUnknown *)pVertexBuffer );
476 hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, pVertexBuffer, 3 * sizeof(float));
477 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
478 hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, NULL, 0);
479 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
481 hr = IDirect3DDevice8_GetStreamSource(pDevice, 0, &pVBuf, &stride);
482 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
483 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
484 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
487 /* Shaders */
488 hr = IDirect3DDevice8_CreateVertexShader( pDevice, decl, simple_vs, &dVertexShader, 0 );
489 CHECK_CALL( hr, "CreateVertexShader", pDevice, refcount );
490 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
492 hr = IDirect3DDevice8_CreatePixelShader( pDevice, simple_ps, &dPixelShader );
493 CHECK_CALL( hr, "CreatePixelShader", pDevice, refcount );
495 /* Textures */
496 hr = IDirect3DDevice8_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture );
497 CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
498 if (pTexture)
500 tmp = get_refcount( (IUnknown *)pTexture );
502 /* SetTexture should not increase refcounts */
503 hr = IDirect3DDevice8_SetTexture(pDevice, 0, (IDirect3DBaseTexture8 *) pTexture);
504 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
505 hr = IDirect3DDevice8_SetTexture(pDevice, 0, NULL);
506 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
508 /* This should not increment device refcount */
509 hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
510 CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
511 /* But should increment texture's refcount */
512 CHECK_REFCOUNT( pTexture, tmp+1 );
513 /* Because the texture and surface refcount are identical */
514 if (pTextureLevel)
516 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
517 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
518 CHECK_REFCOUNT ( pTexture , tmp+2 );
519 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
520 CHECK_REFCOUNT ( pTexture , tmp+1 );
521 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
522 CHECK_REFCOUNT ( pTextureLevel, tmp );
525 if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
527 hr = IDirect3DDevice8_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture );
528 CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
530 else
532 skip("Cube textures not supported\n");
534 if(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
536 hr = IDirect3DDevice8_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture );
537 CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
539 else
541 skip("Volume textures not supported\n");
544 if (pVolumeTexture)
546 tmp = get_refcount( (IUnknown *)pVolumeTexture );
548 /* This should not increment device refcount */
549 hr = IDirect3DVolumeTexture8_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
550 CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
551 /* But should increment volume texture's refcount */
552 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
553 /* Because the volume texture and volume refcount are identical */
554 if (pVolumeLevel)
556 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
557 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
558 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
559 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
560 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
561 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
562 CHECK_REFCOUNT ( pVolumeLevel , tmp );
565 /* Surfaces */
566 hr = IDirect3DDevice8_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D16, D3DMULTISAMPLE_NONE, &pStencilSurface );
567 CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
568 CHECK_REFCOUNT( pStencilSurface, 1);
569 hr = IDirect3DDevice8_CreateImageSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, &pImageSurface );
570 CHECK_CALL( hr, "CreateImageSurface", pDevice, ++refcount );
571 CHECK_REFCOUNT( pImageSurface, 1);
572 hr = IDirect3DDevice8_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget3 );
573 CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
574 CHECK_REFCOUNT( pRenderTarget3, 1);
575 /* Misc */
576 hr = IDirect3DDevice8_CreateStateBlock( pDevice, D3DSBT_ALL, &dStateBlock );
577 CHECK_CALL( hr, "CreateStateBlock", pDevice, refcount );
578 hr = IDirect3DDevice8_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
579 CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
580 if(pSwapChain)
582 /* check implicit back buffer */
583 hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
584 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
585 CHECK_REFCOUNT( pSwapChain, 1);
586 if(pBackBuffer)
588 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DDevice8, pDevice);
589 CHECK_REFCOUNT( pBackBuffer, 1);
590 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
591 CHECK_REFCOUNT( pDevice, --refcount);
593 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
594 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
595 CHECK_REFCOUNT(pDevice, ++refcount);
596 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
597 CHECK_REFCOUNT(pDevice, --refcount);
598 pBackBuffer = NULL;
600 CHECK_REFCOUNT( pSwapChain, 1);
603 if(pVertexBuffer)
605 BYTE *data;
606 /* Vertex buffers can be locked multiple times */
607 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
608 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
609 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
610 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
611 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
612 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
613 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
614 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
617 /* The implicit render target is not freed if refcount reaches 0.
618 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
619 hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget2);
620 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
621 if(pRenderTarget2)
623 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
624 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
625 pRenderTarget, pRenderTarget2);
626 CHECK_REFCOUNT( pDevice, --refcount);
627 pRenderTarget2 = NULL;
629 pRenderTarget = NULL;
631 cleanup:
632 CHECK_RELEASE(pDevice, pDevice, --refcount);
634 /* Buffers */
635 CHECK_RELEASE(pVertexBuffer, pDevice, --refcount);
636 CHECK_RELEASE(pIndexBuffer, pDevice, --refcount);
637 /* Shaders */
638 if (dVertexShader != ~0U) IDirect3DDevice8_DeleteVertexShader( pDevice, dVertexShader );
639 if (dPixelShader != ~0U) IDirect3DDevice8_DeletePixelShader( pDevice, dPixelShader );
640 /* Textures */
641 CHECK_RELEASE(pTexture, pDevice, --refcount);
642 CHECK_RELEASE(pCubeTexture, pDevice, --refcount);
643 CHECK_RELEASE(pVolumeTexture, pDevice, --refcount);
644 /* Surfaces */
645 CHECK_RELEASE(pStencilSurface, pDevice, --refcount);
646 CHECK_RELEASE(pImageSurface, pDevice, --refcount);
647 CHECK_RELEASE(pRenderTarget3, pDevice, --refcount);
648 /* Misc */
649 if (dStateBlock != ~0U) IDirect3DDevice8_DeleteStateBlock( pDevice, dStateBlock );
650 /* This will destroy device - cannot check the refcount here */
651 if (pSwapChain) CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
653 if (pD3d) CHECK_RELEASE_REFCOUNT( pD3d, 0);
655 DestroyWindow( hwnd );
658 static void test_cursor(void)
660 HRESULT hr;
661 HWND hwnd = NULL;
662 IDirect3D8 *pD3d = NULL;
663 IDirect3DDevice8 *pDevice = NULL;
664 D3DPRESENT_PARAMETERS d3dpp;
665 D3DDISPLAYMODE d3ddm;
666 CURSORINFO info;
667 IDirect3DSurface8 *cursor = NULL;
668 HCURSOR cur;
669 HMODULE user32_handle = GetModuleHandleA("user32.dll");
671 pGetCursorInfo = (void *)GetProcAddress(user32_handle, "GetCursorInfo");
672 if (!pGetCursorInfo)
674 win_skip("GetCursorInfo is not available\n");
675 return;
678 memset(&info, 0, sizeof(info));
679 info.cbSize = sizeof(info);
680 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
681 cur = info.hCursor;
683 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
684 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
685 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
686 ok(hwnd != NULL, "Failed to create window\n");
687 if (!pD3d || !hwnd) goto cleanup;
689 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
690 ZeroMemory( &d3dpp, sizeof(d3dpp) );
691 d3dpp.Windowed = TRUE;
692 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
693 d3dpp.BackBufferFormat = d3ddm.Format;
695 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
696 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
697 if(FAILED(hr))
699 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
700 goto cleanup;
703 IDirect3DDevice8_CreateImageSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, &cursor);
704 ok(cursor != NULL, "IDirect3DDevice8_CreateOffscreenPlainSurface failed with %#08x\n", hr);
706 /* Initially hidden */
707 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
708 ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
710 /* Not enabled without a surface*/
711 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
712 ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
714 /* Fails */
715 hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, NULL);
716 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
718 hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, cursor);
719 ok(hr == D3D_OK, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
721 IDirect3DSurface8_Release(cursor);
723 memset(&info, 0, sizeof(info));
724 info.cbSize = sizeof(info);
725 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
726 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
727 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
729 /* Still hidden */
730 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
731 ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
733 /* Enabled now*/
734 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
735 ok(hr == TRUE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
737 /* GDI cursor unchanged */
738 memset(&info, 0, sizeof(info));
739 info.cbSize = sizeof(info);
740 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
741 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
742 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
744 cleanup:
745 if (pDevice)
747 UINT refcount = IDirect3DDevice8_Release(pDevice);
748 ok(!refcount, "Device has %u references left.\n", refcount);
750 if (pD3d) IDirect3D8_Release(pD3d);
753 static void test_states(void)
755 HRESULT hr;
756 HWND hwnd = NULL;
757 IDirect3D8 *pD3d = NULL;
758 IDirect3DDevice8 *pDevice = NULL;
759 D3DPRESENT_PARAMETERS d3dpp;
760 D3DDISPLAYMODE d3ddm;
762 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
763 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
764 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
765 ok(hwnd != NULL, "Failed to create window\n");
766 if (!pD3d || !hwnd) goto cleanup;
768 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
769 ZeroMemory( &d3dpp, sizeof(d3dpp) );
770 d3dpp.Windowed = TRUE;
771 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
772 d3dpp.BackBufferWidth = 640;
773 d3dpp.BackBufferHeight = 480;
774 d3dpp.BackBufferFormat = d3ddm.Format;
776 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
777 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
778 if(FAILED(hr))
780 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
781 goto cleanup;
784 hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, TRUE);
785 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, TRUE) returned %#08x\n", hr);
786 hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, FALSE);
787 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, FALSE) returned %#08x\n", hr);
789 cleanup:
790 if (pDevice)
792 UINT refcount = IDirect3DDevice8_Release(pDevice);
793 ok(!refcount, "Device has %u references left.\n", refcount);
795 if (pD3d) IDirect3D8_Release(pD3d);
798 static void test_shader_versions(void)
800 HRESULT hr;
801 IDirect3D8 *pD3d = NULL;
802 D3DCAPS8 d3dcaps;
804 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
805 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
806 if (pD3d != NULL) {
807 hr = IDirect3D8_GetDeviceCaps(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);
808 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to get D3D8 caps (%#08x)\n", hr);
809 if (SUCCEEDED(hr)) {
810 ok(d3dcaps.VertexShaderVersion <= D3DVS_VERSION(1,1), "Unexpected VertexShaderVersion (%#x > %#x)\n", d3dcaps.VertexShaderVersion, D3DVS_VERSION(1,1));
811 ok(d3dcaps.PixelShaderVersion <= D3DPS_VERSION(1,4), "Unexpected PixelShaderVersion (%#x > %#x)\n", d3dcaps.PixelShaderVersion, D3DPS_VERSION(1,4));
812 } else {
813 skip("No Direct3D support\n");
815 IDirect3D8_Release(pD3d);
820 /* Test adapter display modes */
821 static void test_display_modes(void)
823 UINT max_modes, i;
824 D3DDISPLAYMODE dmode;
825 HRESULT res;
826 IDirect3D8 *pD3d;
828 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
829 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
830 if(!pD3d) return;
832 max_modes = IDirect3D8_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT);
833 ok(max_modes > 0 ||
834 broken(max_modes == 0), /* VMware */
835 "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
837 for(i=0; i<max_modes;i++) {
838 res = IDirect3D8_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, i, &dmode);
839 ok(res==D3D_OK, "EnumAdapterModes returned %#08x for mode %u!\n", res, i);
840 if(res != D3D_OK)
841 continue;
843 ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
844 "Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
847 IDirect3D8_Release(pD3d);
850 static void test_scene(void)
852 HRESULT hr;
853 HWND hwnd = NULL;
854 IDirect3D8 *pD3d = NULL;
855 IDirect3DDevice8 *pDevice = NULL;
856 D3DPRESENT_PARAMETERS d3dpp;
857 D3DDISPLAYMODE d3ddm;
859 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
860 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
861 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
862 ok(hwnd != NULL, "Failed to create window\n");
863 if (!pD3d || !hwnd) goto cleanup;
865 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
866 ZeroMemory( &d3dpp, sizeof(d3dpp) );
867 d3dpp.Windowed = TRUE;
868 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
869 d3dpp.BackBufferWidth = 800;
870 d3dpp.BackBufferHeight = 600;
871 d3dpp.BackBufferFormat = d3ddm.Format;
874 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
875 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
876 ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
877 if(!pDevice)
879 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
880 goto cleanup;
883 /* Test an EndScene without beginscene. Should return an error */
884 hr = IDirect3DDevice8_EndScene(pDevice);
885 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
887 /* Test a normal BeginScene / EndScene pair, this should work */
888 hr = IDirect3DDevice8_BeginScene(pDevice);
889 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
890 if(SUCCEEDED(hr))
892 hr = IDirect3DDevice8_EndScene(pDevice);
893 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
896 /* Test another EndScene without having begun a new scene. Should return an error */
897 hr = IDirect3DDevice8_EndScene(pDevice);
898 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
900 /* Two nested BeginScene and EndScene calls */
901 hr = IDirect3DDevice8_BeginScene(pDevice);
902 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
903 hr = IDirect3DDevice8_BeginScene(pDevice);
904 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
905 hr = IDirect3DDevice8_EndScene(pDevice);
906 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
907 hr = IDirect3DDevice8_EndScene(pDevice);
908 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
910 /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
912 cleanup:
913 if (pDevice)
915 UINT refcount = IDirect3DDevice8_Release(pDevice);
916 ok(!refcount, "Device has %u references left.\n", refcount);
918 if (pD3d) IDirect3D8_Release(pD3d);
919 if(hwnd) DestroyWindow(hwnd);
922 static void test_shader(void)
924 HRESULT hr;
925 HWND hwnd = NULL;
926 IDirect3D8 *pD3d = NULL;
927 IDirect3DDevice8 *pDevice = NULL;
928 D3DPRESENT_PARAMETERS d3dpp;
929 D3DDISPLAYMODE d3ddm;
930 DWORD hPixelShader = 0, hVertexShader = 0;
931 DWORD hPixelShader2 = 0, hVertexShader2 = 0;
932 DWORD hTempHandle;
933 D3DCAPS8 caps;
934 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
935 DWORD data_size;
936 void *data;
938 static DWORD dwVertexDecl[] =
940 D3DVSD_STREAM(0),
941 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
942 D3DVSD_END()
944 DWORD decl_normal_float2[] =
946 D3DVSD_STREAM(0),
947 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
948 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT2), /* D3DVSDE_NORMAL, Register v1 */
949 D3DVSD_END()
951 DWORD decl_normal_float4[] =
953 D3DVSD_STREAM(0),
954 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
955 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT4), /* D3DVSDE_NORMAL, Register v1 */
956 D3DVSD_END()
958 DWORD decl_normal_d3dcolor[] =
960 D3DVSD_STREAM(0),
961 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
962 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL, Register v1 */
963 D3DVSD_END()
965 const DWORD vertex_decl_size = sizeof(dwVertexDecl);
966 const DWORD simple_vs_size = sizeof(simple_vs);
967 const DWORD simple_ps_size = sizeof(simple_ps);
969 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
970 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
971 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
972 ok(hwnd != NULL, "Failed to create window\n");
973 if (!pD3d || !hwnd) goto cleanup;
975 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
976 ZeroMemory( &d3dpp, sizeof(d3dpp) );
977 d3dpp.Windowed = TRUE;
978 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
979 d3dpp.BackBufferWidth = 800;
980 d3dpp.BackBufferHeight = 600;
981 d3dpp.BackBufferFormat = d3ddm.Format;
984 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
985 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
986 ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
987 if(!pDevice)
989 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
990 goto cleanup;
992 IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
994 /* Test setting and retrieving a FVF */
995 hr = IDirect3DDevice8_SetVertexShader(pDevice, fvf);
996 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
997 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
998 ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
999 ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
1001 /* First create a vertex shader */
1002 hr = IDirect3DDevice8_SetVertexShader(pDevice, 0);
1003 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1004 hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, simple_vs, &hVertexShader, 0);
1005 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1006 /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
1007 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1008 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1009 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1010 /* Assign the shader, then verify that GetVertexShader works */
1011 hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1012 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1013 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1014 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1015 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1016 /* Verify that we can retrieve the declaration */
1017 hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, NULL, &data_size);
1018 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1019 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1020 data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
1021 data_size = 1;
1022 hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1023 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
1024 "expected D3DERR_INVALIDCALL\n", hr);
1025 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1026 data_size = vertex_decl_size;
1027 hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
1028 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1029 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1030 ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
1031 HeapFree(GetProcessHeap(), 0, data);
1032 /* Verify that we can retrieve the shader function */
1033 hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, NULL, &data_size);
1034 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1035 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1036 data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
1037 data_size = 1;
1038 hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1039 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
1040 "expected D3DERR_INVALIDCALL\n", hr);
1041 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1042 data_size = simple_vs_size;
1043 hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1044 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1045 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1046 ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
1047 HeapFree(GetProcessHeap(), 0, data);
1048 /* Delete the assigned shader. This is supposed to work */
1049 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1050 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1051 /* The shader should be unset now */
1052 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1053 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1054 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1056 /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
1057 * First try the fixed function shader function, then a custom one
1059 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, 0, &hVertexShader, 0);
1060 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1061 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1062 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float4, 0, &hVertexShader, 0);
1063 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1064 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1065 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_d3dcolor, 0, &hVertexShader, 0);
1066 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1067 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1069 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, simple_vs, &hVertexShader, 0);
1070 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1071 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1073 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
1075 /* The same with a pixel shader */
1076 hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1077 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1078 /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
1079 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1080 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1081 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1082 /* Assign the shader, then verify that GetPixelShader works */
1083 hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1084 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1085 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1086 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1087 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1088 /* Verify that we can retrieve the shader function */
1089 hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, NULL, &data_size);
1090 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1091 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1092 data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
1093 data_size = 1;
1094 hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1095 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
1096 "expected D3DERR_INVALIDCALL\n", hr);
1097 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1098 data_size = simple_ps_size;
1099 hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1100 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1101 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1102 ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
1103 HeapFree(GetProcessHeap(), 0, data);
1104 /* Delete the assigned shader. This is supposed to work */
1105 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1106 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1107 /* The shader should be unset now */
1108 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1109 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1110 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1112 /* What happens if a non-bound shader is deleted? */
1113 hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1114 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1115 hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader2);
1116 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1118 hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1119 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1120 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1121 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1122 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1123 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1124 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1125 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1126 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1128 /* Check for double delete. */
1129 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1130 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1131 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1132 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1134 else
1136 skip("Pixel shaders not supported\n");
1139 /* What happens if a non-bound shader is deleted? */
1140 hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader, 0);
1141 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1142 hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader2, 0);
1143 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1145 hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1146 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1147 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1148 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1149 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1150 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1151 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1152 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1153 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1155 /* Check for double delete. */
1156 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1157 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1158 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1159 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1161 cleanup:
1162 if (pDevice)
1164 UINT refcount = IDirect3DDevice8_Release(pDevice);
1165 ok(!refcount, "Device has %u references left.\n", refcount);
1167 if (pD3d) IDirect3D8_Release(pD3d);
1168 if(hwnd) DestroyWindow(hwnd);
1171 static void test_limits(void)
1173 HRESULT hr;
1174 HWND hwnd = NULL;
1175 IDirect3D8 *pD3d = NULL;
1176 IDirect3DDevice8 *pDevice = NULL;
1177 D3DPRESENT_PARAMETERS d3dpp;
1178 D3DDISPLAYMODE d3ddm;
1179 IDirect3DTexture8 *pTexture = NULL;
1180 int i;
1182 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1183 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1184 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1185 ok(hwnd != NULL, "Failed to create window\n");
1186 if (!pD3d || !hwnd) goto cleanup;
1188 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1189 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1190 d3dpp.Windowed = TRUE;
1191 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1192 d3dpp.BackBufferWidth = 800;
1193 d3dpp.BackBufferHeight = 600;
1194 d3dpp.BackBufferFormat = d3ddm.Format;
1195 d3dpp.EnableAutoDepthStencil = TRUE;
1196 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1198 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1199 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1200 ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1201 if(!pDevice)
1203 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1204 goto cleanup;
1207 hr = IDirect3DDevice8_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture);
1208 ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
1209 if(!pTexture) goto cleanup;
1211 /* There are 8 texture stages. We should be able to access all of them */
1212 for(i = 0; i < 8; i++) {
1213 hr = IDirect3DDevice8_SetTexture(pDevice, i, (IDirect3DBaseTexture8 *) pTexture);
1214 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1215 hr = IDirect3DDevice8_SetTexture(pDevice, i, NULL);
1216 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1217 hr = IDirect3DDevice8_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1218 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
1221 /* Investigations show that accessing higher textures stage states does not return an error either. Writing
1222 * to too high texture stages(approximately texture 40) causes memory corruption in windows, so there is no
1223 * bounds checking but how do I test that?
1226 cleanup:
1227 if(pTexture) IDirect3DTexture8_Release(pTexture);
1228 if (pDevice)
1230 UINT refcount = IDirect3DDevice8_Release(pDevice);
1231 ok(!refcount, "Device has %u references left.\n", refcount);
1233 if (pD3d) IDirect3D8_Release(pD3d);
1234 if(hwnd) DestroyWindow(hwnd);
1237 static void test_lights(void)
1239 D3DPRESENT_PARAMETERS d3dpp;
1240 IDirect3DDevice8 *device = NULL;
1241 IDirect3D8 *d3d8;
1242 HWND hwnd;
1243 HRESULT hr;
1244 unsigned int i;
1245 BOOL enabled;
1246 D3DCAPS8 caps;
1247 D3DDISPLAYMODE d3ddm;
1249 d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1250 ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1251 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1252 ok(hwnd != NULL, "Failed to create window\n");
1253 if (!d3d8 || !hwnd) goto cleanup;
1255 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1256 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1257 d3dpp.Windowed = TRUE;
1258 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1259 d3dpp.BackBufferWidth = 800;
1260 d3dpp.BackBufferHeight = 600;
1261 d3dpp.BackBufferFormat = d3ddm.Format;
1262 d3dpp.EnableAutoDepthStencil = TRUE;
1263 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1265 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1266 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
1267 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1268 "IDirect3D8_CreateDevice failed with %08x\n", hr);
1269 if(!device)
1271 skip("Failed to create a d3d device\n");
1272 goto cleanup;
1275 memset(&caps, 0, sizeof(caps));
1276 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1277 ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
1279 for(i = 1; i <= caps.MaxActiveLights; i++) {
1280 hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
1281 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1282 hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
1283 ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
1284 "GetLightEnable on light %u failed with %08x\n", i, hr);
1285 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1288 /* TODO: Test the rendering results in this situation */
1289 hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
1290 ok(hr == D3D_OK ||
1291 broken(hr == D3DERR_INVALIDCALL), /* Some Win9x and WinME */
1292 "Enabling one light more than supported returned %08x\n", hr);
1293 hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
1294 ok(hr == D3D_OK ||
1295 broken(hr == D3DERR_INVALIDCALL), /* Some Win9x and WinME */
1296 "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1297 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1298 hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
1299 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1301 for(i = 1; i <= caps.MaxActiveLights; i++) {
1302 hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
1303 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
1306 cleanup:
1307 if (device)
1309 UINT refcount = IDirect3DDevice8_Release(device);
1310 ok(!refcount, "Device has %u references left.\n", refcount);
1312 if (d3d8) IDirect3D8_Release(d3d8);
1315 static void test_render_zero_triangles(void)
1317 D3DPRESENT_PARAMETERS d3dpp;
1318 IDirect3DDevice8 *device = NULL;
1319 IDirect3D8 *d3d8;
1320 HWND hwnd;
1321 HRESULT hr;
1322 D3DDISPLAYMODE d3ddm;
1324 struct nvertex
1326 float x, y, z;
1327 float nx, ny, nz;
1328 DWORD diffuse;
1329 } quad[] =
1331 { 0.0f, -1.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1332 { 0.0f, 0.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1333 { 1.0f, 0.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1334 { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1337 d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1338 ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1339 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1340 ok(hwnd != NULL, "Failed to create window\n");
1341 if (!d3d8 || !hwnd) goto cleanup;
1343 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1344 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1345 d3dpp.Windowed = TRUE;
1346 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1347 d3dpp.BackBufferWidth = 800;
1348 d3dpp.BackBufferHeight = 600;
1349 d3dpp.BackBufferFormat = d3ddm.Format;
1350 d3dpp.EnableAutoDepthStencil = TRUE;
1351 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1353 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1354 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
1355 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1356 "IDirect3D8_CreateDevice failed with %08x\n", hr);
1357 if(!device)
1359 skip("Failed to create a d3d device\n");
1360 goto cleanup;
1363 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1364 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1366 hr = IDirect3DDevice8_BeginScene(device);
1367 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1368 if(hr == D3D_OK)
1370 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
1371 0 /*PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
1372 ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
1374 IDirect3DDevice8_EndScene(device);
1375 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1378 IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1380 cleanup:
1381 if (device)
1383 UINT refcount = IDirect3DDevice8_Release(device);
1384 ok(!refcount, "Device has %u references left.\n", refcount);
1386 if (d3d8) IDirect3D8_Release(d3d8);
1389 static void test_depth_stencil_reset(void)
1391 D3DPRESENT_PARAMETERS present_parameters;
1392 D3DDISPLAYMODE display_mode;
1393 IDirect3DSurface8 *surface;
1394 IDirect3DDevice8 *device = NULL;
1395 IDirect3D8 *d3d8;
1396 UINT refcount;
1397 HRESULT hr;
1398 HWND hwnd;
1400 d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
1401 ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1402 hwnd = CreateWindow("static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1403 ok(hwnd != NULL, "Failed to create window\n");
1404 if (!d3d8 || !hwnd) goto cleanup;
1406 IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
1407 memset(&present_parameters, 0, sizeof(present_parameters));
1408 present_parameters.Windowed = TRUE;
1409 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1410 present_parameters.BackBufferFormat = display_mode.Format;
1411 present_parameters.EnableAutoDepthStencil = TRUE;
1412 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1414 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
1415 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1416 if(FAILED(hr))
1418 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
1419 goto cleanup;
1422 hr = IDirect3DDevice8_TestCooperativeLevel(device);
1423 ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
1425 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
1426 ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
1428 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
1429 ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
1430 ok(surface != NULL, "Render target should not be NULL\n");
1431 if (surface) IDirect3DSurface8_Release(surface);
1433 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1434 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1435 ok(surface == NULL, "Depth stencil should be NULL\n");
1437 present_parameters.EnableAutoDepthStencil = TRUE;
1438 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1439 hr = IDirect3DDevice8_Reset(device, &present_parameters);
1440 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
1442 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1443 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1444 ok(surface != NULL, "Depth stencil should not be NULL\n");
1445 if (surface) IDirect3DSurface8_Release(surface);
1447 present_parameters.EnableAutoDepthStencil = FALSE;
1448 hr = IDirect3DDevice8_Reset(device, &present_parameters);
1449 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
1451 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1452 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1453 ok(surface == NULL, "Depth stencil should be NULL\n");
1455 refcount = IDirect3DDevice8_Release(device);
1456 ok(!refcount, "Device has %u references left.\n", refcount);
1457 device = NULL;
1459 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
1461 ZeroMemory( &present_parameters, sizeof(present_parameters) );
1462 present_parameters.Windowed = TRUE;
1463 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1464 present_parameters.BackBufferFormat = display_mode.Format;
1465 present_parameters.EnableAutoDepthStencil = FALSE;
1466 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1468 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
1469 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
1471 if(FAILED(hr))
1473 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
1474 goto cleanup;
1477 hr = IDirect3DDevice8_TestCooperativeLevel(device);
1478 ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
1480 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1481 present_parameters.Windowed = TRUE;
1482 present_parameters.BackBufferWidth = 400;
1483 present_parameters.BackBufferHeight = 300;
1484 present_parameters.EnableAutoDepthStencil = TRUE;
1485 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1487 hr = IDirect3DDevice8_Reset(device, &present_parameters);
1488 ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
1490 if (FAILED(hr)) goto cleanup;
1492 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1493 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1494 ok(surface != NULL, "Depth stencil should not be NULL\n");
1495 if (surface) IDirect3DSurface8_Release(surface);
1497 cleanup:
1498 if (device)
1500 refcount = IDirect3DDevice8_Release(device);
1501 ok(!refcount, "Device has %u references left.\n", refcount);
1503 if (d3d8) IDirect3D8_Release(d3d8);
1506 static HWND filter_messages;
1507 struct
1509 HWND window;
1510 UINT message;
1511 } expect_message;
1513 struct wndproc_thread_param
1515 HWND dummy_window;
1516 HANDLE window_created;
1517 HANDLE test_finished;
1520 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1522 if (filter_messages && filter_messages == hwnd)
1524 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
1525 todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
1528 if (expect_message.window == hwnd && expect_message.message == message) expect_message.message = 0;
1530 return DefWindowProcA(hwnd, message, wparam, lparam);
1533 static DWORD WINAPI wndproc_thread(void *param)
1535 struct wndproc_thread_param *p = param;
1536 DWORD res;
1537 BOOL ret;
1539 p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
1540 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, 640, 480, 0, 0, 0, 0);
1542 ret = SetEvent(p->window_created);
1543 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
1545 for (;;)
1547 MSG msg;
1549 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
1550 res = WaitForSingleObject(p->test_finished, 100);
1551 if (res == WAIT_OBJECT_0) break;
1552 if (res != WAIT_TIMEOUT)
1554 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1555 break;
1559 DestroyWindow(p->dummy_window);
1561 return 0;
1564 static void test_wndproc(void)
1566 struct wndproc_thread_param thread_params;
1567 HWND device_window, focus_window, tmp;
1568 IDirect3DDevice8 *device;
1569 WNDCLASSA wc = {0};
1570 IDirect3D8 *d3d8;
1571 HANDLE thread;
1572 LONG_PTR proc;
1573 ULONG ref;
1574 DWORD res, tid;
1576 if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
1578 skip("Failed to create IDirect3D8 object, skipping tests.\n");
1579 return;
1582 wc.lpfnWndProc = test_proc;
1583 wc.lpszClassName = "d3d8_test_wndproc_wc";
1584 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1586 thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
1587 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
1588 thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
1589 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
1591 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
1592 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1593 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
1594 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1595 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
1596 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1598 res = WaitForSingleObject(thread_params.window_created, INFINITE);
1599 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1601 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
1602 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1603 (LONG_PTR)test_proc, proc);
1604 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
1605 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1606 (LONG_PTR)test_proc, proc);
1608 trace("device_window %p, focus_window %p, dummy_window %p.\n",
1609 device_window, focus_window, thread_params.dummy_window);
1611 tmp = GetFocus();
1612 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
1613 tmp = GetForegroundWindow();
1614 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
1615 thread_params.dummy_window, tmp);
1617 expect_message.window = focus_window;
1618 expect_message.message = WM_SETFOCUS;
1620 flush_events();
1622 device = create_device(d3d8, device_window, focus_window, FALSE);
1623 if (!device)
1625 skip("Failed to create a D3D device, skipping tests.\n");
1626 goto done;
1629 ok(!expect_message.message, "Expected message %#x for window %p, but didn't receive it.\n",
1630 expect_message.message, expect_message.window);
1631 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
1633 tmp = GetFocus();
1634 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
1635 tmp = GetForegroundWindow();
1636 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
1638 SetForegroundWindow(focus_window);
1639 flush_events();
1641 filter_messages = focus_window;
1643 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
1644 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1645 (LONG_PTR)test_proc, proc);
1647 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
1648 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1649 (LONG_PTR)test_proc, proc);
1651 ref = IDirect3DDevice8_Release(device);
1652 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1654 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
1655 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1656 (LONG_PTR)test_proc, proc);
1658 device = create_device(d3d8, focus_window, focus_window, FALSE);
1659 if (!device)
1661 skip("Failed to create a D3D device, skipping tests.\n");
1662 goto done;
1665 ref = IDirect3DDevice8_Release(device);
1666 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1668 device = create_device(d3d8, device_window, focus_window, FALSE);
1669 if (!device)
1671 skip("Failed to create a D3D device, skipping tests.\n");
1672 goto done;
1675 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
1676 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
1677 (LONG_PTR)test_proc, proc);
1679 ref = IDirect3DDevice8_Release(device);
1680 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1682 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
1683 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
1684 (LONG_PTR)DefWindowProcA, proc);
1686 done:
1687 filter_messages = NULL;
1688 IDirect3D8_Release(d3d8);
1690 SetEvent(thread_params.test_finished);
1691 WaitForSingleObject(thread, INFINITE);
1692 CloseHandle(thread_params.test_finished);
1693 CloseHandle(thread_params.window_created);
1694 CloseHandle(thread);
1696 DestroyWindow(device_window);
1697 DestroyWindow(focus_window);
1698 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
1701 static void test_wndproc_windowed(void)
1703 struct wndproc_thread_param thread_params;
1704 HWND device_window, focus_window, tmp;
1705 IDirect3DDevice8 *device;
1706 WNDCLASSA wc = {0};
1707 IDirect3D8 *d3d8;
1708 HANDLE thread;
1709 LONG_PTR proc;
1710 ULONG ref;
1711 DWORD res, tid;
1713 if (!(d3d8 = pDirect3DCreate8(D3D_SDK_VERSION)))
1715 skip("Failed to create IDirect3D8 object, skipping tests.\n");
1716 return;
1719 wc.lpfnWndProc = test_proc;
1720 wc.lpszClassName = "d3d8_test_wndproc_wc";
1721 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1723 thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
1724 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
1725 thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
1726 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
1728 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
1729 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, 640, 480, 0, 0, 0, 0);
1730 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
1731 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, 640, 480, 0, 0, 0, 0);
1732 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
1733 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
1735 res = WaitForSingleObject(thread_params.window_created, INFINITE);
1736 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
1738 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
1739 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1740 (LONG_PTR)test_proc, proc);
1741 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
1742 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1743 (LONG_PTR)test_proc, proc);
1745 trace("device_window %p, focus_window %p, dummy_window %p.\n",
1746 device_window, focus_window, thread_params.dummy_window);
1748 tmp = GetFocus();
1749 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
1750 tmp = GetForegroundWindow();
1751 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
1752 thread_params.dummy_window, tmp);
1754 filter_messages = focus_window;
1756 device = create_device(d3d8, device_window, focus_window, TRUE);
1757 if (!device)
1759 skip("Failed to create a D3D device, skipping tests.\n");
1760 goto done;
1763 tmp = GetFocus();
1764 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
1765 tmp = GetForegroundWindow();
1766 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
1767 thread_params.dummy_window, tmp);
1769 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
1770 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1771 (LONG_PTR)test_proc, proc);
1773 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
1774 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
1775 (LONG_PTR)test_proc, proc);
1777 ref = IDirect3DDevice8_Release(device);
1778 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1780 filter_messages = device_window;
1782 device = create_device(d3d8, focus_window, focus_window, TRUE);
1783 if (!device)
1785 skip("Failed to create a D3D device, skipping tests.\n");
1786 goto done;
1789 ref = IDirect3DDevice8_Release(device);
1790 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1792 device = create_device(d3d8, device_window, focus_window, TRUE);
1793 if (!device)
1795 skip("Failed to create a D3D device, skipping tests.\n");
1796 goto done;
1799 ref = IDirect3DDevice8_Release(device);
1800 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1802 done:
1803 filter_messages = NULL;
1804 IDirect3D8_Release(d3d8);
1806 SetEvent(thread_params.test_finished);
1807 WaitForSingleObject(thread, INFINITE);
1808 CloseHandle(thread_params.test_finished);
1809 CloseHandle(thread_params.window_created);
1810 CloseHandle(thread);
1812 DestroyWindow(device_window);
1813 DestroyWindow(focus_window);
1814 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
1817 static inline void set_fpu_cw(WORD cw)
1819 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1820 __asm__ volatile ("fnclex");
1821 __asm__ volatile ("fldcw %0" : : "m" (cw));
1822 #endif
1825 static inline WORD get_fpu_cw(void)
1827 WORD cw = 0;
1828 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1829 __asm__ volatile ("fnstcw %0" : "=m" (cw));
1830 #endif
1831 return cw;
1834 static void test_fpu_setup(void)
1836 D3DPRESENT_PARAMETERS present_parameters;
1837 IDirect3DDevice8 *device;
1838 D3DDISPLAYMODE d3ddm;
1839 HWND window = NULL;
1840 IDirect3D8 *d3d8;
1841 HRESULT hr;
1842 WORD cw;
1844 d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
1845 ok(!!d3d8, "Failed to create a d3d8 object.\n");
1846 if (!d3d8) return;
1848 window = CreateWindowA("static", "d3d8_test", WS_CAPTION, 0, 0, 640, 480, 0, 0, 0, 0);
1849 ok(!!window, "Failed to create a window.\n");
1850 if (!window) goto done;
1852 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1853 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1855 memset(&present_parameters, 0, sizeof(present_parameters));
1856 present_parameters.Windowed = TRUE;
1857 present_parameters.hDeviceWindow = window;
1858 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1859 present_parameters.BackBufferFormat = d3ddm.Format;
1861 set_fpu_cw(0xf60);
1862 cw = get_fpu_cw();
1863 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
1865 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
1866 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
1867 if (FAILED(hr))
1869 skip("Failed to create a device, hr %#x.\n", hr);
1870 set_fpu_cw(0x37f);
1871 goto done;
1874 cw = get_fpu_cw();
1875 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
1877 IDirect3DDevice8_Release(device);
1879 cw = get_fpu_cw();
1880 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
1881 set_fpu_cw(0xf60);
1882 cw = get_fpu_cw();
1883 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
1885 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
1886 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
1887 ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
1889 cw = get_fpu_cw();
1890 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
1891 set_fpu_cw(0x37f);
1893 IDirect3DDevice8_Release(device);
1895 done:
1896 if (window) DestroyWindow(window);
1897 if (d3d8) IDirect3D8_Release(d3d8);
1900 START_TEST(device)
1902 HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
1903 if (!d3d8_handle)
1905 skip("Could not load d3d8.dll\n");
1906 return;
1909 pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
1910 ok(pDirect3DCreate8 != NULL, "Failed to get address of Direct3DCreate8\n");
1911 if (pDirect3DCreate8)
1913 IDirect3D8 *d3d8;
1914 d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1915 if(!d3d8)
1917 skip("could not create D3D8\n");
1918 return;
1920 IDirect3D8_Release(d3d8);
1922 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1923 test_fpu_setup();
1924 #endif
1925 test_display_modes();
1926 test_shader_versions();
1927 test_swapchain();
1928 test_refcount();
1929 test_mipmap_levels();
1930 test_cursor();
1931 test_states();
1932 test_scene();
1933 test_shader();
1934 test_limits();
1935 test_lights();
1936 test_render_zero_triangles();
1937 test_depth_stencil_reset();
1938 test_wndproc();
1939 test_wndproc_windowed();