push 149f0a5527ac85057a8ef03858d34d91c36f97e8
[wine/hacks.git] / dlls / d3d8 / tests / device.c
blob5e1f5232ff34c0f33479b35a6bd8dba4dadb9868
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 #define CHECK_CALL(r,c,d,rc) \
50 if (SUCCEEDED(r)) {\
51 int tmp1 = get_refcount( (IUnknown *)d ); \
52 int rc_new = rc; \
53 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
54 } else {\
55 trace("%s failed: %#08x\n", c, r); \
58 #define CHECK_RELEASE(obj,d,rc) \
59 if (obj) { \
60 int tmp1, rc_new = rc; \
61 IUnknown_Release( obj ); \
62 tmp1 = get_refcount( (IUnknown *)d ); \
63 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
66 #define CHECK_REFCOUNT(obj,rc) \
67 { \
68 int rc_new = rc; \
69 int count = get_refcount( (IUnknown *)obj ); \
70 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
73 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
74 { \
75 int rc_new = rc; \
76 int count = IUnknown_Release( (IUnknown *)obj ); \
77 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
80 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
81 { \
82 int rc_new = rc; \
83 int count = IUnknown_AddRef( (IUnknown *)obj ); \
84 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
87 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
88 { \
89 void *container_ptr = (void *)0x1337c0d3; \
90 hr = IDirect3DSurface8_GetContainer(obj, &iid, &container_ptr); \
91 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#08x, container_ptr %p. " \
92 "Expected hr %#08x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
93 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
96 static void check_mipmap_levels(IDirect3DDevice8 *device, UINT width, UINT height, UINT count)
98 IDirect3DBaseTexture8* texture = NULL;
99 HRESULT hr = IDirect3DDevice8_CreateTexture( device, width, height, 0, 0,
100 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture8**) &texture );
102 if (SUCCEEDED(hr)) {
103 DWORD levels = IDirect3DBaseTexture8_GetLevelCount(texture);
104 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
105 } else
106 trace("CreateTexture failed: %#08x\n", hr);
108 if (texture) IUnknown_Release( texture );
111 static void test_mipmap_levels(void)
114 HRESULT hr;
115 HWND hwnd = NULL;
117 IDirect3D8 *pD3d = NULL;
118 IDirect3DDevice8 *pDevice = NULL;
119 D3DPRESENT_PARAMETERS d3dpp;
120 D3DDISPLAYMODE d3ddm;
122 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
123 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
124 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
125 ok(hwnd != NULL, "Failed to create window\n");
126 if (!pD3d || !hwnd) goto cleanup;
128 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
129 ZeroMemory( &d3dpp, sizeof(d3dpp) );
130 d3dpp.Windowed = TRUE;
131 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
132 d3dpp.BackBufferFormat = d3ddm.Format;
134 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
135 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
136 if(FAILED(hr))
138 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
139 goto cleanup;
142 check_mipmap_levels(pDevice, 32, 32, 6);
143 check_mipmap_levels(pDevice, 256, 1, 9);
144 check_mipmap_levels(pDevice, 1, 256, 9);
145 check_mipmap_levels(pDevice, 1, 1, 1);
147 cleanup:
148 if (pDevice)
150 UINT refcount = IUnknown_Release( pDevice );
151 ok(!refcount, "Device has %u references left.\n", refcount);
153 if (pD3d) IUnknown_Release( pD3d );
154 DestroyWindow( hwnd );
157 static void test_swapchain(void)
159 HRESULT hr;
160 HWND hwnd = NULL;
161 IDirect3D8 *pD3d = NULL;
162 IDirect3DDevice8 *pDevice = NULL;
163 IDirect3DSwapChain8 *swapchain1 = NULL;
164 IDirect3DSwapChain8 *swapchain2 = NULL;
165 IDirect3DSwapChain8 *swapchain3 = NULL;
166 IDirect3DSurface8 *backbuffer = NULL;
167 D3DPRESENT_PARAMETERS d3dpp;
168 D3DDISPLAYMODE d3ddm;
170 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
171 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
172 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
173 ok(hwnd != NULL, "Failed to create window\n");
174 if (!pD3d || !hwnd) goto cleanup;
176 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
177 ZeroMemory( &d3dpp, sizeof(d3dpp) );
178 d3dpp.Windowed = TRUE;
179 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
180 d3dpp.BackBufferFormat = d3ddm.Format;
181 d3dpp.BackBufferCount = 0;
183 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
184 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
185 if(FAILED(hr))
187 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
188 goto cleanup;
191 /* Check if the back buffer count was modified */
192 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
194 /* Create a bunch of swapchains */
195 d3dpp.BackBufferCount = 0;
196 hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
197 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
198 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
200 d3dpp.BackBufferCount = 1;
201 hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
202 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
204 d3dpp.BackBufferCount = 2;
205 hr = IDirect3DDevice8_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
206 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
207 if(SUCCEEDED(hr)) {
208 /* Swapchain 3, created with backbuffercount 2 */
209 backbuffer = (void *) 0xdeadbeef;
210 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
211 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%#08x)\n", hr);
212 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
213 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
215 backbuffer = (void *) 0xdeadbeef;
216 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
217 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%#08x)\n", hr);
218 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
219 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
221 backbuffer = (void *) 0xdeadbeef;
222 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
223 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
224 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
225 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
227 backbuffer = (void *) 0xdeadbeef;
228 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
229 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
230 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
231 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
234 /* Check the back buffers of the swapchains */
235 /* Swapchain 1, created with backbuffercount 0 */
236 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
237 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
238 ok(backbuffer != NULL, "The back buffer is NULL (%#08x)\n", hr);
239 if(backbuffer) IDirect3DSurface8_Release(backbuffer);
241 backbuffer = (void *) 0xdeadbeef;
242 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
243 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
244 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
245 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
247 /* Swapchain 2 - created with backbuffercount 1 */
248 backbuffer = (void *) 0xdeadbeef;
249 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
250 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
251 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
252 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
254 backbuffer = (void *) 0xdeadbeef;
255 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
256 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
257 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
258 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
260 backbuffer = (void *) 0xdeadbeef;
261 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
262 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
263 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
264 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
266 cleanup:
267 if(swapchain1) IDirect3DSwapChain8_Release(swapchain1);
268 if(swapchain2) IDirect3DSwapChain8_Release(swapchain2);
269 if(swapchain3) IDirect3DSwapChain8_Release(swapchain3);
270 if (pDevice)
272 UINT refcount = IDirect3DDevice8_Release(pDevice);
273 ok(!refcount, "Device has %u references left.\n", refcount);
275 if (pD3d) IDirect3D8_Release(pD3d);
276 DestroyWindow( hwnd );
279 static void test_refcount(void)
281 HRESULT hr;
282 HWND hwnd = NULL;
283 IDirect3D8 *pD3d = NULL;
284 IDirect3DDevice8 *pDevice = NULL;
285 IDirect3DVertexBuffer8 *pVertexBuffer = NULL;
286 IDirect3DIndexBuffer8 *pIndexBuffer = NULL;
287 DWORD dVertexShader = -1;
288 DWORD dPixelShader = -1;
289 IDirect3DCubeTexture8 *pCubeTexture = NULL;
290 IDirect3DTexture8 *pTexture = NULL;
291 IDirect3DVolumeTexture8 *pVolumeTexture = NULL;
292 IDirect3DVolume8 *pVolumeLevel = NULL;
293 IDirect3DSurface8 *pStencilSurface = NULL;
294 IDirect3DSurface8 *pImageSurface = NULL;
295 IDirect3DSurface8 *pRenderTarget = NULL;
296 IDirect3DSurface8 *pRenderTarget2 = NULL;
297 IDirect3DSurface8 *pRenderTarget3 = NULL;
298 IDirect3DSurface8 *pTextureLevel = NULL;
299 IDirect3DSurface8 *pBackBuffer = NULL;
300 DWORD dStateBlock = -1;
301 IDirect3DSwapChain8 *pSwapChain = NULL;
302 D3DCAPS8 caps;
304 D3DPRESENT_PARAMETERS d3dpp;
305 D3DDISPLAYMODE d3ddm;
306 int refcount = 0, tmp;
308 DWORD decl[] =
310 D3DVSD_STREAM(0),
311 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
312 D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
313 D3DVSD_END()
316 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
317 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
318 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
319 ok(hwnd != NULL, "Failed to create window\n");
320 if (!pD3d || !hwnd) goto cleanup;
322 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
323 ZeroMemory( &d3dpp, sizeof(d3dpp) );
324 d3dpp.Windowed = TRUE;
325 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
326 d3dpp.BackBufferFormat = d3ddm.Format;
327 d3dpp.EnableAutoDepthStencil = TRUE;
328 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
330 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
331 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
332 if(FAILED(hr))
334 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
335 goto cleanup;
337 IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
339 refcount = get_refcount( (IUnknown *)pDevice );
340 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
343 * Check refcount of implicit surfaces. Findings:
344 * - the container is the device
345 * - they hold a reference to the device
346 * - they are created with a refcount of 0 (Get/Release returns original refcount)
347 * - they are not freed if refcount reaches 0.
348 * - the refcount is not forwarded to the container.
350 hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
351 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
352 if(pRenderTarget)
354 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DDevice8, pDevice);
355 CHECK_REFCOUNT( pRenderTarget, 1);
357 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
358 CHECK_REFCOUNT(pDevice, refcount);
359 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
360 CHECK_REFCOUNT(pDevice, refcount);
362 hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget);
363 CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
364 CHECK_REFCOUNT( pRenderTarget, 2);
365 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
366 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
367 CHECK_REFCOUNT( pDevice, --refcount);
369 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
370 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
371 CHECK_REFCOUNT(pDevice, ++refcount);
372 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
373 CHECK_REFCOUNT(pDevice, --refcount);
376 /* Render target and back buffer are identical. */
377 hr = IDirect3DDevice8_GetBackBuffer(pDevice, 0, 0, &pBackBuffer);
378 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
379 if(pBackBuffer)
381 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
382 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
383 pRenderTarget, pBackBuffer);
384 pBackBuffer = NULL;
386 CHECK_REFCOUNT( pDevice, --refcount);
388 hr = IDirect3DDevice8_GetDepthStencilSurface(pDevice, &pStencilSurface);
389 CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
390 if(pStencilSurface)
392 CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice8, pDevice);
393 CHECK_REFCOUNT( pStencilSurface, 1);
395 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
396 CHECK_REFCOUNT(pDevice, refcount);
397 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
398 CHECK_REFCOUNT(pDevice, refcount);
400 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
401 CHECK_REFCOUNT( pDevice, --refcount);
403 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
404 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
405 CHECK_REFCOUNT(pDevice, ++refcount);
406 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
407 CHECK_REFCOUNT(pDevice, --refcount);
408 pStencilSurface = NULL;
411 /* Buffers */
412 hr = IDirect3DDevice8_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer );
413 CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
414 if(pIndexBuffer)
416 tmp = get_refcount( (IUnknown *)pIndexBuffer );
418 hr = IDirect3DDevice8_SetIndices(pDevice, pIndexBuffer, 0);
419 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
420 hr = IDirect3DDevice8_SetIndices(pDevice, NULL, 0);
421 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
424 hr = IDirect3DDevice8_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer );
425 CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
426 if(pVertexBuffer)
428 IDirect3DVertexBuffer8 *pVBuf = (void*)~0;
429 UINT stride = ~0;
431 tmp = get_refcount( (IUnknown *)pVertexBuffer );
433 hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, pVertexBuffer, 3 * sizeof(float));
434 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
435 hr = IDirect3DDevice8_SetStreamSource(pDevice, 0, NULL, 0);
436 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
438 hr = IDirect3DDevice8_GetStreamSource(pDevice, 0, &pVBuf, &stride);
439 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
440 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
441 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
444 /* Shaders */
445 hr = IDirect3DDevice8_CreateVertexShader( pDevice, decl, simple_vs, &dVertexShader, 0 );
446 CHECK_CALL( hr, "CreateVertexShader", pDevice, refcount );
447 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
449 hr = IDirect3DDevice8_CreatePixelShader( pDevice, simple_ps, &dPixelShader );
450 CHECK_CALL( hr, "CreatePixelShader", pDevice, refcount );
452 /* Textures */
453 hr = IDirect3DDevice8_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture );
454 CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
455 if (pTexture)
457 tmp = get_refcount( (IUnknown *)pTexture );
459 /* SetTexture should not increase refcounts */
460 hr = IDirect3DDevice8_SetTexture(pDevice, 0, (IDirect3DBaseTexture8 *) pTexture);
461 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
462 hr = IDirect3DDevice8_SetTexture(pDevice, 0, NULL);
463 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
465 /* This should not increment device refcount */
466 hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
467 CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
468 /* But should increment texture's refcount */
469 CHECK_REFCOUNT( pTexture, tmp+1 );
470 /* Because the texture and surface refcount are identical */
471 if (pTextureLevel)
473 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
474 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
475 CHECK_REFCOUNT ( pTexture , tmp+2 );
476 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
477 CHECK_REFCOUNT ( pTexture , tmp+1 );
478 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
479 CHECK_REFCOUNT ( pTextureLevel, tmp );
482 if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
484 hr = IDirect3DDevice8_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture );
485 CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
487 else
489 skip("Cube textures not supported\n");
491 if(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
493 hr = IDirect3DDevice8_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture );
494 CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
496 else
498 skip("Volume textures not supported\n");
501 if (pVolumeTexture)
503 tmp = get_refcount( (IUnknown *)pVolumeTexture );
505 /* This should not increment device refcount */
506 hr = IDirect3DVolumeTexture8_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
507 CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
508 /* But should increment volume texture's refcount */
509 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
510 /* Because the volume texture and volume refcount are identical */
511 if (pVolumeLevel)
513 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
514 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
515 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
516 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
517 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
518 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
519 CHECK_REFCOUNT ( pVolumeLevel , tmp );
522 /* Surfaces */
523 hr = IDirect3DDevice8_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D16, D3DMULTISAMPLE_NONE, &pStencilSurface );
524 CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
525 CHECK_REFCOUNT( pStencilSurface, 1);
526 hr = IDirect3DDevice8_CreateImageSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, &pImageSurface );
527 CHECK_CALL( hr, "CreateImageSurface", pDevice, ++refcount );
528 CHECK_REFCOUNT( pImageSurface, 1);
529 hr = IDirect3DDevice8_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget3 );
530 CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
531 CHECK_REFCOUNT( pRenderTarget3, 1);
532 /* Misc */
533 hr = IDirect3DDevice8_CreateStateBlock( pDevice, D3DSBT_ALL, &dStateBlock );
534 CHECK_CALL( hr, "CreateStateBlock", pDevice, refcount );
535 hr = IDirect3DDevice8_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
536 CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
537 if(pSwapChain)
539 /* check implicit back buffer */
540 hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
541 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
542 CHECK_REFCOUNT( pSwapChain, 1);
543 if(pBackBuffer)
545 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DDevice8, pDevice);
546 CHECK_REFCOUNT( pBackBuffer, 1);
547 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
548 CHECK_REFCOUNT( pDevice, --refcount);
550 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
551 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
552 CHECK_REFCOUNT(pDevice, ++refcount);
553 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
554 CHECK_REFCOUNT(pDevice, --refcount);
555 pBackBuffer = NULL;
557 CHECK_REFCOUNT( pSwapChain, 1);
560 if(pVertexBuffer)
562 BYTE *data;
563 /* Vertex buffers can be locked multiple times */
564 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
565 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
566 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
567 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
568 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
569 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
570 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
571 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
574 /* The implicit render target is not freed if refcount reaches 0.
575 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
576 hr = IDirect3DDevice8_GetRenderTarget(pDevice, &pRenderTarget2);
577 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
578 if(pRenderTarget2)
580 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
581 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
582 pRenderTarget, pRenderTarget2);
583 CHECK_REFCOUNT( pDevice, --refcount);
584 pRenderTarget2 = NULL;
586 pRenderTarget = NULL;
588 cleanup:
589 CHECK_RELEASE(pDevice, pDevice, --refcount);
591 /* Buffers */
592 CHECK_RELEASE(pVertexBuffer, pDevice, --refcount);
593 CHECK_RELEASE(pIndexBuffer, pDevice, --refcount);
594 /* Shaders */
595 if (dVertexShader != ~0U) IDirect3DDevice8_DeleteVertexShader( pDevice, dVertexShader );
596 if (dPixelShader != ~0U) IDirect3DDevice8_DeletePixelShader( pDevice, dPixelShader );
597 /* Textures */
598 CHECK_RELEASE(pTexture, pDevice, --refcount);
599 CHECK_RELEASE(pCubeTexture, pDevice, --refcount);
600 CHECK_RELEASE(pVolumeTexture, pDevice, --refcount);
601 /* Surfaces */
602 CHECK_RELEASE(pStencilSurface, pDevice, --refcount);
603 CHECK_RELEASE(pImageSurface, pDevice, --refcount);
604 CHECK_RELEASE(pRenderTarget3, pDevice, --refcount);
605 /* Misc */
606 if (dStateBlock != ~0U) IDirect3DDevice8_DeleteStateBlock( pDevice, dStateBlock );
607 /* This will destroy device - cannot check the refcount here */
608 if (pSwapChain) CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
610 if (pD3d) CHECK_RELEASE_REFCOUNT( pD3d, 0);
612 DestroyWindow( hwnd );
615 static void test_cursor(void)
617 HRESULT hr;
618 HWND hwnd = NULL;
619 IDirect3D8 *pD3d = NULL;
620 IDirect3DDevice8 *pDevice = NULL;
621 D3DPRESENT_PARAMETERS d3dpp;
622 D3DDISPLAYMODE d3ddm;
623 CURSORINFO info;
624 IDirect3DSurface8 *cursor = NULL;
625 HCURSOR cur;
626 HMODULE user32_handle = GetModuleHandleA("user32.dll");
628 pGetCursorInfo = (void *)GetProcAddress(user32_handle, "GetCursorInfo");
629 if (!pGetCursorInfo)
631 win_skip("GetCursorInfo is not available\n");
632 return;
635 memset(&info, 0, sizeof(info));
636 info.cbSize = sizeof(info);
637 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
638 cur = info.hCursor;
640 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
641 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
642 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
643 ok(hwnd != NULL, "Failed to create window\n");
644 if (!pD3d || !hwnd) goto cleanup;
646 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
647 ZeroMemory( &d3dpp, sizeof(d3dpp) );
648 d3dpp.Windowed = TRUE;
649 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
650 d3dpp.BackBufferFormat = d3ddm.Format;
652 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
653 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
654 if(FAILED(hr))
656 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
657 goto cleanup;
660 IDirect3DDevice8_CreateImageSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, &cursor);
661 ok(cursor != NULL, "IDirect3DDevice8_CreateOffscreenPlainSurface failed with %#08x\n", hr);
663 /* Initially hidden */
664 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
665 ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
667 /* Not enabled without a surface*/
668 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
669 ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
671 /* Fails */
672 hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, NULL);
673 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
675 hr = IDirect3DDevice8_SetCursorProperties(pDevice, 0, 0, cursor);
676 ok(hr == D3D_OK, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
678 IDirect3DSurface8_Release(cursor);
680 memset(&info, 0, sizeof(info));
681 info.cbSize = sizeof(info);
682 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
683 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
684 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
686 /* Still hidden */
687 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
688 ok(hr == FALSE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
690 /* Enabled now*/
691 hr = IDirect3DDevice8_ShowCursor(pDevice, TRUE);
692 ok(hr == TRUE, "IDirect3DDevice8_ShowCursor returned %#08x\n", hr);
694 /* GDI cursor unchanged */
695 memset(&info, 0, sizeof(info));
696 info.cbSize = sizeof(info);
697 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
698 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
699 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
701 cleanup:
702 if (pDevice)
704 UINT refcount = IDirect3DDevice8_Release(pDevice);
705 ok(!refcount, "Device has %u references left.\n", refcount);
707 if (pD3d) IDirect3D8_Release(pD3d);
710 static void test_states(void)
712 HRESULT hr;
713 HWND hwnd = NULL;
714 IDirect3D8 *pD3d = NULL;
715 IDirect3DDevice8 *pDevice = NULL;
716 D3DPRESENT_PARAMETERS d3dpp;
717 D3DDISPLAYMODE d3ddm;
719 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
720 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
721 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
722 ok(hwnd != NULL, "Failed to create window\n");
723 if (!pD3d || !hwnd) goto cleanup;
725 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
726 ZeroMemory( &d3dpp, sizeof(d3dpp) );
727 d3dpp.Windowed = TRUE;
728 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
729 d3dpp.BackBufferWidth = 640;
730 d3dpp.BackBufferHeight = 480;
731 d3dpp.BackBufferFormat = d3ddm.Format;
733 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
734 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
735 if(FAILED(hr))
737 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
738 goto cleanup;
741 hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, TRUE);
742 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, TRUE) returned %#08x\n", hr);
743 hr = IDirect3DDevice8_SetRenderState(pDevice, D3DRS_ZVISIBLE, FALSE);
744 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, FALSE) returned %#08x\n", hr);
746 cleanup:
747 if (pDevice)
749 UINT refcount = IDirect3DDevice8_Release(pDevice);
750 ok(!refcount, "Device has %u references left.\n", refcount);
752 if (pD3d) IDirect3D8_Release(pD3d);
755 static void test_shader_versions(void)
757 HRESULT hr;
758 IDirect3D8 *pD3d = NULL;
759 D3DCAPS8 d3dcaps;
761 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
762 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
763 if (pD3d != NULL) {
764 hr = IDirect3D8_GetDeviceCaps(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);
765 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to get D3D8 caps (%#08x)\n", hr);
766 if (SUCCEEDED(hr)) {
767 ok(d3dcaps.VertexShaderVersion <= D3DVS_VERSION(1,1), "Unexpected VertexShaderVersion (%#x > %#x)\n", d3dcaps.VertexShaderVersion, D3DVS_VERSION(1,1));
768 ok(d3dcaps.PixelShaderVersion <= D3DPS_VERSION(1,4), "Unexpected PixelShaderVersion (%#x > %#x)\n", d3dcaps.PixelShaderVersion, D3DPS_VERSION(1,4));
769 } else {
770 skip("No Direct3D support\n");
772 IDirect3D8_Release(pD3d);
777 /* Test adapter display modes */
778 static void test_display_modes(void)
780 UINT max_modes, i;
781 D3DDISPLAYMODE dmode;
782 HRESULT res;
783 IDirect3D8 *pD3d;
785 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
786 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
787 if(!pD3d) return;
789 max_modes = IDirect3D8_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT);
790 ok(max_modes > 0 ||
791 broken(max_modes == 0), /* VMware */
792 "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
794 for(i=0; i<max_modes;i++) {
795 res = IDirect3D8_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, i, &dmode);
796 ok(res==D3D_OK, "EnumAdapterModes returned %#08x for mode %u!\n", res, i);
797 if(res != D3D_OK)
798 continue;
800 ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
801 "Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
804 IDirect3D8_Release(pD3d);
807 static void test_scene(void)
809 HRESULT hr;
810 HWND hwnd = NULL;
811 IDirect3D8 *pD3d = NULL;
812 IDirect3DDevice8 *pDevice = NULL;
813 D3DPRESENT_PARAMETERS d3dpp;
814 D3DDISPLAYMODE d3ddm;
816 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
817 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
818 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
819 ok(hwnd != NULL, "Failed to create window\n");
820 if (!pD3d || !hwnd) goto cleanup;
822 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
823 ZeroMemory( &d3dpp, sizeof(d3dpp) );
824 d3dpp.Windowed = TRUE;
825 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
826 d3dpp.BackBufferWidth = 800;
827 d3dpp.BackBufferHeight = 600;
828 d3dpp.BackBufferFormat = d3ddm.Format;
831 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
832 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
833 ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
834 if(!pDevice)
836 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
837 goto cleanup;
840 /* Test an EndScene without beginscene. Should return an error */
841 hr = IDirect3DDevice8_EndScene(pDevice);
842 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
844 /* Test a normal BeginScene / EndScene pair, this should work */
845 hr = IDirect3DDevice8_BeginScene(pDevice);
846 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
847 if(SUCCEEDED(hr))
849 hr = IDirect3DDevice8_EndScene(pDevice);
850 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
853 /* Test another EndScene without having begun a new scene. Should return an error */
854 hr = IDirect3DDevice8_EndScene(pDevice);
855 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
857 /* Two nested BeginScene and EndScene calls */
858 hr = IDirect3DDevice8_BeginScene(pDevice);
859 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
860 hr = IDirect3DDevice8_BeginScene(pDevice);
861 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
862 hr = IDirect3DDevice8_EndScene(pDevice);
863 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
864 hr = IDirect3DDevice8_EndScene(pDevice);
865 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
867 /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
869 cleanup:
870 if (pDevice)
872 UINT refcount = IDirect3DDevice8_Release(pDevice);
873 ok(!refcount, "Device has %u references left.\n", refcount);
875 if (pD3d) IDirect3D8_Release(pD3d);
876 if(hwnd) DestroyWindow(hwnd);
879 static void test_shader(void)
881 HRESULT hr;
882 HWND hwnd = NULL;
883 IDirect3D8 *pD3d = NULL;
884 IDirect3DDevice8 *pDevice = NULL;
885 D3DPRESENT_PARAMETERS d3dpp;
886 D3DDISPLAYMODE d3ddm;
887 DWORD hPixelShader = 0, hVertexShader = 0;
888 DWORD hPixelShader2 = 0, hVertexShader2 = 0;
889 DWORD hTempHandle;
890 D3DCAPS8 caps;
891 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
892 DWORD data_size;
893 void *data;
895 static DWORD dwVertexDecl[] =
897 D3DVSD_STREAM(0),
898 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
899 D3DVSD_END()
901 DWORD decl_normal_float2[] =
903 D3DVSD_STREAM(0),
904 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
905 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT2), /* D3DVSDE_NORMAL, Register v1 */
906 D3DVSD_END()
908 DWORD decl_normal_float4[] =
910 D3DVSD_STREAM(0),
911 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
912 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT4), /* D3DVSDE_NORMAL, Register v1 */
913 D3DVSD_END()
915 DWORD decl_normal_d3dcolor[] =
917 D3DVSD_STREAM(0),
918 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
919 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL, Register v1 */
920 D3DVSD_END()
922 const DWORD vertex_decl_size = sizeof(dwVertexDecl);
923 const DWORD simple_vs_size = sizeof(simple_vs);
924 const DWORD simple_ps_size = sizeof(simple_ps);
926 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
927 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
928 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
929 ok(hwnd != NULL, "Failed to create window\n");
930 if (!pD3d || !hwnd) goto cleanup;
932 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
933 ZeroMemory( &d3dpp, sizeof(d3dpp) );
934 d3dpp.Windowed = TRUE;
935 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
936 d3dpp.BackBufferWidth = 800;
937 d3dpp.BackBufferHeight = 600;
938 d3dpp.BackBufferFormat = d3ddm.Format;
941 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
942 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
943 ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
944 if(!pDevice)
946 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
947 goto cleanup;
949 IDirect3DDevice8_GetDeviceCaps(pDevice, &caps);
951 /* Test setting and retrieving a FVF */
952 hr = IDirect3DDevice8_SetVertexShader(pDevice, fvf);
953 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
954 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
955 ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
956 ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
958 /* First create a vertex shader */
959 hr = IDirect3DDevice8_SetVertexShader(pDevice, 0);
960 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
961 hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, simple_vs, &hVertexShader, 0);
962 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
963 /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
964 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
965 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
966 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
967 /* Assign the shader, then verify that GetVertexShader works */
968 hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
969 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
970 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
971 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
972 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
973 /* Verify that we can retrieve the declaration */
974 hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, NULL, &data_size);
975 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
976 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
977 data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
978 data_size = 1;
979 hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
980 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
981 "expected D3DERR_INVALIDCALL\n", hr);
982 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
983 data_size = vertex_decl_size;
984 hr = IDirect3DDevice8_GetVertexShaderDeclaration(pDevice, hVertexShader, data, &data_size);
985 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
986 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
987 ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
988 HeapFree(GetProcessHeap(), 0, data);
989 /* Verify that we can retrieve the shader function */
990 hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, NULL, &data_size);
991 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
992 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
993 data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
994 data_size = 1;
995 hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
996 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
997 "expected D3DERR_INVALIDCALL\n", hr);
998 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
999 data_size = simple_vs_size;
1000 hr = IDirect3DDevice8_GetVertexShaderFunction(pDevice, hVertexShader, data, &data_size);
1001 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1002 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
1003 ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
1004 HeapFree(GetProcessHeap(), 0, data);
1005 /* Delete the assigned shader. This is supposed to work */
1006 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1007 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1008 /* The shader should be unset now */
1009 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1010 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1011 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1013 /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
1014 * First try the fixed function shader function, then a custom one
1016 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, 0, &hVertexShader, 0);
1017 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1018 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1019 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float4, 0, &hVertexShader, 0);
1020 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1021 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1022 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_d3dcolor, 0, &hVertexShader, 0);
1023 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1024 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1026 hr = IDirect3DDevice8_CreateVertexShader(pDevice, decl_normal_float2, simple_vs, &hVertexShader, 0);
1027 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1028 if(SUCCEEDED(hr)) IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1030 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
1032 /* The same with a pixel shader */
1033 hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1034 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1035 /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
1036 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1037 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1038 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1039 /* Assign the shader, then verify that GetPixelShader works */
1040 hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1041 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1042 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1043 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1044 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1045 /* Verify that we can retrieve the shader function */
1046 hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, NULL, &data_size);
1047 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1048 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1049 data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
1050 data_size = 1;
1051 hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1052 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
1053 "expected D3DERR_INVALIDCALL\n", hr);
1054 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1055 data_size = simple_ps_size;
1056 hr = IDirect3DDevice8_GetPixelShaderFunction(pDevice, hPixelShader, data, &data_size);
1057 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
1058 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
1059 ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
1060 HeapFree(GetProcessHeap(), 0, data);
1061 /* Delete the assigned shader. This is supposed to work */
1062 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1063 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1064 /* The shader should be unset now */
1065 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1066 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1067 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
1069 /* What happens if a non-bound shader is deleted? */
1070 hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader);
1071 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1072 hr = IDirect3DDevice8_CreatePixelShader(pDevice, simple_ps, &hPixelShader2);
1073 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
1075 hr = IDirect3DDevice8_SetPixelShader(pDevice, hPixelShader);
1076 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
1077 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1078 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1079 hr = IDirect3DDevice8_GetPixelShader(pDevice, &hTempHandle);
1080 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
1081 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
1082 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1083 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1085 /* Check for double delete. */
1086 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader2);
1087 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1088 hr = IDirect3DDevice8_DeletePixelShader(pDevice, hPixelShader);
1089 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
1091 else
1093 skip("Pixel shaders not supported\n");
1096 /* What happens if a non-bound shader is deleted? */
1097 hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader, 0);
1098 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1099 hr = IDirect3DDevice8_CreateVertexShader(pDevice, dwVertexDecl, NULL, &hVertexShader2, 0);
1100 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1102 hr = IDirect3DDevice8_SetVertexShader(pDevice, hVertexShader);
1103 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1104 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1105 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1106 hr = IDirect3DDevice8_GetVertexShader(pDevice, &hTempHandle);
1107 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1108 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1109 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1110 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1112 /* Check for double delete. */
1113 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader2);
1114 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1115 hr = IDirect3DDevice8_DeleteVertexShader(pDevice, hVertexShader);
1116 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
1118 cleanup:
1119 if (pDevice)
1121 UINT refcount = IDirect3DDevice8_Release(pDevice);
1122 ok(!refcount, "Device has %u references left.\n", refcount);
1124 if (pD3d) IDirect3D8_Release(pD3d);
1125 if(hwnd) DestroyWindow(hwnd);
1128 static void test_limits(void)
1130 HRESULT hr;
1131 HWND hwnd = NULL;
1132 IDirect3D8 *pD3d = NULL;
1133 IDirect3DDevice8 *pDevice = NULL;
1134 D3DPRESENT_PARAMETERS d3dpp;
1135 D3DDISPLAYMODE d3ddm;
1136 IDirect3DTexture8 *pTexture = NULL;
1137 int i;
1139 pD3d = pDirect3DCreate8( D3D_SDK_VERSION );
1140 ok(pD3d != NULL, "Failed to create IDirect3D8 object\n");
1141 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1142 ok(hwnd != NULL, "Failed to create window\n");
1143 if (!pD3d || !hwnd) goto cleanup;
1145 IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1146 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1147 d3dpp.Windowed = TRUE;
1148 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1149 d3dpp.BackBufferWidth = 800;
1150 d3dpp.BackBufferHeight = 600;
1151 d3dpp.BackBufferFormat = d3ddm.Format;
1152 d3dpp.EnableAutoDepthStencil = TRUE;
1153 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1155 hr = IDirect3D8_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1156 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1157 ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D8_CreateDevice failed with %#08x\n", hr);
1158 if(!pDevice)
1160 skip("could not create device, IDirect3D8_CreateDevice returned %#08x\n", hr);
1161 goto cleanup;
1164 hr = IDirect3DDevice8_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture);
1165 ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
1166 if(!pTexture) goto cleanup;
1168 /* There are 8 texture stages. We should be able to access all of them */
1169 for(i = 0; i < 8; i++) {
1170 hr = IDirect3DDevice8_SetTexture(pDevice, i, (IDirect3DBaseTexture8 *) pTexture);
1171 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1172 hr = IDirect3DDevice8_SetTexture(pDevice, i, NULL);
1173 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
1174 hr = IDirect3DDevice8_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1175 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
1178 /* Investigations show that accessing higher textures stage states does not return an error either. Writing
1179 * to too high texture stages(approximately texture 40) causes memory corruption in windows, so there is no
1180 * bounds checking but how do I test that?
1183 cleanup:
1184 if(pTexture) IDirect3DTexture8_Release(pTexture);
1185 if (pDevice)
1187 UINT refcount = IDirect3DDevice8_Release(pDevice);
1188 ok(!refcount, "Device has %u references left.\n", refcount);
1190 if (pD3d) IDirect3D8_Release(pD3d);
1191 if(hwnd) DestroyWindow(hwnd);
1194 static void test_lights(void)
1196 D3DPRESENT_PARAMETERS d3dpp;
1197 IDirect3DDevice8 *device = NULL;
1198 IDirect3D8 *d3d8;
1199 HWND hwnd;
1200 HRESULT hr;
1201 unsigned int i;
1202 BOOL enabled;
1203 D3DCAPS8 caps;
1204 D3DDISPLAYMODE d3ddm;
1206 d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1207 ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1208 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1209 ok(hwnd != NULL, "Failed to create window\n");
1210 if (!d3d8 || !hwnd) goto cleanup;
1212 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1213 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1214 d3dpp.Windowed = TRUE;
1215 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1216 d3dpp.BackBufferWidth = 800;
1217 d3dpp.BackBufferHeight = 600;
1218 d3dpp.BackBufferFormat = d3ddm.Format;
1219 d3dpp.EnableAutoDepthStencil = TRUE;
1220 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1222 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1223 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
1224 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1225 "IDirect3D8_CreateDevice failed with %08x\n", hr);
1226 if(!device)
1228 skip("Failed to create a d3d device\n");
1229 goto cleanup;
1232 memset(&caps, 0, sizeof(caps));
1233 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1234 ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
1236 for(i = 1; i <= caps.MaxActiveLights; i++) {
1237 hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
1238 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
1239 hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
1240 ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
1241 "GetLightEnable on light %u failed with %08x\n", i, hr);
1242 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
1245 /* TODO: Test the rendering results in this situation */
1246 hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
1247 ok(hr == D3D_OK ||
1248 broken(hr == D3DERR_INVALIDCALL), /* Some Win9x and WinME */
1249 "Enabling one light more than supported returned %08x\n", hr);
1250 hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
1251 ok(hr == D3D_OK ||
1252 broken(hr == D3DERR_INVALIDCALL), /* Some Win9x and WinME */
1253 "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
1254 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
1255 hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
1256 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
1258 for(i = 1; i <= caps.MaxActiveLights; i++) {
1259 hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
1260 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
1263 cleanup:
1264 if (device)
1266 UINT refcount = IDirect3DDevice8_Release(device);
1267 ok(!refcount, "Device has %u references left.\n", refcount);
1269 if (d3d8) IDirect3D8_Release(d3d8);
1272 static void test_render_zero_triangles(void)
1274 D3DPRESENT_PARAMETERS d3dpp;
1275 IDirect3DDevice8 *device = NULL;
1276 IDirect3D8 *d3d8;
1277 HWND hwnd;
1278 HRESULT hr;
1279 D3DDISPLAYMODE d3ddm;
1281 struct nvertex
1283 float x, y, z;
1284 float nx, ny, nz;
1285 DWORD diffuse;
1286 } quad[] =
1288 { 0.0f, -1.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1289 { 0.0f, 0.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1290 { 1.0f, 0.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1291 { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0xff0000ff},
1294 d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1295 ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1296 hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1297 ok(hwnd != NULL, "Failed to create window\n");
1298 if (!d3d8 || !hwnd) goto cleanup;
1300 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
1301 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1302 d3dpp.Windowed = TRUE;
1303 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1304 d3dpp.BackBufferWidth = 800;
1305 d3dpp.BackBufferHeight = 600;
1306 d3dpp.BackBufferFormat = d3ddm.Format;
1307 d3dpp.EnableAutoDepthStencil = TRUE;
1308 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1310 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1311 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
1312 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
1313 "IDirect3D8_CreateDevice failed with %08x\n", hr);
1314 if(!device)
1316 skip("Failed to create a d3d device\n");
1317 goto cleanup;
1320 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1321 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1323 hr = IDirect3DDevice8_BeginScene(device);
1324 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1325 if(hr == D3D_OK)
1327 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
1328 0 /*PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
1329 ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
1331 IDirect3DDevice8_EndScene(device);
1332 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1335 IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1337 cleanup:
1338 if (device)
1340 UINT refcount = IDirect3DDevice8_Release(device);
1341 ok(!refcount, "Device has %u references left.\n", refcount);
1343 if (d3d8) IDirect3D8_Release(d3d8);
1346 static void test_depth_stencil_reset(void)
1348 D3DPRESENT_PARAMETERS present_parameters;
1349 D3DDISPLAYMODE display_mode;
1350 IDirect3DSurface8 *surface;
1351 IDirect3DDevice8 *device = NULL;
1352 IDirect3D8 *d3d8;
1353 UINT refcount;
1354 HRESULT hr;
1355 HWND hwnd;
1357 d3d8 = pDirect3DCreate8(D3D_SDK_VERSION);
1358 ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
1359 hwnd = CreateWindow("static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1360 ok(hwnd != NULL, "Failed to create window\n");
1361 if (!d3d8 || !hwnd) goto cleanup;
1363 IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
1364 memset(&present_parameters, 0, sizeof(present_parameters));
1365 present_parameters.Windowed = TRUE;
1366 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1367 present_parameters.BackBufferFormat = display_mode.Format;
1368 present_parameters.EnableAutoDepthStencil = TRUE;
1369 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1371 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
1372 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1373 if(FAILED(hr))
1375 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
1376 goto cleanup;
1379 hr = IDirect3DDevice8_TestCooperativeLevel(device);
1380 ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
1382 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
1383 ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
1385 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
1386 ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
1387 ok(surface != NULL, "Render target should not be NULL\n");
1388 if (surface) IDirect3DSurface8_Release(surface);
1390 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1391 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1392 ok(surface == NULL, "Depth stencil should be NULL\n");
1394 present_parameters.EnableAutoDepthStencil = TRUE;
1395 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1396 hr = IDirect3DDevice8_Reset(device, &present_parameters);
1397 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
1399 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1400 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1401 ok(surface != NULL, "Depth stencil should not be NULL\n");
1402 if (surface) IDirect3DSurface8_Release(surface);
1404 present_parameters.EnableAutoDepthStencil = FALSE;
1405 hr = IDirect3DDevice8_Reset(device, &present_parameters);
1406 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
1408 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1409 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1410 ok(surface == NULL, "Depth stencil should be NULL\n");
1412 refcount = IDirect3DDevice8_Release(device);
1413 ok(!refcount, "Device has %u references left.\n", refcount);
1414 device = NULL;
1416 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
1418 ZeroMemory( &present_parameters, sizeof(present_parameters) );
1419 present_parameters.Windowed = TRUE;
1420 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1421 present_parameters.BackBufferFormat = display_mode.Format;
1422 present_parameters.EnableAutoDepthStencil = FALSE;
1423 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1425 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
1426 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
1428 if(FAILED(hr))
1430 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
1431 goto cleanup;
1434 hr = IDirect3DDevice8_TestCooperativeLevel(device);
1435 ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
1437 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1438 present_parameters.Windowed = TRUE;
1439 present_parameters.BackBufferWidth = 400;
1440 present_parameters.BackBufferHeight = 300;
1441 present_parameters.EnableAutoDepthStencil = TRUE;
1442 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
1444 hr = IDirect3DDevice8_Reset(device, &present_parameters);
1445 ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
1447 if (FAILED(hr)) goto cleanup;
1449 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
1450 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1451 ok(surface != NULL, "Depth stencil should not be NULL\n");
1452 if (surface) IDirect3DSurface8_Release(surface);
1454 cleanup:
1455 if (device)
1457 refcount = IDirect3DDevice8_Release(device);
1458 ok(!refcount, "Device has %u references left.\n", refcount);
1460 if (d3d8) IDirect3D8_Release(d3d8);
1463 START_TEST(device)
1465 HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
1466 if (!d3d8_handle)
1468 skip("Could not load d3d8.dll\n");
1469 return;
1472 pDirect3DCreate8 = (void *)GetProcAddress( d3d8_handle, "Direct3DCreate8" );
1473 ok(pDirect3DCreate8 != NULL, "Failed to get address of Direct3DCreate8\n");
1474 if (pDirect3DCreate8)
1476 IDirect3D8 *d3d8;
1477 d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
1478 if(!d3d8)
1480 skip("could not create D3D8\n");
1481 return;
1483 IDirect3D8_Release(d3d8);
1485 test_display_modes();
1486 test_shader_versions();
1487 test_swapchain();
1488 test_refcount();
1489 test_mipmap_levels();
1490 test_cursor();
1491 test_states();
1492 test_scene();
1493 test_shader();
1494 test_limits();
1495 test_lights();
1496 test_render_zero_triangles();
1497 test_depth_stencil_reset();