d3d9: Update locked_rect only if wined3d_surface_map succeeds.
[wine.git] / dlls / d3d9 / tests / device.c
blob37fb8fe65645182862ea25e1bc608cf6cef5af98
1 /*
2 * Copyright (C) 2006 Vitaliy Margolen
3 * Copyright (C) 2006 Chris Robinson
4 * Copyright 2006-2008, 2010-2011, 2013 Stefan Dösinger for CodeWeavers
5 * Copyright 2005, 2006, 2007 Henri Verbeet
6 * Copyright 2013 Henri Verbeet for CodeWeavers
7 * Copyright (C) 2008 Rico Schüller
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define COBJMACROS
25 #include <windowsx.h>
26 #include <d3d9.h>
27 #include "wine/test.h"
29 static INT screen_width;
30 static INT screen_height;
32 static IDirect3D9 *(WINAPI *pDirect3DCreate9)(UINT);
34 static const DWORD simple_vs[] =
36 0xfffe0101, /* vs_1_1 */
37 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
38 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
39 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
40 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
41 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
42 0x0000ffff, /* end */
45 static const DWORD simple_ps[] =
47 0xffff0101, /* ps_1_1 */
48 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
49 0x00000042, 0xb00f0000, /* tex t0 */
50 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
51 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
52 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
53 0x0000ffff, /* end */
56 static int get_refcount(IUnknown *object)
58 IUnknown_AddRef( object );
59 return IUnknown_Release( object );
62 /* try to make sure pending X events have been processed before continuing */
63 static void flush_events(void)
65 MSG msg;
66 int diff = 200;
67 int min_timeout = 100;
68 DWORD time = GetTickCount() + diff;
70 while (diff > 0)
72 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
73 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
74 diff = time - GetTickCount();
78 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND device_window, HWND focus_window, BOOL windowed)
80 D3DPRESENT_PARAMETERS present_parameters = {0};
81 IDirect3DDevice9 *device;
83 present_parameters.Windowed = windowed;
84 present_parameters.hDeviceWindow = device_window;
85 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
86 present_parameters.BackBufferWidth = screen_width;
87 present_parameters.BackBufferHeight = screen_height;
88 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
89 present_parameters.EnableAutoDepthStencil = TRUE;
90 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
92 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
93 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
95 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
96 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
97 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
99 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
100 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device))) return device;
102 return NULL;
105 static HRESULT reset_device(IDirect3DDevice9 *device, HWND device_window, BOOL windowed)
107 D3DPRESENT_PARAMETERS present_parameters = {0};
109 present_parameters.Windowed = windowed;
110 present_parameters.hDeviceWindow = device_window;
111 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
112 present_parameters.BackBufferWidth = screen_width;
113 present_parameters.BackBufferHeight = screen_height;
114 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
115 present_parameters.EnableAutoDepthStencil = TRUE;
116 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
118 return IDirect3DDevice9_Reset(device, &present_parameters);
121 #define CHECK_CALL(r,c,d,rc) \
122 if (SUCCEEDED(r)) {\
123 int tmp1 = get_refcount( (IUnknown *)d ); \
124 int rc_new = rc; \
125 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
126 } else {\
127 trace("%s failed: %08x\n", c, r); \
130 #define CHECK_RELEASE(obj,d,rc) \
131 if (obj) { \
132 int tmp1, rc_new = rc; \
133 IUnknown_Release( (IUnknown*)obj ); \
134 tmp1 = get_refcount( (IUnknown *)d ); \
135 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
138 #define CHECK_REFCOUNT(obj,rc) \
140 int rc_new = rc; \
141 int count = get_refcount( (IUnknown *)obj ); \
142 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
145 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
147 int rc_new = rc; \
148 int count = IUnknown_Release( (IUnknown *)obj ); \
149 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
152 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
154 int rc_new = rc; \
155 int count = IUnknown_AddRef( (IUnknown *)obj ); \
156 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
159 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
161 void *container_ptr = (void *)0x1337c0d3; \
162 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
163 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
164 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
165 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
168 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
170 IDirect3DBaseTexture9* texture = NULL;
171 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
172 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
174 if (SUCCEEDED(hr)) {
175 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
176 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
177 } else
178 trace("CreateTexture failed: %08x\n", hr);
180 if (texture) IDirect3DBaseTexture9_Release( texture );
183 static void test_mipmap_levels(void)
186 HRESULT hr;
187 HWND hwnd = NULL;
189 IDirect3D9 *pD3d = NULL;
190 IDirect3DDevice9 *pDevice = NULL;
191 D3DPRESENT_PARAMETERS d3dpp;
192 D3DDISPLAYMODE d3ddm;
194 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
195 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
196 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
197 ok(hwnd != NULL, "Failed to create window\n");
198 if (!pD3d || !hwnd) goto cleanup;
200 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
201 ZeroMemory( &d3dpp, sizeof(d3dpp) );
202 d3dpp.Windowed = TRUE;
203 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
204 d3dpp.BackBufferFormat = d3ddm.Format;
206 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
207 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
208 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
209 if (FAILED(hr)) {
210 skip("failed to create a d3d device\n");
211 goto cleanup;
214 check_mipmap_levels(pDevice, 32, 32, 6);
215 check_mipmap_levels(pDevice, 256, 1, 9);
216 check_mipmap_levels(pDevice, 1, 256, 9);
217 check_mipmap_levels(pDevice, 1, 1, 1);
219 cleanup:
220 if (pDevice)
222 UINT refcount = IDirect3DDevice9_Release( pDevice );
223 ok(!refcount, "Device has %u references left.\n", refcount);
225 if (pD3d) IDirect3D9_Release( pD3d );
226 DestroyWindow( hwnd );
229 static void test_checkdevicemultisampletype(void)
232 HRESULT hr;
233 HWND hwnd = NULL;
235 IDirect3D9 *pD3d = NULL;
236 IDirect3DDevice9 *pDevice = NULL;
237 D3DPRESENT_PARAMETERS d3dpp;
238 D3DDISPLAYMODE d3ddm;
239 DWORD qualityLevels;
241 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
242 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
243 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
244 ok(hwnd != NULL, "Failed to create window\n");
245 if (!pD3d || !hwnd) goto cleanup;
247 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
248 ZeroMemory( &d3dpp, sizeof(d3dpp) );
249 d3dpp.Windowed = TRUE;
250 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
251 d3dpp.BackBufferFormat = d3ddm.Format;
253 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
254 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
255 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
256 if (FAILED(hr)) {
257 skip("failed to create a d3d device\n");
258 goto cleanup;
261 qualityLevels = 0;
263 hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE,
264 D3DMULTISAMPLE_NONE, &qualityLevels);
265 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
266 if(hr == D3DERR_NOTAVAILABLE)
268 skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
269 goto cleanup;
271 ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
273 hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, FALSE,
274 D3DMULTISAMPLE_NONE, &qualityLevels);
275 ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
276 ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
278 cleanup:
279 if (pDevice)
281 UINT refcount = IDirect3DDevice9_Release( pDevice );
282 ok(!refcount, "Device has %u references left.\n", refcount);
284 if (pD3d) IDirect3D9_Release( pD3d );
285 DestroyWindow( hwnd );
288 static void test_swapchain(void)
290 HRESULT hr;
291 HWND hwnd = NULL;
292 IDirect3D9 *pD3d = NULL;
293 IDirect3DDevice9 *pDevice = NULL;
294 IDirect3DSwapChain9 *swapchain0 = NULL;
295 IDirect3DSwapChain9 *swapchain1 = NULL;
296 IDirect3DSwapChain9 *swapchain2 = NULL;
297 IDirect3DSwapChain9 *swapchain3 = NULL;
298 IDirect3DSwapChain9 *swapchainX = NULL;
299 IDirect3DSurface9 *backbuffer = NULL;
300 D3DPRESENT_PARAMETERS d3dpp;
301 D3DDISPLAYMODE d3ddm;
303 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
304 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
305 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
306 ok(hwnd != NULL, "Failed to create window\n");
307 if (!pD3d || !hwnd) goto cleanup;
309 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
310 ZeroMemory( &d3dpp, sizeof(d3dpp) );
311 d3dpp.Windowed = TRUE;
312 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
313 d3dpp.BackBufferFormat = d3ddm.Format;
314 d3dpp.BackBufferCount = 0;
316 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
317 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
318 ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
319 "Failed to create IDirect3D9Device (%08x)\n", hr);
320 if (FAILED(hr)) goto cleanup;
322 /* Check if the back buffer count was modified */
323 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
325 /* Get the implicit swapchain */
326 hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &swapchain0);
327 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
328 if(swapchain0) IDirect3DSwapChain9_Release(swapchain0);
330 /* Check if there is a back buffer */
331 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
332 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
333 ok(backbuffer != NULL, "The back buffer is NULL\n");
334 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
336 /* Try to get a nonexistent swapchain */
337 hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
338 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
339 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
340 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
342 /* Create a bunch of swapchains */
343 d3dpp.BackBufferCount = 0;
344 hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
345 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
346 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
348 d3dpp.BackBufferCount = 1;
349 hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
350 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
352 d3dpp.BackBufferCount = 2;
353 hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
354 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
355 if(SUCCEEDED(hr)) {
356 /* Swapchain 3, created with backbuffercount 2 */
357 backbuffer = (void *) 0xdeadbeef;
358 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
359 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
360 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
361 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
363 backbuffer = (void *) 0xdeadbeef;
364 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
365 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
366 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
367 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
369 backbuffer = (void *) 0xdeadbeef;
370 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
371 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
372 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
373 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
375 backbuffer = (void *) 0xdeadbeef;
376 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
377 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
378 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
379 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
382 /* Check the back buffers of the swapchains */
383 /* Swapchain 1, created with backbuffercount 0 */
384 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
385 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
386 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
387 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
389 backbuffer = (void *) 0xdeadbeef;
390 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
391 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
392 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
393 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
395 /* Swapchain 2 - created with backbuffercount 1 */
396 backbuffer = (void *) 0xdeadbeef;
397 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
398 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
399 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
400 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
402 backbuffer = (void *) 0xdeadbeef;
403 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
404 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
405 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
406 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
408 backbuffer = (void *) 0xdeadbeef;
409 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
410 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
411 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
412 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
414 /* Try getSwapChain on a manually created swapchain
415 * it should fail, apparently GetSwapChain only returns implicit swapchains
417 swapchainX = (void *) 0xdeadbeef;
418 hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
419 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
420 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
421 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
423 cleanup:
424 if(swapchain1) IDirect3DSwapChain9_Release(swapchain1);
425 if(swapchain2) IDirect3DSwapChain9_Release(swapchain2);
426 if(swapchain3) IDirect3DSwapChain9_Release(swapchain3);
427 if (pDevice)
429 UINT refcount = IDirect3DDevice9_Release(pDevice);
430 ok(!refcount, "Device has %u references left.\n", refcount);
432 if (pD3d) IDirect3D9_Release(pD3d);
433 DestroyWindow( hwnd );
436 static void test_refcount(void)
438 HRESULT hr;
439 HWND hwnd = NULL;
440 IDirect3D9 *pD3d = NULL;
441 IDirect3D9 *pD3d2 = NULL;
442 IDirect3DDevice9 *pDevice = NULL;
443 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
444 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
445 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
446 IDirect3DVertexShader9 *pVertexShader = NULL;
447 IDirect3DPixelShader9 *pPixelShader = NULL;
448 IDirect3DCubeTexture9 *pCubeTexture = NULL;
449 IDirect3DTexture9 *pTexture = NULL;
450 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
451 IDirect3DVolume9 *pVolumeLevel = NULL;
452 IDirect3DSurface9 *pStencilSurface = NULL;
453 IDirect3DSurface9 *pOffscreenSurface = NULL;
454 IDirect3DSurface9 *pRenderTarget = NULL;
455 IDirect3DSurface9 *pRenderTarget2 = NULL;
456 IDirect3DSurface9 *pRenderTarget3 = NULL;
457 IDirect3DSurface9 *pTextureLevel = NULL;
458 IDirect3DSurface9 *pBackBuffer = NULL;
459 IDirect3DStateBlock9 *pStateBlock = NULL;
460 IDirect3DStateBlock9 *pStateBlock1 = NULL;
461 IDirect3DSwapChain9 *pSwapChain = NULL;
462 IDirect3DQuery9 *pQuery = NULL;
463 D3DPRESENT_PARAMETERS d3dpp;
464 D3DDISPLAYMODE d3ddm;
465 int refcount = 0, tmp;
467 D3DVERTEXELEMENT9 decl[] =
469 D3DDECL_END()
472 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
473 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
474 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
475 ok(hwnd != NULL, "Failed to create window\n");
476 if (!pD3d || !hwnd) goto cleanup;
478 CHECK_REFCOUNT( pD3d, 1 );
480 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
481 ZeroMemory( &d3dpp, sizeof(d3dpp) );
482 d3dpp.Windowed = TRUE;
483 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
484 d3dpp.BackBufferFormat = d3ddm.Format;
485 d3dpp.EnableAutoDepthStencil = TRUE;
486 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
488 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
489 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
490 ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
491 "Failed to create IDirect3D9Device (%08x)\n", hr);
492 if (FAILED(hr)) goto cleanup;
494 refcount = get_refcount( (IUnknown *)pDevice );
495 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
497 CHECK_REFCOUNT( pD3d, 2 );
499 hr = IDirect3DDevice9_GetDirect3D(pDevice, &pD3d2);
500 CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
502 ok(pD3d2 == pD3d, "Expected IDirect3D9 pointers to be equal\n");
503 CHECK_REFCOUNT( pD3d, 3 );
504 CHECK_RELEASE_REFCOUNT( pD3d, 2 );
507 * Check refcount of implicit surfaces and implicit swapchain. Findings:
508 * - the container is the device OR swapchain
509 * - they hold a reference to the device
510 * - they are created with a refcount of 0 (Get/Release returns original refcount)
511 * - they are not freed if refcount reaches 0.
512 * - the refcount is not forwarded to the container.
514 hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
515 CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
516 if (pSwapChain)
518 CHECK_REFCOUNT( pSwapChain, 1);
520 hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
521 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
522 CHECK_REFCOUNT( pSwapChain, 1);
523 if(pRenderTarget)
525 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
526 CHECK_REFCOUNT( pRenderTarget, 1);
528 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
529 CHECK_REFCOUNT(pDevice, refcount);
530 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
531 CHECK_REFCOUNT(pDevice, refcount);
533 hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
534 CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
535 CHECK_REFCOUNT( pRenderTarget, 2);
536 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
537 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
538 CHECK_REFCOUNT( pDevice, --refcount);
540 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
541 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
542 CHECK_REFCOUNT(pDevice, ++refcount);
543 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
544 CHECK_REFCOUNT(pDevice, --refcount);
547 /* Render target and back buffer are identical. */
548 hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
549 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
550 if(pBackBuffer)
552 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
553 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
554 pRenderTarget, pBackBuffer);
555 pBackBuffer = NULL;
557 CHECK_REFCOUNT( pDevice, --refcount);
559 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
560 CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
561 CHECK_REFCOUNT( pSwapChain, 1);
562 if(pStencilSurface)
564 CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
565 CHECK_REFCOUNT( pStencilSurface, 1);
567 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
568 CHECK_REFCOUNT(pDevice, refcount);
569 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
570 CHECK_REFCOUNT(pDevice, refcount);
572 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
573 CHECK_REFCOUNT( pDevice, --refcount);
575 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
576 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
577 CHECK_REFCOUNT(pDevice, ++refcount);
578 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
579 CHECK_REFCOUNT(pDevice, --refcount);
580 pStencilSurface = NULL;
583 CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
584 CHECK_REFCOUNT( pDevice, --refcount);
586 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
587 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
588 CHECK_REFCOUNT(pDevice, ++refcount);
589 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
590 CHECK_REFCOUNT(pDevice, --refcount);
591 pSwapChain = NULL;
594 /* Buffers */
595 hr = IDirect3DDevice9_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL );
596 CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
597 if(pIndexBuffer)
599 tmp = get_refcount( (IUnknown *)pIndexBuffer );
601 hr = IDirect3DDevice9_SetIndices(pDevice, pIndexBuffer);
602 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
603 hr = IDirect3DDevice9_SetIndices(pDevice, NULL);
604 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
607 hr = IDirect3DDevice9_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
608 CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
609 if(pVertexBuffer)
611 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
612 UINT offset = ~0;
613 UINT stride = ~0;
615 tmp = get_refcount( (IUnknown *)pVertexBuffer );
617 hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, pVertexBuffer, 0, 3 * sizeof(float));
618 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
619 hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, NULL, 0, 0);
620 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
622 hr = IDirect3DDevice9_GetStreamSource(pDevice, 0, &pVBuf, &offset, &stride);
623 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
624 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
625 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
626 ok(offset==0, "offset not 0 (got %u)!\n", offset);
628 /* Shaders */
629 hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, decl, &pVertexDeclaration );
630 CHECK_CALL( hr, "CreateVertexDeclaration", pDevice, ++refcount );
631 hr = IDirect3DDevice9_CreateVertexShader( pDevice, simple_vs, &pVertexShader );
632 CHECK_CALL( hr, "CreateVertexShader", pDevice, ++refcount );
633 hr = IDirect3DDevice9_CreatePixelShader( pDevice, simple_ps, &pPixelShader );
634 CHECK_CALL( hr, "CreatePixelShader", pDevice, ++refcount );
635 /* Textures */
636 hr = IDirect3DDevice9_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL );
637 CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
638 if (pTexture)
640 tmp = get_refcount( (IUnknown *)pTexture );
642 /* SetTexture should not increase refcounts */
643 hr = IDirect3DDevice9_SetTexture(pDevice, 0, (IDirect3DBaseTexture9 *) pTexture);
644 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
645 hr = IDirect3DDevice9_SetTexture(pDevice, 0, NULL);
646 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
648 /* This should not increment device refcount */
649 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
650 CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
651 /* But should increment texture's refcount */
652 CHECK_REFCOUNT( pTexture, tmp+1 );
653 /* Because the texture and surface refcount are identical */
654 if (pTextureLevel)
656 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
657 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
658 CHECK_REFCOUNT ( pTexture , tmp+2 );
659 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
660 CHECK_REFCOUNT ( pTexture , tmp+1 );
661 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
662 CHECK_REFCOUNT ( pTextureLevel, tmp );
665 hr = IDirect3DDevice9_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL );
666 CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
667 hr = IDirect3DDevice9_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL );
668 CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
669 if (pVolumeTexture)
671 tmp = get_refcount( (IUnknown *)pVolumeTexture );
673 /* This should not increment device refcount */
674 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
675 CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
676 /* But should increment volume texture's refcount */
677 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
678 /* Because the volume texture and volume refcount are identical */
679 if (pVolumeLevel)
681 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
682 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
683 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
684 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
685 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
686 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
687 CHECK_REFCOUNT ( pVolumeLevel , tmp );
690 /* Surfaces */
691 hr = IDirect3DDevice9_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL );
692 CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
693 CHECK_REFCOUNT( pStencilSurface, 1 );
694 hr = IDirect3DDevice9_CreateOffscreenPlainSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL );
695 CHECK_CALL( hr, "CreateOffscreenPlainSurface", pDevice, ++refcount );
696 CHECK_REFCOUNT( pOffscreenSurface, 1 );
697 hr = IDirect3DDevice9_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL );
698 CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
699 CHECK_REFCOUNT( pRenderTarget3, 1 );
700 /* Misc */
701 hr = IDirect3DDevice9_CreateStateBlock( pDevice, D3DSBT_ALL, &pStateBlock );
702 CHECK_CALL( hr, "CreateStateBlock", pDevice, ++refcount );
703 hr = IDirect3DDevice9_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
704 CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
705 if(pSwapChain)
707 /* check implicit back buffer */
708 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
709 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
710 CHECK_REFCOUNT( pSwapChain, 1);
711 if(pBackBuffer)
713 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
714 CHECK_REFCOUNT( pBackBuffer, 1);
715 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
716 CHECK_REFCOUNT( pDevice, --refcount);
718 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
719 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
720 CHECK_REFCOUNT(pDevice, ++refcount);
721 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
722 CHECK_REFCOUNT(pDevice, --refcount);
723 pBackBuffer = NULL;
725 CHECK_REFCOUNT( pSwapChain, 1);
727 hr = IDirect3DDevice9_CreateQuery( pDevice, D3DQUERYTYPE_EVENT, &pQuery );
728 CHECK_CALL( hr, "CreateQuery", pDevice, ++refcount );
730 hr = IDirect3DDevice9_BeginStateBlock( pDevice );
731 CHECK_CALL( hr, "BeginStateBlock", pDevice, refcount );
732 hr = IDirect3DDevice9_EndStateBlock( pDevice, &pStateBlock1 );
733 CHECK_CALL( hr, "EndStateBlock", pDevice, ++refcount );
735 /* The implicit render target is not freed if refcount reaches 0.
736 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
737 hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget2);
738 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
739 if(pRenderTarget2)
741 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
742 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
743 pRenderTarget, pRenderTarget2);
744 CHECK_REFCOUNT( pDevice, --refcount);
745 pRenderTarget2 = NULL;
747 pRenderTarget = NULL;
749 cleanup:
750 CHECK_RELEASE(pDevice, pDevice, --refcount);
752 /* Buffers */
753 CHECK_RELEASE(pVertexBuffer, pDevice, --refcount);
754 CHECK_RELEASE(pIndexBuffer, pDevice, --refcount);
755 /* Shaders */
756 CHECK_RELEASE(pVertexDeclaration, pDevice, --refcount);
757 CHECK_RELEASE(pVertexShader, pDevice, --refcount);
758 CHECK_RELEASE(pPixelShader, pDevice, --refcount);
759 /* Textures */
760 CHECK_RELEASE(pTextureLevel, pDevice, --refcount);
761 CHECK_RELEASE(pCubeTexture, pDevice, --refcount);
762 CHECK_RELEASE(pVolumeTexture, pDevice, --refcount);
763 /* Surfaces */
764 CHECK_RELEASE(pStencilSurface, pDevice, --refcount);
765 CHECK_RELEASE(pOffscreenSurface, pDevice, --refcount);
766 CHECK_RELEASE(pRenderTarget3, pDevice, --refcount);
767 /* Misc */
768 CHECK_RELEASE(pStateBlock, pDevice, --refcount);
769 CHECK_RELEASE(pSwapChain, pDevice, --refcount);
770 CHECK_RELEASE(pQuery, pDevice, --refcount);
771 /* This will destroy device - cannot check the refcount here */
772 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
774 if (pD3d) CHECK_RELEASE_REFCOUNT( pD3d, 0);
776 DestroyWindow( hwnd );
779 static void test_cursor(void)
781 HRESULT hr;
782 HWND hwnd = NULL;
783 IDirect3D9 *pD3d = NULL;
784 IDirect3DDevice9 *pDevice = NULL;
785 D3DPRESENT_PARAMETERS d3dpp;
786 D3DDISPLAYMODE d3ddm;
787 CURSORINFO info;
788 IDirect3DSurface9 *cursor = NULL;
789 HCURSOR cur;
791 memset(&info, 0, sizeof(info));
792 info.cbSize = sizeof(info);
793 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
794 cur = info.hCursor;
796 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
797 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
798 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
799 ok(hwnd != NULL, "Failed to create window\n");
800 if (!pD3d || !hwnd) goto cleanup;
802 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
803 ZeroMemory( &d3dpp, sizeof(d3dpp) );
804 d3dpp.Windowed = TRUE;
805 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
806 d3dpp.BackBufferFormat = d3ddm.Format;
808 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
809 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
810 ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
811 "Failed to create IDirect3D9Device (%08x)\n", hr);
812 if (FAILED(hr)) goto cleanup;
814 IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, 0);
815 ok(cursor != NULL, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
817 /* Initially hidden */
818 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
819 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
821 /* Not enabled without a surface*/
822 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
823 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
825 /* Fails */
826 hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, NULL);
827 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
829 hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, cursor);
830 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
832 IDirect3DSurface9_Release(cursor);
834 memset(&info, 0, sizeof(info));
835 info.cbSize = sizeof(info);
836 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
837 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
838 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
840 /* Still hidden */
841 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
842 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
844 /* Enabled now*/
845 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
846 ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
848 /* GDI cursor unchanged */
849 memset(&info, 0, sizeof(info));
850 info.cbSize = sizeof(info);
851 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
852 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
853 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
855 cleanup:
856 if (pDevice)
858 UINT refcount = IDirect3DDevice9_Release(pDevice);
859 ok(!refcount, "Device has %u references left.\n", refcount);
861 if (pD3d) IDirect3D9_Release(pD3d);
862 DestroyWindow( hwnd );
865 static void test_reset(void)
867 HRESULT hr;
868 HWND hwnd = NULL;
869 RECT winrect;
870 IDirect3D9 *pD3d = NULL;
871 D3DPRESENT_PARAMETERS d3dpp;
872 D3DDISPLAYMODE d3ddm, d3ddm2;
873 D3DVIEWPORT9 vp;
874 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
875 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
876 IDirect3DSwapChain9 *pSwapchain;
877 IDirect3DSurface9 *surface;
878 IDirect3DTexture9 *texture;
879 IDirect3DVertexShader9 *shader;
880 UINT i, adapter_mode_count;
881 D3DLOCKED_RECT lockrect;
882 IDirect3DDevice9 *device1 = NULL;
883 IDirect3DDevice9 *device2 = NULL;
884 D3DCAPS9 caps;
885 DWORD value;
886 struct
888 UINT w;
889 UINT h;
890 } *modes = NULL;
891 UINT mode_count = 0;
893 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
894 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
895 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
896 ok(hwnd != NULL, "Failed to create window\n");
897 if (!pD3d || !hwnd) goto cleanup;
899 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
900 adapter_mode_count = IDirect3D9_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format);
901 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
902 for(i = 0; i < adapter_mode_count; ++i)
904 UINT j;
905 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
906 hr = IDirect3D9_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
907 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
909 for (j = 0; j < mode_count; ++j)
911 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
912 break;
914 if (j == mode_count)
916 modes[j].w = d3ddm2.Width;
917 modes[j].h = d3ddm2.Height;
918 ++mode_count;
921 /* We use them as invalid modes */
922 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
923 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
924 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
925 d3ddm2.Width, d3ddm2.Height);
926 goto cleanup;
930 if (mode_count < 2)
932 skip("Less than 2 modes supported, skipping mode tests\n");
933 goto cleanup;
936 i = 0;
937 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
939 ZeroMemory( &d3dpp, sizeof(d3dpp) );
940 d3dpp.Windowed = FALSE;
941 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
942 d3dpp.BackBufferWidth = modes[i].w;
943 d3dpp.BackBufferHeight = modes[i].h;
944 d3dpp.BackBufferFormat = d3ddm.Format;
945 d3dpp.EnableAutoDepthStencil = TRUE;
946 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
948 hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
949 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
950 if (FAILED(hr))
952 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
953 goto cleanup;
955 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
956 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
958 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
959 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
961 width = GetSystemMetrics(SM_CXSCREEN);
962 height = GetSystemMetrics(SM_CYSCREEN);
963 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
964 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
966 hr = IDirect3DDevice9_GetViewport(device1, &vp);
967 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
968 if(SUCCEEDED(hr))
970 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
971 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
972 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
973 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
974 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
975 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
978 i = 1;
979 vp.X = 10;
980 vp.Y = 20;
981 vp.MinZ = 2;
982 vp.MaxZ = 3;
983 hr = IDirect3DDevice9_SetViewport(device1, &vp);
984 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
986 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
987 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
988 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
989 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
990 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
992 ZeroMemory( &d3dpp, sizeof(d3dpp) );
993 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
994 d3dpp.Windowed = FALSE;
995 d3dpp.BackBufferWidth = modes[i].w;
996 d3dpp.BackBufferHeight = modes[i].h;
997 d3dpp.BackBufferFormat = d3ddm.Format;
998 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
999 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1000 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1001 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1003 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1004 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1005 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1007 ZeroMemory(&vp, sizeof(vp));
1008 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1009 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1010 if(SUCCEEDED(hr))
1012 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1013 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1014 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1015 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1016 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1017 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1020 width = GetSystemMetrics(SM_CXSCREEN);
1021 height = GetSystemMetrics(SM_CYSCREEN);
1022 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1023 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1025 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1026 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1027 if(SUCCEEDED(hr))
1029 ZeroMemory(&d3dpp, sizeof(d3dpp));
1030 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1031 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1032 if(SUCCEEDED(hr))
1034 ok(d3dpp.BackBufferWidth == modes[i].w, "Back buffer width is %u, expected %u\n",
1035 d3dpp.BackBufferWidth, modes[i].w);
1036 ok(d3dpp.BackBufferHeight == modes[i].h, "Back buffer height is %u, expected %u\n",
1037 d3dpp.BackBufferHeight, modes[i].h);
1039 IDirect3DSwapChain9_Release(pSwapchain);
1042 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1043 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1044 d3dpp.Windowed = TRUE;
1045 d3dpp.BackBufferWidth = 400;
1046 d3dpp.BackBufferHeight = 300;
1047 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1048 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1049 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1050 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1052 width = GetSystemMetrics(SM_CXSCREEN);
1053 height = GetSystemMetrics(SM_CYSCREEN);
1054 ok(width == orig_width, "Screen width is %d\n", width);
1055 ok(height == orig_height, "Screen height is %d\n", height);
1057 ZeroMemory(&vp, sizeof(vp));
1058 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1059 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1060 if(SUCCEEDED(hr))
1062 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1063 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1064 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1065 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1066 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1067 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1070 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1071 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1072 if(SUCCEEDED(hr))
1074 ZeroMemory(&d3dpp, sizeof(d3dpp));
1075 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1076 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1077 if(SUCCEEDED(hr))
1079 ok(d3dpp.BackBufferWidth == 400, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1080 ok(d3dpp.BackBufferHeight == 300, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1082 IDirect3DSwapChain9_Release(pSwapchain);
1085 winrect.left = 0;
1086 winrect.top = 0;
1087 winrect.right = 200;
1088 winrect.bottom = 150;
1089 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1090 ok(SetWindowPos(hwnd, NULL, 0, 0,
1091 winrect.right-winrect.left,
1092 winrect.bottom-winrect.top,
1093 SWP_NOMOVE|SWP_NOZORDER),
1094 "SetWindowPos failed\n");
1096 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1097 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1098 d3dpp.Windowed = TRUE;
1099 d3dpp.BackBufferWidth = 0;
1100 d3dpp.BackBufferHeight = 0;
1101 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1102 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1103 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1104 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1106 ZeroMemory(&vp, sizeof(vp));
1107 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1108 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1109 if(SUCCEEDED(hr))
1111 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1112 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1113 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
1114 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
1115 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1116 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1119 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1120 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1121 if(SUCCEEDED(hr))
1123 ZeroMemory(&d3dpp, sizeof(d3dpp));
1124 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1125 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1126 if(SUCCEEDED(hr))
1128 ok(d3dpp.BackBufferWidth == 200, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1129 ok(d3dpp.BackBufferHeight == 150, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1131 IDirect3DSwapChain9_Release(pSwapchain);
1134 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1135 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1136 d3dpp.Windowed = TRUE;
1137 d3dpp.BackBufferWidth = 400;
1138 d3dpp.BackBufferHeight = 300;
1140 /* _Reset fails if there is a resource in the default pool */
1141 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1142 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1143 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1144 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1145 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1146 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1147 IDirect3DSurface9_Release(surface);
1148 /* Reset again to get the device out of the lost state */
1149 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1150 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1151 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1152 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1154 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1156 IDirect3DVolumeTexture9 *volume_texture;
1158 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1159 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1160 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1161 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1162 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1163 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1164 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1165 hr, D3DERR_DEVICENOTRESET);
1166 IDirect3DVolumeTexture9_Release(volume_texture);
1167 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1168 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1169 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1170 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1172 else
1174 skip("Volume textures not supported.\n");
1177 /* Scratch, sysmem and managed pools are fine */
1178 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1179 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1180 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1181 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1182 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1183 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1184 IDirect3DSurface9_Release(surface);
1186 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1187 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1188 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1189 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1190 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1191 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1192 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1193 IDirect3DSurface9_Release(surface);
1195 /* The depth stencil should get reset to the auto depth stencil when present. */
1196 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
1197 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
1199 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1200 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1201 ok(surface == NULL, "Depth stencil should be NULL\n");
1203 d3dpp.EnableAutoDepthStencil = TRUE;
1204 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1205 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1206 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1208 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1209 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1210 ok(surface != NULL, "Depth stencil should not be NULL\n");
1211 if (surface) IDirect3DSurface9_Release(surface);
1213 d3dpp.EnableAutoDepthStencil = FALSE;
1214 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1215 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1217 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1218 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1219 ok(surface == NULL, "Depth stencil should be NULL\n");
1221 /* Will a sysmem or scratch survive while locked */
1222 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1223 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1224 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1225 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1226 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1227 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1228 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1229 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1230 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1231 IDirect3DSurface9_UnlockRect(surface);
1232 IDirect3DSurface9_Release(surface);
1234 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1235 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1236 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1237 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1238 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1239 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1240 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1241 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1242 IDirect3DSurface9_UnlockRect(surface);
1243 IDirect3DSurface9_Release(surface);
1245 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
1246 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
1247 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1248 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1249 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1250 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1251 IDirect3DTexture9_Release(texture);
1253 /* A reference held to an implicit surface causes failures as well */
1254 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1255 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
1256 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1257 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1258 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1259 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1260 IDirect3DSurface9_Release(surface);
1261 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1262 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1263 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1264 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1266 /* Shaders are fine as well */
1267 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
1268 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
1269 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1270 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1271 IDirect3DVertexShader9_Release(shader);
1273 /* Try setting invalid modes */
1274 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1275 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1276 d3dpp.Windowed = FALSE;
1277 d3dpp.BackBufferWidth = 32;
1278 d3dpp.BackBufferHeight = 32;
1279 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1280 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
1281 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1282 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1284 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1285 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1286 d3dpp.Windowed = FALSE;
1287 d3dpp.BackBufferWidth = 801;
1288 d3dpp.BackBufferHeight = 600;
1289 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1290 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
1291 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1292 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1294 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1295 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1296 d3dpp.Windowed = FALSE;
1297 d3dpp.BackBufferWidth = 0;
1298 d3dpp.BackBufferHeight = 0;
1299 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1300 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
1301 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1302 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1304 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1306 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1307 d3dpp.Windowed = TRUE;
1308 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1309 d3dpp.BackBufferFormat = d3ddm.Format;
1310 d3dpp.EnableAutoDepthStencil = FALSE;
1311 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1313 hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1314 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1315 if (FAILED(hr))
1317 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
1318 goto cleanup;
1321 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
1322 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1324 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1325 d3dpp.Windowed = TRUE;
1326 d3dpp.BackBufferWidth = 400;
1327 d3dpp.BackBufferHeight = 300;
1328 d3dpp.EnableAutoDepthStencil = TRUE;
1329 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1331 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
1332 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1334 if (FAILED(hr)) goto cleanup;
1336 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
1337 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1338 ok(surface != NULL, "Depth stencil should not be NULL\n");
1339 if (surface) IDirect3DSurface9_Release(surface);
1341 cleanup:
1342 HeapFree(GetProcessHeap(), 0, modes);
1343 if (device2)
1345 UINT refcount = IDirect3DDevice9_Release(device2);
1346 ok(!refcount, "Device has %u references left.\n", refcount);
1348 if (device1)
1350 UINT refcount = IDirect3DDevice9_Release(device1);
1351 ok(!refcount, "Device has %u references left.\n", refcount);
1353 if (pD3d) IDirect3D9_Release(pD3d);
1354 if (hwnd) DestroyWindow(hwnd);
1357 /* Test adapter display modes */
1358 static void test_display_modes(void)
1360 D3DDISPLAYMODE dmode;
1361 IDirect3D9 *pD3d;
1363 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1364 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1365 if(!pD3d) return;
1367 #define TEST_FMT(x,r) do { \
1368 HRESULT res = IDirect3D9_EnumAdapterModes(pD3d, 0, (x), 0, &dmode); \
1369 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
1370 } while(0)
1372 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
1373 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
1374 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1375 /* D3DFMT_R5G6B5 */
1376 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
1377 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
1378 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
1379 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
1380 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
1381 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
1382 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
1383 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
1384 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
1385 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1386 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
1387 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
1389 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
1390 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
1392 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
1393 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
1394 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
1396 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
1397 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
1398 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
1399 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
1400 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
1401 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
1403 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
1404 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
1405 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
1406 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
1407 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
1408 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
1409 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
1410 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
1411 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
1412 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
1414 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
1415 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
1416 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
1417 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
1418 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
1419 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
1420 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
1421 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
1422 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
1423 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
1425 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
1426 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
1427 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
1428 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
1429 /* Floating point formats */
1430 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
1431 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
1432 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
1434 /* IEEE formats */
1435 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
1436 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
1437 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
1439 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
1441 TEST_FMT(0, D3DERR_INVALIDCALL);
1443 IDirect3D9_Release(pD3d);
1446 static void test_scene(void)
1448 HRESULT hr;
1449 HWND hwnd = NULL;
1450 IDirect3D9 *pD3d = NULL;
1451 IDirect3DDevice9 *pDevice = NULL;
1452 D3DPRESENT_PARAMETERS d3dpp;
1453 D3DDISPLAYMODE d3ddm;
1454 IDirect3DSurface9 *pSurface1 = NULL, *pSurface2 = NULL, *pSurface3 = NULL, *pRenderTarget = NULL;
1455 IDirect3DSurface9 *pBackBuffer = NULL, *pDepthStencil = NULL;
1456 RECT rect = {0, 0, 128, 128};
1457 D3DCAPS9 caps;
1459 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1460 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1461 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1462 ok(hwnd != NULL, "Failed to create window\n");
1463 if (!pD3d || !hwnd) goto cleanup;
1465 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1466 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1467 d3dpp.Windowed = TRUE;
1468 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1469 d3dpp.BackBufferWidth = 800;
1470 d3dpp.BackBufferHeight = 600;
1471 d3dpp.BackBufferFormat = d3ddm.Format;
1472 d3dpp.EnableAutoDepthStencil = TRUE;
1473 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1475 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1476 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1477 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1478 if(!pDevice)
1480 skip("Failed to create a d3d device\n");
1481 goto cleanup;
1484 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
1485 memset(&caps, 0, sizeof(caps));
1486 hr = IDirect3DDevice9_GetDeviceCaps(pDevice, &caps);
1487 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
1488 if(FAILED(hr)) goto cleanup;
1490 /* Test an EndScene without BeginScene. Should return an error */
1491 hr = IDirect3DDevice9_EndScene(pDevice);
1492 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1494 /* Test a normal BeginScene / EndScene pair, this should work */
1495 hr = IDirect3DDevice9_BeginScene(pDevice);
1496 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1497 if(SUCCEEDED(hr))
1499 hr = IDirect3DDevice9_EndScene(pDevice);
1500 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1503 /* Test another EndScene without having begun a new scene. Should return an error */
1504 hr = IDirect3DDevice9_EndScene(pDevice);
1505 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1507 /* Two nested BeginScene and EndScene calls */
1508 hr = IDirect3DDevice9_BeginScene(pDevice);
1509 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1510 hr = IDirect3DDevice9_BeginScene(pDevice);
1511 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
1512 hr = IDirect3DDevice9_EndScene(pDevice);
1513 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1514 hr = IDirect3DDevice9_EndScene(pDevice);
1515 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1517 /* Create some surfaces to test stretchrect between the scenes */
1518 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface1, NULL);
1519 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1520 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface2, NULL);
1521 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1522 hr = IDirect3DDevice9_CreateDepthStencilSurface(pDevice, 800, 600, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface3, NULL);
1523 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
1524 hr = IDirect3DDevice9_CreateRenderTarget(pDevice, 128, 128, d3ddm.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pRenderTarget, NULL);
1525 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
1527 hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
1528 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1529 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1530 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1532 /* First make sure a simple StretchRect call works */
1533 if(pSurface1 && pSurface2) {
1534 hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1535 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1537 if(pBackBuffer && pRenderTarget) {
1538 hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1539 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1541 if(pDepthStencil && pSurface3) {
1542 HRESULT expected;
1543 if(0) /* Disabled for now because it crashes in wine */ {
1544 expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
1545 hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1546 ok( hr == expected, "IDirect3DDevice9_StretchRect returned %08x, expected %08x\n", hr, expected);
1550 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a beginScene - Endscene pair
1551 * with normal surfaces and render targets, but not depth stencil surfaces.
1553 hr = IDirect3DDevice9_BeginScene(pDevice);
1554 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1556 if(pSurface1 && pSurface2)
1558 hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1559 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1561 if(pBackBuffer && pRenderTarget)
1563 hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1564 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1566 if(pDepthStencil && pSurface3)
1568 /* This is supposed to fail inside a BeginScene - EndScene pair. */
1569 hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1570 ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
1573 hr = IDirect3DDevice9_EndScene(pDevice);
1574 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1576 /* Does a SetRenderTarget influence BeginScene / EndScene ?
1577 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
1578 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
1580 hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pRenderTarget);
1581 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1582 hr = IDirect3DDevice9_BeginScene(pDevice);
1583 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1584 hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pBackBuffer);
1585 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1586 hr = IDirect3DDevice9_EndScene(pDevice);
1587 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1589 cleanup:
1590 if(pRenderTarget) IDirect3DSurface9_Release(pRenderTarget);
1591 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1592 if(pBackBuffer) IDirect3DSurface9_Release(pBackBuffer);
1593 if(pSurface1) IDirect3DSurface9_Release(pSurface1);
1594 if(pSurface2) IDirect3DSurface9_Release(pSurface2);
1595 if(pSurface3) IDirect3DSurface9_Release(pSurface3);
1596 if (pDevice)
1598 UINT refcount = IDirect3DDevice9_Release(pDevice);
1599 ok(!refcount, "Device has %u references left.\n", refcount);
1601 if (pD3d) IDirect3D9_Release(pD3d);
1602 if(hwnd) DestroyWindow(hwnd);
1605 static void test_limits(void)
1607 HRESULT hr;
1608 HWND hwnd = NULL;
1609 IDirect3D9 *pD3d = NULL;
1610 IDirect3DDevice9 *pDevice = NULL;
1611 D3DPRESENT_PARAMETERS d3dpp;
1612 D3DDISPLAYMODE d3ddm;
1613 IDirect3DTexture9 *pTexture = NULL;
1614 int i;
1616 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1617 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1618 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1619 ok(hwnd != NULL, "Failed to create window\n");
1620 if (!pD3d || !hwnd) goto cleanup;
1622 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1623 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1624 d3dpp.Windowed = TRUE;
1625 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1626 d3dpp.BackBufferWidth = 800;
1627 d3dpp.BackBufferHeight = 600;
1628 d3dpp.BackBufferFormat = d3ddm.Format;
1629 d3dpp.EnableAutoDepthStencil = TRUE;
1630 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1632 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1633 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1634 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1635 if(!pDevice)
1637 skip("Failed to create a d3d device\n");
1638 goto cleanup;
1641 hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL);
1642 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
1643 if(!pTexture) goto cleanup;
1645 /* There are 16 pixel samplers. We should be able to access all of them */
1646 for(i = 0; i < 16; i++) {
1647 hr = IDirect3DDevice9_SetTexture(pDevice, i, (IDirect3DBaseTexture9 *) pTexture);
1648 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1649 hr = IDirect3DDevice9_SetTexture(pDevice, i, NULL);
1650 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1651 hr = IDirect3DDevice9_SetSamplerState(pDevice, i, D3DSAMP_SRGBTEXTURE, TRUE);
1652 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
1655 /* Now test all 8 textures stage states */
1656 for(i = 0; i < 8; i++) {
1657 hr = IDirect3DDevice9_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1658 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
1661 /* Investigations show that accessing higher samplers / textures stage states does not return an error either. Writing
1662 * to too high samplers(approximately sampler 40) causes memory corruption in windows, so there is no bounds checking
1663 * but how do I test that?
1665 cleanup:
1666 if(pTexture) IDirect3DTexture9_Release(pTexture);
1667 if (pDevice)
1669 UINT refcount = IDirect3D9_Release(pDevice);
1670 ok(!refcount, "Device has %u references left.\n", refcount);
1672 if (pD3d) IDirect3D9_Release(pD3d);
1673 if(hwnd) DestroyWindow(hwnd);
1676 static void test_depthstenciltest(void)
1678 HRESULT hr;
1679 HWND hwnd = NULL;
1680 IDirect3D9 *pD3d = NULL;
1681 IDirect3DDevice9 *pDevice = NULL;
1682 D3DPRESENT_PARAMETERS d3dpp;
1683 D3DDISPLAYMODE d3ddm;
1684 IDirect3DSurface9 *pDepthStencil = NULL;
1685 IDirect3DSurface9 *pDepthStencil2 = NULL;
1686 DWORD state;
1688 pD3d = pDirect3DCreate9( D3D_SDK_VERSION );
1689 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1690 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
1691 ok(hwnd != NULL, "Failed to create window\n");
1692 if (!pD3d || !hwnd) goto cleanup;
1694 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1695 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1696 d3dpp.Windowed = TRUE;
1697 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1698 d3dpp.BackBufferWidth = 800;
1699 d3dpp.BackBufferHeight = 600;
1700 d3dpp.BackBufferFormat = d3ddm.Format;
1701 d3dpp.EnableAutoDepthStencil = TRUE;
1702 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1704 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1705 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1706 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1707 if(!pDevice)
1709 skip("Failed to create a d3d device\n");
1710 goto cleanup;
1713 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1714 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1716 /* Try to clear */
1717 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1718 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1720 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
1721 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1723 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
1724 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
1725 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1726 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
1728 /* This left the render states untouched! */
1729 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1730 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1731 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1732 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
1733 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1734 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
1735 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
1736 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1737 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
1738 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
1739 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1740 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
1742 /* This is supposed to fail now */
1743 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1744 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1746 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
1747 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
1749 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
1750 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1752 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1753 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1754 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1756 /* Now it works again */
1757 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1758 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1760 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1761 if(pDevice) IDirect3D9_Release(pDevice);
1763 /* Now see if autodepthstencil disable is honored. First, without a format set */
1764 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1765 d3dpp.Windowed = TRUE;
1766 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1767 d3dpp.BackBufferWidth = 800;
1768 d3dpp.BackBufferHeight = 600;
1769 d3dpp.BackBufferFormat = d3ddm.Format;
1770 d3dpp.EnableAutoDepthStencil = FALSE;
1771 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1773 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1774 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1775 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1776 if(!pDevice)
1778 skip("Failed to create a d3d device\n");
1779 goto cleanup;
1782 pDepthStencil = NULL;
1783 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1784 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1785 if(pDepthStencil) {
1786 IDirect3DSurface9_Release(pDepthStencil);
1787 pDepthStencil = NULL;
1790 /* Check the depth test state */
1791 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1792 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1793 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1795 if(pDevice) IDirect3D9_Release(pDevice);
1797 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
1798 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1799 d3dpp.Windowed = TRUE;
1800 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1801 d3dpp.BackBufferWidth = 800;
1802 d3dpp.BackBufferHeight = 600;
1803 d3dpp.BackBufferFormat = d3ddm.Format;
1804 d3dpp.EnableAutoDepthStencil = FALSE;
1805 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1807 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1808 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1809 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1810 if(!pDevice)
1812 skip("Failed to create a d3d device\n");
1813 goto cleanup;
1816 pDepthStencil = NULL;
1817 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1818 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1819 if(pDepthStencil) {
1820 IDirect3DSurface9_Release(pDepthStencil);
1821 pDepthStencil = NULL;
1824 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1825 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1826 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1828 cleanup:
1829 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1830 if (pDevice)
1832 UINT refcount = IDirect3D9_Release(pDevice);
1833 ok(!refcount, "Device has %u references left.\n", refcount);
1835 if (pD3d) IDirect3D9_Release(pD3d);
1836 if(hwnd) DestroyWindow(hwnd);
1839 static void test_get_rt(void)
1841 IDirect3DSurface9 *backbuffer, *rt;
1842 IDirect3DDevice9 *device;
1843 IDirect3D9 *d3d9;
1844 D3DCAPS9 caps;
1845 HWND window;
1846 HRESULT hr;
1847 ULONG ref;
1848 UINT i;
1850 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
1852 skip("Failed to create IDirect3D9 object, skipping tests.\n");
1853 return;
1856 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1857 0, 0, 128, 128, 0, 0, 0, 0);
1858 device = create_device(d3d9, window, window, TRUE);
1859 if (!device)
1861 skip("Failed to create a D3D device, skipping tests.\n");
1862 goto done;
1865 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
1866 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
1867 ok(!!backbuffer, "Got a NULL backbuffer.\n");
1869 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1870 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1872 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
1874 rt = backbuffer;
1875 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
1876 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
1877 ok(!rt, "Got rt %p.\n", rt);
1880 IDirect3DSurface9_Release(backbuffer);
1882 ref = IDirect3DDevice9_Release(device);
1883 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
1884 done:
1885 IDirect3D9_Release(d3d9);
1886 DestroyWindow(window);
1889 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
1890 static void test_draw_indexed(void)
1892 static const struct {
1893 float position[3];
1894 DWORD color;
1895 } quad[] = {
1896 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
1897 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
1898 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
1899 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
1901 WORD indices[] = {0, 1, 2, 3, 0, 2};
1903 static const D3DVERTEXELEMENT9 decl_elements[] = {
1904 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1905 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
1906 D3DDECL_END()
1909 IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1910 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
1911 IDirect3DIndexBuffer9 *index_buffer = NULL;
1912 D3DPRESENT_PARAMETERS present_parameters;
1913 IDirect3DDevice9 *device = NULL;
1914 IDirect3D9 *d3d9;
1915 HRESULT hr;
1916 HWND hwnd;
1917 void *ptr;
1919 hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
1920 0, 0, 0, 10, 10, 0, 0, 0, 0);
1921 if (!hwnd)
1923 skip("Failed to create window\n");
1924 return;
1927 d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
1928 if (!d3d9)
1930 skip("Failed to create IDirect3D9 object\n");
1931 goto cleanup;
1934 ZeroMemory(&present_parameters, sizeof(present_parameters));
1935 present_parameters.Windowed = TRUE;
1936 present_parameters.hDeviceWindow = hwnd;
1937 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1939 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1940 NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1941 if (FAILED(hr) || !device)
1943 skip("Failed to create device\n");
1944 goto cleanup;
1947 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1948 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1949 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1950 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1952 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
1953 ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
1954 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1955 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1956 memcpy(ptr, quad, sizeof(quad));
1957 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
1958 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1959 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
1960 ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
1962 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
1963 ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
1964 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1965 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1966 memcpy(ptr, indices, sizeof(indices));
1967 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
1968 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1969 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1970 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
1971 hr = IDirect3DDevice9_BeginScene(device);
1972 ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1974 /* NULL index buffer. Should fail */
1975 hr = IDirect3DDevice9_SetIndices(device, NULL);
1976 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1977 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1978 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1979 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1980 hr, D3DERR_INVALIDCALL);
1982 /* Valid index buffer, NULL vertex declaration. Should fail */
1983 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
1984 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1985 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1986 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1987 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1988 hr, D3DERR_INVALIDCALL);
1990 /* Valid index buffer and vertex declaration. Should succeed */
1991 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1992 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1993 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1994 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1995 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
1997 hr = IDirect3DDevice9_EndScene(device);
1998 ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2000 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2001 ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2003 IDirect3DVertexBuffer9_Release(vertex_buffer);
2004 IDirect3DIndexBuffer9_Release(index_buffer);
2005 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2007 cleanup:
2008 if (device)
2010 UINT refcount = IDirect3DDevice9_Release(device);
2011 ok(!refcount, "Device has %u references left.\n", refcount);
2013 if (d3d9) IDirect3D9_Release(d3d9);
2014 if (hwnd) DestroyWindow(hwnd);
2017 static void test_null_stream(void)
2019 IDirect3DVertexBuffer9 *buffer = NULL;
2020 D3DPRESENT_PARAMETERS present_parameters;
2021 IDirect3DDevice9 *device = NULL;
2022 IDirect3D9 *d3d9;
2023 HWND hwnd;
2024 HRESULT hr;
2025 IDirect3DVertexShader9 *shader = NULL;
2026 IDirect3DVertexDeclaration9 *decl = NULL;
2027 static const DWORD shader_code[] =
2029 0xfffe0101, /* vs_1_1 */
2030 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2031 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2032 0x0000ffff /* end */
2034 static const D3DVERTEXELEMENT9 decl_elements[] = {
2035 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2036 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2037 D3DDECL_END()
2040 d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2041 ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2042 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2043 ok(hwnd != NULL, "Failed to create window\n");
2044 if (!d3d9 || !hwnd) goto cleanup;
2046 ZeroMemory(&present_parameters, sizeof(present_parameters));
2047 present_parameters.Windowed = TRUE;
2048 present_parameters.hDeviceWindow = hwnd;
2049 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2051 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
2052 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2053 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2054 if(!device)
2056 skip("Failed to create a d3d device\n");
2057 goto cleanup;
2060 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2061 if(FAILED(hr)) {
2062 skip("No vertex shader support\n");
2063 goto cleanup;
2065 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2066 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2067 if (FAILED(hr)) {
2068 skip("Vertex declaration handling not possible.\n");
2069 goto cleanup;
2071 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2072 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2073 if (FAILED(hr)) {
2074 skip("Vertex buffer handling not possible.\n");
2075 goto cleanup;
2078 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
2079 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2080 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
2081 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2082 hr = IDirect3DDevice9_SetVertexShader(device, shader);
2083 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
2084 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2085 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
2087 hr = IDirect3DDevice9_BeginScene(device);
2088 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (0x%08x)\n", hr);
2089 if(SUCCEEDED(hr)) {
2090 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
2091 ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitive failed (0x%08x)\n", hr);
2093 hr = IDirect3DDevice9_EndScene(device);
2094 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed (0x%08x)\n", hr);
2097 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2098 IDirect3DDevice9_SetVertexShader(device, NULL);
2099 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2101 cleanup:
2102 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
2103 if(decl) IDirect3DVertexDeclaration9_Release(decl);
2104 if(shader) IDirect3DVertexShader9_Release(shader);
2105 if (device)
2107 UINT refcount = IDirect3DDevice9_Release(device);
2108 ok(!refcount, "Device has %u references left.\n", refcount);
2110 if(d3d9) IDirect3D9_Release(d3d9);
2113 static void test_lights(void)
2115 D3DPRESENT_PARAMETERS present_parameters;
2116 IDirect3DDevice9 *device = NULL;
2117 IDirect3D9 *d3d9;
2118 HWND hwnd;
2119 HRESULT hr;
2120 unsigned int i;
2121 BOOL enabled;
2122 D3DCAPS9 caps;
2124 d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2125 ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2126 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2127 ok(hwnd != NULL, "Failed to create window\n");
2128 if (!d3d9 || !hwnd) goto cleanup;
2130 ZeroMemory(&present_parameters, sizeof(present_parameters));
2131 present_parameters.Windowed = TRUE;
2132 present_parameters.hDeviceWindow = hwnd;
2133 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2135 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2136 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2137 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2138 "IDirect3D9_CreateDevice failed with %08x\n", hr);
2139 if(!device)
2141 skip("Failed to create a d3d device\n");
2142 goto cleanup;
2145 memset(&caps, 0, sizeof(caps));
2146 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2147 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
2149 for(i = 1; i <= caps.MaxActiveLights; i++) {
2150 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
2151 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2152 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
2153 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
2154 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2157 /* TODO: Test the rendering results in this situation */
2158 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
2159 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2160 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
2161 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2162 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2163 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
2164 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2166 for(i = 1; i <= caps.MaxActiveLights; i++) {
2167 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2168 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2171 cleanup:
2172 if (device)
2174 UINT refcount = IDirect3DDevice9_Release(device);
2175 ok(!refcount, "Device has %u references left.\n", refcount);
2177 if(d3d9) IDirect3D9_Release(d3d9);
2180 static void test_set_stream_source(void)
2182 D3DPRESENT_PARAMETERS present_parameters;
2183 IDirect3DDevice9 *device = NULL;
2184 IDirect3D9 *d3d9;
2185 HWND hwnd;
2186 HRESULT hr;
2187 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
2189 d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2190 ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2191 hwnd = CreateWindow( "d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
2192 ok(hwnd != NULL, "Failed to create window\n");
2193 if (!d3d9 || !hwnd) goto cleanup;
2195 ZeroMemory(&present_parameters, sizeof(present_parameters));
2196 present_parameters.Windowed = TRUE;
2197 present_parameters.hDeviceWindow = hwnd;
2198 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2200 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2201 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2202 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2203 "IDirect3D9_CreateDevice failed with %08x\n", hr);
2204 if(!device)
2206 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd,
2207 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2208 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2209 "IDirect3D9_CreateDevice failed with %08x\n", hr);
2210 if(!device)
2212 skip("Failed to create a d3d device\n");
2213 goto cleanup;
2217 hr = IDirect3DDevice9_CreateVertexBuffer( device, 512, 0, 0, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
2218 ok(hr == D3D_OK, "Failed to create a vertex buffer, hr = %08x\n", hr);
2219 if (SUCCEEDED(hr)) {
2220 /* Some cards(Geforce 7400 at least) accept non-aligned offsets, others(radeon 9000 verified) reject it,
2221 * so accept both results. Wine currently rejects this to be able to optimize the vbo conversion, but writes
2222 * a WARN
2224 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32);
2225 ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2226 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32);
2227 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2228 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 2, 32);
2229 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2230 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 3, 32);
2231 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2232 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 4, 32);
2233 ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2235 /* Try to set the NULL buffer with an offset and stride 0 */
2236 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2237 ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2238 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2239 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2240 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2241 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2242 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2243 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2244 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2245 ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2247 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2248 ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2250 cleanup:
2251 if (pVertexBuffer) IDirect3DVertexBuffer9_Release(pVertexBuffer);
2252 if (device)
2254 UINT refcount = IDirect3DDevice9_Release(device);
2255 ok(!refcount, "Device has %u references left.\n", refcount);
2257 if(d3d9) IDirect3D9_Release(d3d9);
2260 struct formats {
2261 D3DFORMAT DisplayFormat;
2262 D3DFORMAT BackBufferFormat;
2263 BOOL shouldPass;
2266 static const struct formats r5g6b5_format_list[] =
2268 { D3DFMT_R5G6B5, D3DFMT_R5G6B5, TRUE },
2269 { D3DFMT_R5G6B5, D3DFMT_X1R5G5B5, FALSE },
2270 { D3DFMT_R5G6B5, D3DFMT_A1R5G5B5, FALSE },
2271 { D3DFMT_R5G6B5, D3DFMT_X8R8G8B8, FALSE },
2272 { D3DFMT_R5G6B5, D3DFMT_A8R8G8B8, FALSE },
2273 { 0, 0, 0}
2276 static const struct formats x1r5g5b5_format_list[] =
2278 { D3DFMT_X1R5G5B5, D3DFMT_R5G6B5, FALSE },
2279 { D3DFMT_X1R5G5B5, D3DFMT_X1R5G5B5, TRUE },
2280 { D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE },
2281 { D3DFMT_X1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2282 { D3DFMT_X1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2284 /* A1R5G5B5 should not be usable as a display format, it is backbuffer-only */
2285 { D3DFMT_A1R5G5B5, D3DFMT_R5G6B5, FALSE },
2286 { D3DFMT_A1R5G5B5, D3DFMT_X1R5G5B5, FALSE },
2287 { D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE },
2288 { D3DFMT_A1R5G5B5, D3DFMT_X8R8G8B8, FALSE },
2289 { D3DFMT_A1R5G5B5, D3DFMT_A8R8G8B8, FALSE },
2290 { 0, 0, 0}
2293 static const struct formats x8r8g8b8_format_list[] =
2295 { D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, FALSE },
2296 { D3DFMT_X8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2297 { D3DFMT_X8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2298 { D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, TRUE },
2299 { D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE },
2301 /* A1R8G8B8 should not be usable as a display format, it is backbuffer-only */
2302 { D3DFMT_A8R8G8B8, D3DFMT_R5G6B5, FALSE },
2303 { D3DFMT_A8R8G8B8, D3DFMT_X1R5G5B5, FALSE },
2304 { D3DFMT_A8R8G8B8, D3DFMT_A1R5G5B5, FALSE },
2305 { D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8, FALSE },
2306 { D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE },
2307 { 0, 0, 0}
2310 static void test_display_formats(void)
2312 /* Direct3D9 offers 4 display formats R5G6B5, X1R5G5B5, X8R8G8B8 and A2R10G10B10.
2313 * Next to these there are 6 different backbuffer formats. Only a fixed number of
2314 * combinations are possible in FULLSCREEN mode. In windowed mode more combinations are
2315 * allowed due to depth conversion and this is likely driver dependent.
2316 * This test checks which combinations are possible in fullscreen mode and this should not be driver dependent.
2317 * TODO: handle A2R10G10B10 but what hardware supports it? Parhelia? It is very rare. */
2319 UINT Adapter = D3DADAPTER_DEFAULT;
2320 D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
2321 int i, nmodes;
2322 HRESULT hr;
2324 IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
2325 ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2326 if(!d3d9) return;
2328 nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_R5G6B5);
2329 if(!nmodes) {
2330 skip("Display format R5G6B5 not supported, skipping\n");
2331 } else {
2332 trace("Testing display format R5G6B5\n");
2333 for(i=0; r5g6b5_format_list[i].DisplayFormat != 0; i++)
2335 hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, FALSE);
2337 if(r5g6b5_format_list[i].shouldPass)
2338 ok(hr == D3D_OK ||
2339 broken(hr == D3DERR_NOTAVAILABLE) /* Windows VGA driver */,
2340 "format %d %d didn't pass with hr=%#08x\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat, hr);
2341 else
2342 ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", r5g6b5_format_list[i].DisplayFormat, r5g6b5_format_list[i].BackBufferFormat);
2346 nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X1R5G5B5);
2347 if(!nmodes) {
2348 skip("Display format X1R5G5B5 not supported, skipping\n");
2349 } else {
2350 trace("Testing display format X1R5G5B5\n");
2351 for(i=0; x1r5g5b5_format_list[i].DisplayFormat != 0; i++)
2353 hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, FALSE);
2355 if(x1r5g5b5_format_list[i].shouldPass)
2356 ok(hr == D3D_OK ||
2357 broken(hr == D3DERR_NOTAVAILABLE) /* Spice QXL driver */,
2358 "format %d %d didn't pass with hr=%#08x\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat, hr);
2359 else
2360 ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x1r5g5b5_format_list[i].DisplayFormat, x1r5g5b5_format_list[i].BackBufferFormat);
2364 nmodes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
2365 if(!nmodes) {
2366 skip("Display format X8R8G8B8 not supported, skipping\n");
2367 } else {
2368 trace("Testing display format X8R8G8B8\n");
2369 for(i=0; x8r8g8b8_format_list[i].DisplayFormat != 0; i++)
2371 hr = IDirect3D9_CheckDeviceType(d3d9, Adapter, DeviceType, x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, FALSE);
2372 trace("CheckDeviceType(%d %d) = %08x shouldPass = %d\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr, x8r8g8b8_format_list[i].shouldPass);
2374 if(x8r8g8b8_format_list[i].shouldPass)
2375 ok(hr == D3D_OK ||
2376 broken(hr == D3DERR_NOTAVAILABLE) /* Windows VGA driver */,
2377 "format %d %d didn't pass with hr=%#08x\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat, hr);
2378 else
2379 ok(hr != D3D_OK, "format %d %d didn't pass while it was expected to\n", x8r8g8b8_format_list[i].DisplayFormat, x8r8g8b8_format_list[i].BackBufferFormat);
2383 if(d3d9) IDirect3D9_Release(d3d9);
2386 static void test_scissor_size(void)
2388 IDirect3D9 *d3d9_ptr = 0;
2389 unsigned int i;
2390 static struct {
2391 int winx; int winy; int backx; int backy; BOOL window;
2392 } scts[] = { /* scissor tests */
2393 {800, 600, 640, 480, TRUE},
2394 {800, 600, 640, 480, FALSE},
2395 {640, 480, 800, 600, TRUE},
2396 {640, 480, 800, 600, FALSE},
2399 d3d9_ptr = pDirect3DCreate9(D3D_SDK_VERSION);
2400 ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
2401 if (!d3d9_ptr){
2402 skip("Failed to create IDirect3D9 object\n");
2403 return;
2406 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
2407 IDirect3DDevice9 *device_ptr = 0;
2408 D3DPRESENT_PARAMETERS present_parameters;
2409 HRESULT hr;
2410 HWND hwnd = 0;
2411 RECT scissorrect;
2413 hwnd = CreateWindow("d3d9_test_wc", "d3d9_test",
2414 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
2416 if (!scts[i].window)
2418 scts[i].backx = screen_width;
2419 scts[i].backy = screen_height;
2422 ZeroMemory(&present_parameters, sizeof(present_parameters));
2423 present_parameters.Windowed = scts[i].window;
2424 present_parameters.hDeviceWindow = hwnd;
2425 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2426 present_parameters.BackBufferWidth = scts[i].backx;
2427 present_parameters.BackBufferHeight = scts[i].backy;
2428 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
2429 present_parameters.EnableAutoDepthStencil = TRUE;
2430 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2432 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2433 if(FAILED(hr)) {
2434 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
2435 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2436 if(FAILED(hr)) {
2437 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2440 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
2442 if (!device_ptr)
2444 DestroyWindow(hwnd);
2445 skip("Creating the device failed\n");
2446 goto err_out;
2449 /* Check for the default scissor rect size */
2450 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2451 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2452 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy && scissorrect.top == 0 && scissorrect.left == 0, "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom, scts[i].backx, scts[i].backy);
2454 /* check the scissorrect values after a reset */
2455 present_parameters.BackBufferWidth = screen_width;
2456 present_parameters.BackBufferHeight = screen_height;
2457 hr = IDirect3DDevice9_Reset(device_ptr, &present_parameters);
2458 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2459 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
2460 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2462 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2463 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2464 ok(scissorrect.right == screen_width && scissorrect.bottom == screen_height && scissorrect.top == 0 && scissorrect.left == 0, "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom, screen_width, screen_height);
2466 if(device_ptr) {
2467 ULONG ref;
2469 ref = IDirect3DDevice9_Release(device_ptr);
2470 DestroyWindow(hwnd);
2471 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
2475 err_out:
2476 if(d3d9_ptr) IDirect3D9_Release(d3d9_ptr);
2477 return;
2480 static void test_multi_device(void)
2482 IDirect3DDevice9 *device1 = NULL, *device2 = NULL;
2483 D3DPRESENT_PARAMETERS present_parameters;
2484 HWND hwnd1 = NULL, hwnd2 = NULL;
2485 IDirect3D9 *d3d9;
2486 ULONG refcount;
2487 HRESULT hr;
2489 d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2490 ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2491 if (!d3d9) goto fail;
2493 hwnd1 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2494 ok(hwnd1 != NULL, "Failed to create a window.\n");
2495 if (!hwnd1) goto fail;
2497 memset(&present_parameters, 0, sizeof(present_parameters));
2498 present_parameters.Windowed = TRUE;
2499 present_parameters.hDeviceWindow = hwnd1;
2500 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2502 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd1,
2503 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device1);
2504 IDirect3D9_Release(d3d9);
2505 d3d9 = NULL;
2506 if (FAILED(hr)) {
2507 skip("Failed to create a device\n");
2508 goto fail;
2511 d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
2512 ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2513 if (!d3d9) goto fail;
2515 hwnd2 = CreateWindow("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2516 ok(hwnd2 != NULL, "Failed to create a window.\n");
2517 if (!hwnd2) goto fail;
2519 memset(&present_parameters, 0, sizeof(present_parameters));
2520 present_parameters.Windowed = TRUE;
2521 present_parameters.hDeviceWindow = hwnd2;
2522 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2524 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd2,
2525 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device2);
2526 ok(SUCCEEDED(hr), "Failed to create a device, hr %#x\n", hr);
2527 IDirect3D9_Release(d3d9);
2528 d3d9 = NULL;
2529 if (FAILED(hr)) goto fail;
2531 fail:
2532 if (d3d9) IDirect3D9_Release(d3d9);
2533 if (device1)
2535 refcount = IDirect3DDevice9_Release(device1);
2536 ok(!refcount, "Device has %u references left.\n", refcount);
2538 if (device2)
2540 refcount = IDirect3DDevice9_Release(device2);
2541 ok(!refcount, "Device has %u references left.\n", refcount);
2543 if (hwnd1) DestroyWindow(hwnd1);
2544 if (hwnd2) DestroyWindow(hwnd2);
2547 static HWND filter_messages;
2549 enum message_window
2551 DEVICE_WINDOW,
2552 FOCUS_WINDOW,
2555 struct message
2557 UINT message;
2558 enum message_window window;
2561 static const struct message *expect_messages;
2562 static HWND device_window, focus_window;
2564 struct wndproc_thread_param
2566 HWND dummy_window;
2567 HANDLE window_created;
2568 HANDLE test_finished;
2569 BOOL running_in_foreground;
2572 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2574 if (filter_messages && filter_messages == hwnd)
2576 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2577 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2580 if (expect_messages)
2582 HWND w;
2584 switch (expect_messages->window)
2586 case DEVICE_WINDOW:
2587 w = device_window;
2588 break;
2590 case FOCUS_WINDOW:
2591 w = focus_window;
2592 break;
2594 default:
2595 w = NULL;
2596 break;
2599 if (hwnd == w && expect_messages->message == message) ++expect_messages;
2602 return DefWindowProcA(hwnd, message, wparam, lparam);
2605 static DWORD WINAPI wndproc_thread(void *param)
2607 struct wndproc_thread_param *p = param;
2608 DWORD res;
2609 BOOL ret;
2611 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2612 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2613 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2615 ret = SetEvent(p->window_created);
2616 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2618 for (;;)
2620 MSG msg;
2622 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2623 res = WaitForSingleObject(p->test_finished, 100);
2624 if (res == WAIT_OBJECT_0) break;
2625 if (res != WAIT_TIMEOUT)
2627 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2628 break;
2632 DestroyWindow(p->dummy_window);
2634 return 0;
2637 static void test_wndproc(void)
2639 struct wndproc_thread_param thread_params;
2640 IDirect3DDevice9 *device;
2641 WNDCLASSA wc = {0};
2642 IDirect3D9 *d3d9;
2643 HANDLE thread;
2644 LONG_PTR proc;
2645 ULONG ref;
2646 DWORD res, tid;
2647 HWND tmp;
2649 static const struct message messages[] =
2651 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW},
2652 {WM_ACTIVATE, FOCUS_WINDOW},
2653 {WM_SETFOCUS, FOCUS_WINDOW},
2654 {0, 0},
2657 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2659 skip("Failed to create IDirect3D9 object, skipping tests.\n");
2660 return;
2663 wc.lpfnWndProc = test_proc;
2664 wc.lpszClassName = "d3d9_test_wndproc_wc";
2665 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2667 thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2668 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2669 thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2670 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2672 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2673 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2674 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2675 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2676 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2677 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2679 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2680 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2682 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2683 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2684 (LONG_PTR)test_proc, proc);
2685 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2686 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2687 (LONG_PTR)test_proc, proc);
2689 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2690 device_window, focus_window, thread_params.dummy_window);
2692 tmp = GetFocus();
2693 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2694 if (thread_params.running_in_foreground)
2696 tmp = GetForegroundWindow();
2697 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2698 thread_params.dummy_window, tmp);
2700 else
2701 skip("Not running in foreground, skip foreground window test\n");
2703 flush_events();
2705 expect_messages = messages;
2707 device = create_device(d3d9, device_window, focus_window, FALSE);
2708 if (!device)
2710 skip("Failed to create a D3D device, skipping tests.\n");
2711 goto done;
2714 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2715 expect_messages->message, expect_messages->window);
2716 expect_messages = NULL;
2718 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2720 tmp = GetFocus();
2721 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2722 tmp = GetForegroundWindow();
2723 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2725 SetForegroundWindow(focus_window);
2726 flush_events();
2728 filter_messages = focus_window;
2730 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2731 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2732 (LONG_PTR)test_proc, proc);
2734 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2735 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2736 (LONG_PTR)test_proc, proc);
2738 ref = IDirect3DDevice9_Release(device);
2739 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2741 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2742 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2743 (LONG_PTR)test_proc, proc);
2745 device = create_device(d3d9, focus_window, focus_window, FALSE);
2746 if (!device)
2748 skip("Failed to create a D3D device, skipping tests.\n");
2749 goto done;
2752 ref = IDirect3DDevice9_Release(device);
2753 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2755 device = create_device(d3d9, device_window, focus_window, FALSE);
2756 if (!device)
2758 skip("Failed to create a D3D device, skipping tests.\n");
2759 goto done;
2762 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2763 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2764 (LONG_PTR)test_proc, proc);
2766 ref = IDirect3DDevice9_Release(device);
2767 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2769 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2770 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2771 (LONG_PTR)DefWindowProcA, proc);
2773 done:
2774 filter_messages = NULL;
2775 IDirect3D9_Release(d3d9);
2777 SetEvent(thread_params.test_finished);
2778 WaitForSingleObject(thread, INFINITE);
2779 CloseHandle(thread_params.test_finished);
2780 CloseHandle(thread_params.window_created);
2781 CloseHandle(thread);
2783 DestroyWindow(device_window);
2784 DestroyWindow(focus_window);
2785 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2788 static void test_wndproc_windowed(void)
2790 struct wndproc_thread_param thread_params;
2791 IDirect3DDevice9 *device;
2792 WNDCLASSA wc = {0};
2793 IDirect3D9 *d3d9;
2794 HANDLE thread;
2795 LONG_PTR proc;
2796 HRESULT hr;
2797 ULONG ref;
2798 DWORD res, tid;
2799 HWND tmp;
2801 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
2803 skip("Failed to create IDirect3D9 object, skipping tests.\n");
2804 return;
2807 wc.lpfnWndProc = test_proc;
2808 wc.lpszClassName = "d3d9_test_wndproc_wc";
2809 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2811 thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2812 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2813 thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2814 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2816 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2817 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2818 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2819 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2820 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2821 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2823 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2824 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2826 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2827 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2828 (LONG_PTR)test_proc, proc);
2829 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2830 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2831 (LONG_PTR)test_proc, proc);
2833 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2834 device_window, focus_window, thread_params.dummy_window);
2836 tmp = GetFocus();
2837 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2838 if (thread_params.running_in_foreground)
2840 tmp = GetForegroundWindow();
2841 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2842 thread_params.dummy_window, tmp);
2844 else
2845 skip("Not running in foreground, skip foreground window test\n");
2847 filter_messages = focus_window;
2849 device = create_device(d3d9, device_window, focus_window, TRUE);
2850 if (!device)
2852 skip("Failed to create a D3D device, skipping tests.\n");
2853 goto done;
2856 tmp = GetFocus();
2857 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2858 tmp = GetForegroundWindow();
2859 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2860 thread_params.dummy_window, tmp);
2862 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2863 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2864 (LONG_PTR)test_proc, proc);
2866 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2867 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2868 (LONG_PTR)test_proc, proc);
2870 filter_messages = NULL;
2872 hr = reset_device(device, device_window, FALSE);
2873 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2875 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2876 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2877 (LONG_PTR)test_proc, proc);
2879 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2880 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2881 (LONG_PTR)test_proc, proc);
2883 hr = reset_device(device, device_window, TRUE);
2884 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2886 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2887 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2888 (LONG_PTR)test_proc, proc);
2890 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2891 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2892 (LONG_PTR)test_proc, proc);
2894 filter_messages = focus_window;
2896 ref = IDirect3DDevice9_Release(device);
2897 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2899 filter_messages = device_window;
2901 device = create_device(d3d9, focus_window, focus_window, TRUE);
2902 if (!device)
2904 skip("Failed to create a D3D device, skipping tests.\n");
2905 goto done;
2908 filter_messages = NULL;
2910 hr = reset_device(device, focus_window, FALSE);
2911 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2913 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2914 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2915 (LONG_PTR)test_proc, proc);
2917 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2918 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2919 (LONG_PTR)test_proc, proc);
2921 hr = reset_device(device, focus_window, TRUE);
2922 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2924 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2925 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2926 (LONG_PTR)test_proc, proc);
2928 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2929 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2930 (LONG_PTR)test_proc, proc);
2932 filter_messages = device_window;
2934 ref = IDirect3DDevice9_Release(device);
2935 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2937 device = create_device(d3d9, device_window, focus_window, TRUE);
2938 if (!device)
2940 skip("Failed to create a D3D device, skipping tests.\n");
2941 goto done;
2944 filter_messages = NULL;
2946 hr = reset_device(device, device_window, FALSE);
2947 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2949 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2950 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2951 (LONG_PTR)test_proc, proc);
2953 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2954 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2955 (LONG_PTR)test_proc, proc);
2957 hr = reset_device(device, device_window, TRUE);
2958 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2960 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2961 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2962 (LONG_PTR)test_proc, proc);
2964 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2965 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2966 (LONG_PTR)test_proc, proc);
2968 filter_messages = device_window;
2970 ref = IDirect3DDevice9_Release(device);
2971 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2973 done:
2974 filter_messages = NULL;
2975 IDirect3D9_Release(d3d9);
2977 SetEvent(thread_params.test_finished);
2978 WaitForSingleObject(thread, INFINITE);
2979 CloseHandle(thread_params.test_finished);
2980 CloseHandle(thread_params.window_created);
2981 CloseHandle(thread);
2983 DestroyWindow(device_window);
2984 DestroyWindow(focus_window);
2985 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2988 static void test_reset_fullscreen(void)
2990 WNDCLASSEX wc = {0};
2991 IDirect3DDevice9 *device = NULL;
2992 IDirect3D9 *d3d = NULL;
2993 ATOM atom;
2994 static const struct message messages[] =
2996 {WM_ACTIVATEAPP, FOCUS_WINDOW},
2997 {0, 0},
3000 d3d = pDirect3DCreate9(D3D_SDK_VERSION);
3001 ok(d3d != NULL, "Failed to create an IDirect3D object.\n");
3002 expect_messages = messages;
3004 wc.cbSize = sizeof(WNDCLASSEX);
3005 wc.lpfnWndProc = test_proc;
3006 wc.lpszClassName = "test_reset_fullscreen";
3008 atom = RegisterClassEx(&wc);
3009 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
3011 device_window = focus_window = CreateWindowEx(0, wc.lpszClassName, "Test Reset Fullscreen", 0, 0, 0, screen_width, screen_height, NULL, NULL, NULL, NULL);
3012 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
3015 * Create a device in windowed mode.
3016 * Since the device is windowed and we haven't called any methods that
3017 * could show the window (such as ShowWindow or SetWindowPos) yet,
3018 * WM_ACTIVATEAPP will not have been sent.
3020 device = create_device(d3d, device_window, focus_window, TRUE);
3021 if (!device)
3023 skip("Unable to create device. Skipping test.\n");
3024 goto cleanup;
3028 * Switch to fullscreen mode.
3029 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
3030 * message to be sent.
3032 ok(SUCCEEDED(reset_device(device, device_window, FALSE)), "Failed to reset device.\n");
3034 flush_events();
3035 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
3036 expect_messages = NULL;
3038 cleanup:
3039 if (device) IDirect3DDevice9_Release(device);
3040 if (d3d) IDirect3D9_Release(d3d);
3041 DestroyWindow(device_window);
3042 device_window = focus_window = NULL;
3043 UnregisterClass(wc.lpszClassName, GetModuleHandle(NULL));
3047 static inline void set_fpu_cw(WORD cw)
3049 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3050 #define D3D9_TEST_SET_FPU_CW 1
3051 __asm__ volatile ("fnclex");
3052 __asm__ volatile ("fldcw %0" : : "m" (cw));
3053 #elif defined(__i386__) && defined(_MSC_VER)
3054 #define D3D9_TEST_SET_FPU_CW 1
3055 __asm fnclex;
3056 __asm fldcw cw;
3057 #endif
3060 static inline WORD get_fpu_cw(void)
3062 WORD cw = 0;
3063 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3064 #define D3D9_TEST_GET_FPU_CW 1
3065 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3066 #elif defined(__i386__) && defined(_MSC_VER)
3067 #define D3D9_TEST_GET_FPU_CW 1
3068 __asm fnstcw cw;
3069 #endif
3070 return cw;
3073 static void test_fpu_setup(void)
3075 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
3076 D3DPRESENT_PARAMETERS present_parameters;
3077 IDirect3DDevice9 *device;
3078 HWND window = NULL;
3079 IDirect3D9 *d3d9;
3080 HRESULT hr;
3081 WORD cw;
3083 d3d9 = pDirect3DCreate9(D3D_SDK_VERSION);
3084 ok(!!d3d9, "Failed to create a d3d9 object.\n");
3085 if (!d3d9) return;
3087 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3088 ok(!!window, "Failed to create a window.\n");
3089 if (!window) goto done;
3091 memset(&present_parameters, 0, sizeof(present_parameters));
3092 present_parameters.Windowed = TRUE;
3093 present_parameters.hDeviceWindow = window;
3094 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
3096 set_fpu_cw(0xf60);
3097 cw = get_fpu_cw();
3098 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3100 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3101 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
3102 if (FAILED(hr))
3104 skip("Failed to create a device, hr %#x.\n", hr);
3105 set_fpu_cw(0x37f);
3106 goto done;
3109 cw = get_fpu_cw();
3110 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3112 IDirect3DDevice9_Release(device);
3114 cw = get_fpu_cw();
3115 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3116 set_fpu_cw(0xf60);
3117 cw = get_fpu_cw();
3118 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3120 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3121 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
3122 ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
3124 cw = get_fpu_cw();
3125 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3126 set_fpu_cw(0x37f);
3128 IDirect3DDevice9_Release(device);
3130 done:
3131 if (window) DestroyWindow(window);
3132 if (d3d9) IDirect3D9_Release(d3d9);
3133 #endif
3136 static void test_window_style(void)
3138 RECT focus_rect, fullscreen_rect, r;
3139 LONG device_style, device_exstyle;
3140 LONG focus_style, focus_exstyle;
3141 LONG style, expected_style;
3142 IDirect3DDevice9 *device;
3143 IDirect3D9 *d3d9;
3144 HRESULT hr;
3145 ULONG ref;
3148 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3150 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3151 return;
3154 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3155 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3156 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3157 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3159 device_style = GetWindowLongA(device_window, GWL_STYLE);
3160 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3161 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3162 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3164 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3165 GetWindowRect(focus_window, &focus_rect);
3167 device = create_device(d3d9, device_window, focus_window, FALSE);
3168 if (!device)
3170 skip("Failed to create a D3D device, skipping tests.\n");
3171 goto done;
3174 style = GetWindowLongA(device_window, GWL_STYLE);
3175 expected_style = device_style | WS_VISIBLE;
3176 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3177 expected_style, style);
3178 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3179 expected_style = device_exstyle | WS_EX_TOPMOST;
3180 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3181 expected_style, style);
3183 style = GetWindowLongA(focus_window, GWL_STYLE);
3184 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3185 focus_style, style);
3186 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3187 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3188 focus_exstyle, style);
3190 GetWindowRect(device_window, &r);
3191 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3192 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3193 r.left, r.top, r.right, r.bottom);
3194 GetClientRect(device_window, &r);
3195 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3196 GetWindowRect(focus_window, &r);
3197 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3198 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3199 r.left, r.top, r.right, r.bottom);
3201 hr = reset_device(device, device_window, TRUE);
3202 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3204 style = GetWindowLongA(device_window, GWL_STYLE);
3205 expected_style = device_style | WS_VISIBLE;
3206 ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3207 expected_style, style);
3208 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3209 expected_style = device_exstyle | WS_EX_TOPMOST;
3210 ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3211 expected_style, style);
3213 style = GetWindowLongA(focus_window, GWL_STYLE);
3214 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3215 focus_style, style);
3216 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3217 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3218 focus_exstyle, style);
3220 ref = IDirect3DDevice9_Release(device);
3221 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3223 done:
3224 IDirect3D9_Release(d3d9);
3226 DestroyWindow(device_window);
3227 DestroyWindow(focus_window);
3230 static const POINT *expect_pos;
3232 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
3234 if (message == WM_MOUSEMOVE)
3236 if (expect_pos && expect_pos->x && expect_pos->y)
3238 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
3240 ClientToScreen(window, &p);
3241 if (expect_pos->x == p.x && expect_pos->y == p.y)
3242 ++expect_pos;
3246 return DefWindowProcA(window, message, wparam, lparam);
3249 static void test_cursor_pos(void)
3251 IDirect3DSurface9 *cursor;
3252 IDirect3DDevice9 *device;
3253 WNDCLASSA wc = {0};
3254 IDirect3D9 *d3d9;
3255 UINT refcount;
3256 HWND window;
3257 HRESULT hr;
3258 BOOL ret;
3260 /* Note that we don't check for movement we're not supposed to receive.
3261 * That's because it's hard to distinguish from the user accidentally
3262 * moving the mouse. */
3263 static const POINT points[] =
3265 {50, 50},
3266 {75, 75},
3267 {100, 100},
3268 {125, 125},
3269 {150, 150},
3270 {125, 125},
3271 {150, 150},
3272 {150, 150},
3273 {0, 0},
3276 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3278 skip("Failed to create IDirect3D9 object, skipping cursor tests.\n");
3279 return;
3282 wc.lpfnWndProc = test_cursor_proc;
3283 wc.lpszClassName = "d3d9_test_cursor_wc";
3284 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3285 window = CreateWindow("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3286 0, 0, 320, 240, NULL, NULL, NULL, NULL);
3287 ShowWindow(window, SW_SHOW);
3289 device = create_device(d3d9, window, window, TRUE);
3290 if (!device)
3292 skip("Failed to create a D3D device, skipping tests.\n");
3293 goto done;
3296 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
3297 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
3298 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
3299 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
3300 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
3301 IDirect3DSurface9_Release(cursor);
3302 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
3303 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
3305 flush_events();
3306 expect_pos = points;
3308 ret = SetCursorPos(50, 50);
3309 ok(ret, "Failed to set cursor position.\n");
3310 flush_events();
3312 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3313 flush_events();
3314 /* SetCursorPosition() eats duplicates. */
3315 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3316 flush_events();
3318 ret = SetCursorPos(100, 100);
3319 ok(ret, "Failed to set cursor position.\n");
3320 flush_events();
3321 /* Even if the position was set with SetCursorPos(). */
3322 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
3323 flush_events();
3325 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3326 flush_events();
3327 ret = SetCursorPos(150, 150);
3328 ok(ret, "Failed to set cursor position.\n");
3329 flush_events();
3330 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3331 flush_events();
3333 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
3334 flush_events();
3335 /* SetCursorPos() doesn't. */
3336 ret = SetCursorPos(150, 150);
3337 ok(ret, "Failed to set cursor position.\n");
3338 flush_events();
3340 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
3341 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
3343 refcount = IDirect3DDevice9_Release(device);
3344 ok(!refcount, "Device has %u references left.\n", refcount);
3345 done:
3346 DestroyWindow(window);
3347 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
3348 if (d3d9)
3349 IDirect3D9_Release(d3d9);
3352 static void test_mode_change(void)
3354 RECT fullscreen_rect, focus_rect, r;
3355 IDirect3DSurface9 *backbuffer;
3356 IDirect3DDevice9 *device;
3357 D3DSURFACE_DESC desc;
3358 IDirect3D9 *d3d9;
3359 DEVMODEW devmode;
3360 UINT refcount;
3361 HRESULT hr;
3362 DWORD ret;
3364 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3366 skip("Failed to create IDirect3D9 object, skipping mode change tests.\n");
3367 return;
3370 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3371 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3372 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3373 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3375 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3376 GetWindowRect(focus_window, &focus_rect);
3378 device = create_device(d3d9, device_window, focus_window, FALSE);
3379 if (!device)
3381 skip("Failed to create a D3D device, skipping tests.\n");
3382 goto done;
3385 memset(&devmode, 0, sizeof(devmode));
3386 devmode.dmSize = sizeof(devmode);
3387 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3388 devmode.dmPelsWidth = 640;
3389 devmode.dmPelsHeight = 480;
3391 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3392 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3394 memset(&devmode, 0, sizeof(devmode));
3395 devmode.dmSize = sizeof(devmode);
3396 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3397 ok(ret, "Failed to get display mode.\n");
3398 ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3399 ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3401 GetWindowRect(device_window, &r);
3402 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3403 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3404 r.left, r.top, r.right, r.bottom);
3405 GetWindowRect(focus_window, &r);
3406 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3407 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3408 r.left, r.top, r.right, r.bottom);
3410 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3411 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3412 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
3413 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3414 ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3415 ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3416 IDirect3DSurface9_Release(backbuffer);
3418 refcount = IDirect3DDevice9_Release(device);
3419 ok(!refcount, "Device has %u references left.\n", refcount);
3421 memset(&devmode, 0, sizeof(devmode));
3422 devmode.dmSize = sizeof(devmode);
3423 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3424 ok(ret, "Failed to get display mode.\n");
3425 ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3426 ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3428 done:
3429 DestroyWindow(device_window);
3430 DestroyWindow(focus_window);
3431 if (d3d9)
3432 IDirect3D9_Release(d3d9);
3434 memset(&devmode, 0, sizeof(devmode));
3435 devmode.dmSize = sizeof(devmode);
3436 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3437 ok(ret, "Failed to get display mode.\n");
3438 ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3439 ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3442 static void test_device_window_reset(void)
3444 RECT fullscreen_rect, device_rect, r;
3445 IDirect3DDevice9 *device;
3446 WNDCLASSA wc = {0};
3447 IDirect3D9 *d3d9;
3448 LONG_PTR proc;
3449 HRESULT hr;
3450 ULONG ref;
3452 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3454 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3455 return;
3458 wc.lpfnWndProc = test_proc;
3459 wc.lpszClassName = "d3d9_test_wndproc_wc";
3460 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3462 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3463 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3464 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3465 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3467 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3468 GetWindowRect(device_window, &device_rect);
3470 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3471 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3472 (LONG_PTR)test_proc, proc);
3473 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3474 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3475 (LONG_PTR)test_proc, proc);
3477 device = create_device(d3d9, NULL, focus_window, FALSE);
3478 if (!device)
3480 skip("Failed to create a D3D device, skipping tests.\n");
3481 goto done;
3484 GetWindowRect(focus_window, &r);
3485 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3486 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3487 r.left, r.top, r.right, r.bottom);
3488 GetWindowRect(device_window, &r);
3489 ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3490 device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3491 r.left, r.top, r.right, r.bottom);
3493 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3494 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3495 (LONG_PTR)test_proc, proc);
3496 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3497 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3498 (LONG_PTR)test_proc, proc);
3500 hr = reset_device(device, device_window, FALSE);
3501 ok(SUCCEEDED(hr), "Failed to reset device.\n");
3503 GetWindowRect(focus_window, &r);
3504 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3505 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3506 r.left, r.top, r.right, r.bottom);
3507 GetWindowRect(device_window, &r);
3508 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3509 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3510 r.left, r.top, r.right, r.bottom);
3512 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3513 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3514 (LONG_PTR)test_proc, proc);
3515 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3516 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3517 (LONG_PTR)test_proc, proc);
3519 ref = IDirect3DDevice9_Release(device);
3520 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3522 done:
3523 IDirect3D9_Release(d3d9);
3524 DestroyWindow(device_window);
3525 DestroyWindow(focus_window);
3526 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3529 static void test_reset_resources(void)
3531 IDirect3DSurface9 *surface, *rt;
3532 IDirect3DTexture9 *texture;
3533 IDirect3DDevice9 *device;
3534 IDirect3D9 *d3d9;
3535 unsigned int i;
3536 D3DCAPS9 caps;
3537 HWND window;
3538 HRESULT hr;
3539 ULONG ref;
3541 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3542 0, 0, 640, 480, 0, 0, 0, 0);
3544 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3546 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3547 DestroyWindow(window);
3548 return;
3551 if (!(device = create_device(d3d9, window, window, TRUE)))
3553 skip("Failed to create a D3D device, skipping tests.\n");
3554 goto done;
3557 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3558 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3560 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
3561 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
3562 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
3563 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
3564 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
3565 IDirect3DSurface9_Release(surface);
3567 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
3569 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3570 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
3571 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
3572 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3573 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
3574 IDirect3DTexture9_Release(texture);
3575 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
3576 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
3577 IDirect3DSurface9_Release(surface);
3580 hr = reset_device(device, device_window, TRUE);
3581 ok(SUCCEEDED(hr), "Failed to reset device.\n");
3583 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3584 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3585 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
3586 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3587 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3588 IDirect3DSurface9_Release(surface);
3589 IDirect3DSurface9_Release(rt);
3591 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
3593 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
3594 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
3597 ref = IDirect3DDevice9_Release(device);
3598 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3600 done:
3601 IDirect3D9_Release(d3d9);
3602 DestroyWindow(window);
3605 static void test_set_rt_vp_scissor(void)
3607 IDirect3DStateBlock9 *stateblock;
3608 IDirect3DDevice9 *device;
3609 IDirect3DSurface9 *rt;
3610 IDirect3D9 *d3d9;
3611 D3DVIEWPORT9 vp;
3612 UINT refcount;
3613 HWND window;
3614 HRESULT hr;
3615 RECT rect;
3617 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3619 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3620 return;
3623 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3624 0, 0, 640, 480, 0, 0, 0, 0);
3625 if (!(device = create_device(d3d9, window, window, TRUE)))
3627 skip("Failed to create a D3D device, skipping tests.\n");
3628 DestroyWindow(window);
3629 return;
3632 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3633 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
3634 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3636 hr = IDirect3DDevice9_GetViewport(device, &vp);
3637 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3638 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3639 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3640 ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3641 ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3642 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3643 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3645 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3646 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3647 ok(rect.left == 0 && rect.top == 0 && rect.right == screen_width && rect.bottom == screen_height,
3648 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3649 rect.left, rect.top, rect.right, rect.bottom);
3651 hr = IDirect3DDevice9_BeginStateBlock(device);
3652 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3654 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3655 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3657 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
3658 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3659 IDirect3DStateBlock9_Release(stateblock);
3661 hr = IDirect3DDevice9_GetViewport(device, &vp);
3662 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3663 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3664 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3665 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3666 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3667 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3668 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3670 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3671 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3672 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3673 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3674 rect.left, rect.top, rect.right, rect.bottom);
3676 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3677 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3679 vp.X = 10;
3680 vp.Y = 20;
3681 vp.Width = 30;
3682 vp.Height = 40;
3683 vp.MinZ = 0.25f;
3684 vp.MaxZ = 0.75f;
3685 hr = IDirect3DDevice9_SetViewport(device, &vp);
3686 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3688 SetRect(&rect, 50, 60, 70, 80);
3689 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
3690 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
3692 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3693 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3695 hr = IDirect3DDevice9_GetViewport(device, &vp);
3696 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3697 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3698 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3699 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3700 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3701 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3702 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3704 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3705 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3706 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3707 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3708 rect.left, rect.top, rect.right, rect.bottom);
3710 IDirect3DSurface9_Release(rt);
3711 refcount = IDirect3DDevice9_Release(device);
3712 ok(!refcount, "Device has %u references left.\n", refcount);
3713 IDirect3D9_Release(d3d9);
3714 DestroyWindow(window);
3717 static void test_volume_get_container(void)
3719 IDirect3DVolumeTexture9 *texture = NULL;
3720 IDirect3DVolume9 *volume = NULL;
3721 IDirect3DDevice9 *device;
3722 IUnknown *container;
3723 IDirect3D9 *d3d9;
3724 ULONG refcount;
3725 D3DCAPS9 caps;
3726 HWND window;
3727 HRESULT hr;
3729 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3731 skip("Failed to create d3d9 object, skipping tests.\n");
3732 return;
3735 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3736 0, 0, 640, 480, 0, 0, 0, 0);
3737 if (!(device = create_device(d3d9, window, window, TRUE)))
3739 skip("Failed to create a D3D device, skipping tests.\n");
3740 IDirect3D9_Release(d3d9);
3741 DestroyWindow(window);
3742 return;
3745 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3746 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3747 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3749 skip("No volume texture support, skipping tests.\n");
3750 IDirect3DDevice9_Release(device);
3751 IDirect3D9_Release(d3d9);
3752 DestroyWindow(window);
3753 return;
3756 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3757 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3758 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3759 ok(!!texture, "Got unexpected texture %p.\n", texture);
3761 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3762 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3763 ok(!!volume, "Got unexpected volume %p.\n", volume);
3765 /* These should work... */
3766 container = NULL;
3767 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
3768 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3769 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3770 IUnknown_Release(container);
3772 container = NULL;
3773 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
3774 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3775 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3776 IUnknown_Release(container);
3778 container = NULL;
3779 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
3780 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3781 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3782 IUnknown_Release(container);
3784 container = NULL;
3785 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
3786 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3787 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3788 IUnknown_Release(container);
3790 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3791 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
3792 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3793 ok(!container, "Got unexpected container %p.\n", container);
3795 IDirect3DVolume9_Release(volume);
3796 IDirect3DVolumeTexture9_Release(texture);
3797 refcount = IDirect3DDevice9_Release(device);
3798 ok(!refcount, "Device has %u references left.\n", refcount);
3799 IDirect3D9_Release(d3d9);
3800 DestroyWindow(window);
3803 static void test_volume_resource(void)
3805 IDirect3DVolumeTexture9 *texture;
3806 IDirect3DResource9 *resource;
3807 IDirect3DVolume9 *volume;
3808 IDirect3DDevice9 *device;
3809 IDirect3D9 *d3d9;
3810 ULONG refcount;
3811 D3DCAPS9 caps;
3812 HWND window;
3813 HRESULT hr;
3815 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3817 skip("Failed to create d3d9 object, skipping tests.\n");
3818 return;
3821 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3822 0, 0, 640, 480, 0, 0, 0, 0);
3823 if (!(device = create_device(d3d9, window, window, TRUE)))
3825 skip("Failed to create a D3D device, skipping tests.\n");
3826 IDirect3D9_Release(d3d9);
3827 DestroyWindow(window);
3828 return;
3831 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3832 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3833 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3835 skip("No volume texture support, skipping tests.\n");
3836 IDirect3DDevice9_Release(device);
3837 IDirect3D9_Release(d3d9);
3838 DestroyWindow(window);
3839 return;
3842 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3843 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3844 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3845 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3846 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3847 IDirect3DVolumeTexture9_Release(texture);
3849 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
3850 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3852 IDirect3DVolume9_Release(volume);
3853 refcount = IDirect3DDevice9_Release(device);
3854 ok(!refcount, "Device has %u references left.\n", refcount);
3855 IDirect3D9_Release(d3d9);
3856 DestroyWindow(window);
3859 static void test_vb_lock_flags(void)
3861 static const struct
3863 DWORD flags;
3864 const char *debug_string;
3865 HRESULT win7_result;
3867 test_data[] =
3869 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
3870 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
3871 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
3872 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
3873 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
3874 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
3875 /* Completely bogus flags aren't an error. */
3876 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
3878 IDirect3DVertexBuffer9 *buffer;
3879 IDirect3DDevice9 *device;
3880 IDirect3D9 *d3d9;
3881 unsigned int i;
3882 ULONG refcount;
3883 HWND window;
3884 HRESULT hr;
3885 void *data;
3887 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3889 skip("Failed to create d3d9 object, skipping tests.\n");
3890 return;
3893 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3894 0, 0, 640, 480, 0, 0, 0, 0);
3895 if (!(device = create_device(d3d9, window, window, TRUE)))
3897 skip("Failed to create a D3D device, skipping tests.\n");
3898 IDirect3D9_Release(d3d9);
3899 DestroyWindow(window);
3900 return;
3903 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
3904 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3906 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
3908 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
3909 /* Windows XP always returns D3D_OK even with flags that don't make
3910 * sense. Windows 7 returns an error. At least one game (Shaiya)
3911 * depends on the Windows XP result, so mark the Windows 7 behavior as
3912 * broken. */
3913 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
3914 hr, test_data[i].debug_string);
3915 if (SUCCEEDED(hr))
3917 ok(!!data, "Got unexpected data %p.\n", data);
3918 hr = IDirect3DVertexBuffer9_Unlock(buffer);
3919 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3923 IDirect3DVertexBuffer9_Release(buffer);
3924 refcount = IDirect3DDevice9_Release(device);
3925 ok(!refcount, "Device has %u references left.\n", refcount);
3926 IDirect3D9_Release(d3d9);
3927 DestroyWindow(window);
3930 static const char *debug_d3dpool(D3DPOOL pool)
3932 switch (pool)
3934 case D3DPOOL_DEFAULT:
3935 return "D3DPOOL_DEFAULT";
3936 case D3DPOOL_SYSTEMMEM:
3937 return "D3DPOOL_SYSTEMMEM";
3938 case D3DPOOL_SCRATCH:
3939 return "D3DPOOL_SCRATCH";
3940 case D3DPOOL_MANAGED:
3941 return "D3DPOOL_MANAGED";
3942 default:
3943 return "unknown pool";
3947 static void test_vertex_buffer_alignment(void)
3949 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
3950 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
3951 IDirect3DVertexBuffer9 *buffer = NULL;
3952 const unsigned int align = 16;
3953 IDirect3DDevice9 *device;
3954 unsigned int i, j;
3955 IDirect3D9 *d3d9;
3956 ULONG refcount;
3957 HWND window;
3958 HRESULT hr;
3959 void *data;
3961 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
3963 skip("Failed to create d3d9 object, skipping tests.\n");
3964 return;
3967 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3968 0, 0, 640, 480, 0, 0, 0, 0);
3969 if (!(device = create_device(d3d9, window, window, TRUE)))
3971 skip("Failed to create a D3D device, skipping tests.\n");
3972 IDirect3D9_Release(d3d9);
3973 DestroyWindow(window);
3974 return;
3977 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
3979 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
3981 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
3982 if (pools[j] == D3DPOOL_SCRATCH)
3983 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
3984 else
3985 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
3986 debug_d3dpool(pools[j]), sizes[i], hr);
3987 if (FAILED(hr))
3988 continue;
3990 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
3991 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3992 ok(!((DWORD_PTR)data & (align - 1)),
3993 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
3994 data, align, sizes[i], debug_d3dpool(pools[j]));
3995 hr = IDirect3DVertexBuffer9_Unlock(buffer);
3996 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3997 IDirect3DVertexBuffer9_Release(buffer);
4001 refcount = IDirect3DDevice9_Release(device);
4002 ok(!refcount, "Device has %u references left.\n", refcount);
4003 IDirect3D9_Release(d3d9);
4004 DestroyWindow(window);
4007 static void test_query_support(void)
4009 static const D3DQUERYTYPE queries[] =
4011 D3DQUERYTYPE_VCACHE,
4012 D3DQUERYTYPE_RESOURCEMANAGER,
4013 D3DQUERYTYPE_VERTEXSTATS,
4014 D3DQUERYTYPE_EVENT,
4015 D3DQUERYTYPE_OCCLUSION,
4016 D3DQUERYTYPE_TIMESTAMP,
4017 D3DQUERYTYPE_TIMESTAMPDISJOINT,
4018 D3DQUERYTYPE_TIMESTAMPFREQ,
4019 D3DQUERYTYPE_PIPELINETIMINGS,
4020 D3DQUERYTYPE_INTERFACETIMINGS,
4021 D3DQUERYTYPE_VERTEXTIMINGS,
4022 D3DQUERYTYPE_PIXELTIMINGS,
4023 D3DQUERYTYPE_BANDWIDTHTIMINGS,
4024 D3DQUERYTYPE_CACHEUTILIZATION,
4026 IDirect3DQuery9 *query = NULL;
4027 IDirect3DDevice9 *device;
4028 IDirect3D9 *d3d9;
4029 unsigned int i;
4030 ULONG refcount;
4031 BOOL supported;
4032 HWND window;
4033 HRESULT hr;
4035 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4037 skip("Failed to create d3d9 object, skipping tests.\n");
4038 return;
4041 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4042 0, 0, 640, 480, 0, 0, 0, 0);
4043 if (!(device = create_device(d3d9, window, window, TRUE)))
4045 skip("Failed to create a D3D device, skipping tests.\n");
4046 IDirect3D9_Release(d3d9);
4047 DestroyWindow(window);
4048 return;
4051 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
4053 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
4054 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4056 supported = hr == D3D_OK;
4058 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
4059 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4061 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
4062 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
4064 if (query)
4066 IDirect3DQuery9_Release(query);
4067 query = NULL;
4071 refcount = IDirect3DDevice9_Release(device);
4072 ok(!refcount, "Device has %u references left.\n", refcount);
4073 IDirect3D9_Release(d3d9);
4074 DestroyWindow(window);
4077 static void test_occlusion_query_states(void)
4079 static const float point[3] = {0.0, 0.0, 0.0};
4080 IDirect3DQuery9 *query = NULL;
4081 unsigned int data_size, i;
4082 IDirect3DDevice9 *device;
4083 IDirect3D9 *d3d9;
4084 ULONG refcount;
4085 HWND window;
4086 HRESULT hr;
4087 BYTE *data;
4089 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
4091 skip("Failed to create d3d9 object, skipping tests.\n");
4092 return;
4095 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4096 0, 0, 640, 480, 0, 0, 0, 0);
4097 if (!(device = create_device(d3d9, window, window, TRUE)))
4099 skip("Failed to create a D3D device, skipping tests.\n");
4100 IDirect3D9_Release(d3d9);
4101 DestroyWindow(window);
4102 return;
4105 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
4106 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
4107 if (!query)
4109 skip("Occlusion queries are not supported, skipping tests.\n");
4110 IDirect3DDevice9_Release(device);
4111 IDirect3D9_Release(d3d9);
4112 DestroyWindow(window);
4113 return;
4116 data_size = IDirect3DQuery9_GetDataSize(query);
4117 data = HeapAlloc(GetProcessHeap(), 0, data_size);
4119 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4120 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4121 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4122 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4124 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4125 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4126 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4127 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4128 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4129 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4131 *((DWORD *)data) = 0x12345678;
4132 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4133 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4134 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4135 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4136 if (hr == D3D_OK)
4137 ok(!*(DWORD *)data, "Got unexpected query result %u.\n", *(DWORD *)data);
4139 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4140 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
4141 hr = IDirect3DDevice9_BeginScene(device);
4142 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4143 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
4144 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4145 hr = IDirect3DDevice9_EndScene(device);
4146 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4148 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4149 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4150 for (i = 0; i < 500; ++i)
4152 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4153 break;
4154 Sleep(10);
4156 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4158 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4159 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4160 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4161 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4163 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4164 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4165 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4166 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4167 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4168 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4170 HeapFree(GetProcessHeap(), 0, data);
4171 IDirect3DQuery9_Release(query);
4172 refcount = IDirect3DDevice9_Release(device);
4173 ok(!refcount, "Device has %u references left.\n", refcount);
4174 IDirect3D9_Release(d3d9);
4175 DestroyWindow(window);
4178 static void test_get_set_vertex_shader(void)
4180 IDirect3DVertexShader9 *current_shader = NULL;
4181 IDirect3DVertexShader9 *shader = NULL;
4182 IDirect3DDevice9 *device;
4183 ULONG refcount, i;
4184 IDirect3D9 *d3d;
4185 D3DCAPS9 caps;
4186 HWND window;
4187 HRESULT hr;
4189 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4191 skip("Failed to create D3D object, skipping tests.\n");
4192 return;
4195 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4196 0, 0, 640, 480, 0, 0, 0, 0);
4197 if (!(device = create_device(d3d, window, window, TRUE)))
4199 skip("Failed to create a D3D device, skipping tests.\n");
4200 IDirect3D9_Release(d3d);
4201 DestroyWindow(window);
4202 return;
4205 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4206 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4207 if (!(caps.VertexShaderVersion & 0xffff))
4209 skip("No vertex shader support, skipping tests.\n");
4210 IDirect3DDevice9_Release(device);
4211 IDirect3D9_Release(d3d);
4212 DestroyWindow(window);
4213 return;
4216 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
4217 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4218 ok(!!shader, "Got unexpected shader %p.\n", shader);
4220 /* SetVertexShader() should not touch the shader's refcount. */
4221 i = get_refcount((IUnknown *)shader);
4222 hr = IDirect3DDevice9_SetVertexShader(device, shader);
4223 refcount = get_refcount((IUnknown *)shader);
4224 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
4225 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4227 /* GetVertexShader() should increase the shader's refcount by one. */
4228 i = refcount + 1;
4229 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
4230 refcount = get_refcount((IUnknown *)shader);
4231 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
4232 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4233 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4234 IDirect3DVertexShader9_Release(current_shader);
4236 IDirect3DVertexShader9_Release(shader);
4237 refcount = IDirect3DDevice9_Release(device);
4238 ok(!refcount, "Device has %u references left.\n", refcount);
4239 IDirect3D9_Release(d3d);
4240 DestroyWindow(window);
4243 static void test_vertex_shader_constant(void)
4245 static const float d[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4246 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4247 IDirect3DDevice9 *device;
4248 IDirect3D9 *d3d;
4249 ULONG refcount;
4250 D3DCAPS9 caps;
4251 DWORD consts;
4252 HWND window;
4253 HRESULT hr;
4255 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4257 skip("Failed to create D3D object, skipping tests.\n");
4258 return;
4261 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4262 0, 0, 640, 480, 0, 0, 0, 0);
4263 if (!(device = create_device(d3d, window, window, TRUE)))
4265 skip("Failed to create a D3D device, skipping tests.\n");
4266 IDirect3D9_Release(d3d);
4267 DestroyWindow(window);
4268 return;
4271 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4272 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4273 if (!(caps.VertexShaderVersion & 0xffff))
4275 skip("No vertex shader support, skipping tests.\n");
4276 IDirect3DDevice9_Release(device);
4277 IDirect3D9_Release(d3d);
4278 DestroyWindow(window);
4279 return;
4281 consts = caps.MaxVertexShaderConst;
4283 /* A simple check that the stuff works at all. */
4284 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
4285 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4287 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
4288 * consts from MAX - 1. */
4289 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
4290 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4291 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
4292 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4293 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
4294 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4295 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
4296 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4298 /* Constant -1. */
4299 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
4300 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4302 refcount = IDirect3DDevice9_Release(device);
4303 ok(!refcount, "Device has %u references left.\n", refcount);
4304 IDirect3D9_Release(d3d);
4305 DestroyWindow(window);
4308 static void test_get_set_pixel_shader(void)
4310 IDirect3DPixelShader9 *current_shader = NULL;
4311 IDirect3DPixelShader9 *shader = NULL;
4312 IDirect3DDevice9 *device;
4313 ULONG refcount, i;
4314 IDirect3D9 *d3d;
4315 D3DCAPS9 caps;
4316 HWND window;
4317 HRESULT hr;
4319 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4321 skip("Failed to create D3D object, skipping tests.\n");
4322 return;
4325 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4326 0, 0, 640, 480, 0, 0, 0, 0);
4327 if (!(device = create_device(d3d, window, window, TRUE)))
4329 skip("Failed to create a D3D device, skipping tests.\n");
4330 IDirect3D9_Release(d3d);
4331 DestroyWindow(window);
4332 return;
4335 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4336 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4337 if (!(caps.PixelShaderVersion & 0xffff))
4339 skip("No pixel shader support, skipping tests.\n");
4340 IDirect3DDevice9_Release(device);
4341 IDirect3D9_Release(d3d);
4342 DestroyWindow(window);
4343 return;
4346 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
4347 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4348 ok(!!shader, "Got unexpected shader %p.\n", shader);
4350 /* SetPixelShader() should not touch the shader's refcount. */
4351 i = get_refcount((IUnknown *)shader);
4352 hr = IDirect3DDevice9_SetPixelShader(device, shader);
4353 refcount = get_refcount((IUnknown *)shader);
4354 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
4355 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4357 /* GetPixelShader() should increase the shader's refcount by one. */
4358 i = refcount + 1;
4359 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
4360 refcount = get_refcount((IUnknown *)shader);
4361 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
4362 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4363 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4364 IDirect3DPixelShader9_Release(current_shader);
4366 IDirect3DPixelShader9_Release(shader);
4367 refcount = IDirect3DDevice9_Release(device);
4368 ok(!refcount, "Device has %u references left.\n", refcount);
4369 IDirect3D9_Release(d3d);
4370 DestroyWindow(window);
4373 static void test_pixel_shader_constant(void)
4375 static const float d[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
4376 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4377 IDirect3DDevice9 *device;
4378 DWORD consts = 0;
4379 IDirect3D9 *d3d;
4380 ULONG refcount;
4381 D3DCAPS9 caps;
4382 HWND window;
4383 HRESULT hr;
4385 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4387 skip("Failed to create D3D object, skipping tests.\n");
4388 return;
4391 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4392 0, 0, 640, 480, 0, 0, 0, 0);
4393 if (!(device = create_device(d3d, window, window, TRUE)))
4395 skip("Failed to create a D3D device, skipping tests.\n");
4396 IDirect3D9_Release(d3d);
4397 DestroyWindow(window);
4398 return;
4401 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4402 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4403 if (!(caps.PixelShaderVersion & 0xffff))
4405 skip("No pixel shader support, skipping tests.\n");
4406 IDirect3DDevice9_Release(device);
4407 IDirect3D9_Release(d3d);
4408 DestroyWindow(window);
4409 return;
4412 /* A simple check that the stuff works at all. */
4413 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
4414 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4416 /* Is there really no max pixel shader constant value??? Test how far I can go. */
4417 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
4418 consts = consts - 1;
4419 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
4421 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
4422 * pointless given the way the constant limit was determined. */
4423 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
4424 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4426 /* Constant -1. */
4427 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
4428 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4430 refcount = IDirect3DDevice9_Release(device);
4431 ok(!refcount, "Device has %u references left.\n", refcount);
4432 IDirect3D9_Release(d3d);
4433 DestroyWindow(window);
4436 static void test_wrong_shader(void)
4438 static const DWORD vs_3_0[] =
4440 0xfffe0300, /* vs_3_0 */
4441 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
4442 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
4443 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
4444 0x0000ffff, /* end */
4447 #if 0
4448 float4 main(const float4 color : COLOR) : SV_TARGET
4450 float4 o;
4452 o = color;
4454 return o;
4456 #endif
4457 static const DWORD ps_4_0[] =
4459 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
4460 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
4461 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
4462 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
4463 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
4464 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
4465 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
4466 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
4467 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
4468 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
4469 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
4470 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4471 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4472 0x00000000, 0x00000000, 0x00000000,
4475 IDirect3DVertexShader9 *vs = NULL;
4476 IDirect3DPixelShader9 *ps = NULL;
4477 IDirect3DDevice9 *device;
4478 IDirect3D9 * d3d;
4479 ULONG refcount;
4480 D3DCAPS9 caps;
4481 HWND window;
4482 HRESULT hr;
4484 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4486 skip("Failed to create D3D object, skipping tests.\n");
4487 return;
4490 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4491 0, 0, 640, 480, 0, 0, 0, 0);
4492 if (!(device = create_device(d3d, window, window, TRUE)))
4494 skip("Failed to create a D3D device, skipping tests.\n");
4495 IDirect3D9_Release(d3d);
4496 DestroyWindow(window);
4497 return;
4500 /* These should always fail, regardless of supported shader version. */
4501 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
4502 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4503 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
4504 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4505 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
4506 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4508 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4509 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4510 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
4512 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
4513 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4515 else
4516 skip("This GPU supports SM3, skipping unsupported shader test.\n");
4518 refcount = IDirect3DDevice9_Release(device);
4519 ok(!refcount, "Device has %u references left.\n", refcount);
4520 IDirect3D9_Release(d3d);
4521 DestroyWindow(window);
4524 /* Test the default texture stage state values */
4525 static void test_texture_stage_states(void)
4527 IDirect3DDevice9 *device;
4528 IDirect3D9 *d3d;
4529 unsigned int i;
4530 ULONG refcount;
4531 D3DCAPS9 caps;
4532 DWORD value;
4533 HWND window;
4534 HRESULT hr;
4536 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4538 skip("Failed to create D3D object, skipping tests.\n");
4539 return;
4542 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4543 0, 0, 640, 480, 0, 0, 0, 0);
4544 if (!(device = create_device(d3d, window, window, TRUE)))
4546 skip("Failed to create a D3D device, skipping tests.\n");
4547 IDirect3D9_Release(d3d);
4548 DestroyWindow(window);
4549 return;
4552 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4553 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4555 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
4557 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
4558 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4559 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
4560 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
4561 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
4562 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4563 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
4564 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
4565 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4566 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
4567 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
4568 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4569 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
4570 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
4571 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
4572 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4573 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
4574 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
4575 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4576 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
4577 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
4578 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4579 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
4580 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
4581 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4582 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
4583 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
4584 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4585 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
4586 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
4587 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4588 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
4589 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
4590 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4591 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
4592 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
4593 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4594 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
4595 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
4596 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4597 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
4598 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
4599 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4600 ok(value == D3DTTFF_DISABLE,
4601 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
4602 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
4603 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4604 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
4605 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
4606 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4607 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
4608 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
4609 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4610 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
4611 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
4612 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4613 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
4616 refcount = IDirect3DDevice9_Release(device);
4617 ok(!refcount, "Device has %u references left.\n", refcount);
4618 IDirect3D9_Release(d3d);
4619 DestroyWindow(window);
4622 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
4624 IDirect3DCubeTexture9 *texture;
4625 IDirect3D9 *d3d;
4626 HRESULT hr;
4628 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
4629 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
4630 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4631 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
4632 IDirect3D9_Release(d3d);
4633 if (FAILED(hr))
4635 skip("No cube mipmap generation support, skipping tests.\n");
4636 return;
4639 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4640 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4642 IDirect3DCubeTexture9_Release(texture);
4644 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4645 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4646 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4647 IDirect3DCubeTexture9_Release(texture);
4650 static void test_cube_texture_levels(IDirect3DDevice9 *device)
4652 IDirect3DCubeTexture9 *texture;
4653 IDirect3DSurface9 *surface;
4654 D3DSURFACE_DESC desc;
4655 DWORD levels;
4656 HRESULT hr;
4657 D3DCAPS9 caps;
4659 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4660 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4661 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
4662 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
4664 skip("Failed to create cube texture, skipping tests.\n");
4665 return;
4668 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
4669 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
4670 ok(levels == 7, "Got unexpected levels %u.\n", levels);
4671 else
4672 ok(levels == 1, "Got unexpected levels %u.\n", levels);
4674 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
4675 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4676 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
4677 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4678 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
4679 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4681 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
4682 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4683 IDirect3DSurface9_Release(surface);
4684 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
4685 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4686 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
4687 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4689 IDirect3DCubeTexture9_Release(texture);
4692 static void test_cube_textures(void)
4694 IDirect3DCubeTexture9 *texture;
4695 IDirect3DDevice9 *device;
4696 IDirect3D9 *d3d;
4697 ULONG refcount;
4698 D3DCAPS9 caps;
4699 HWND window;
4700 HRESULT hr;
4702 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4704 skip("Failed to create D3D object, skipping tests.\n");
4705 return;
4708 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4709 0, 0, 640, 480, 0, 0, 0, 0);
4710 if (!(device = create_device(d3d, window, window, TRUE)))
4712 skip("Failed to create a D3D device, skipping tests.\n");
4713 IDirect3D9_Release(d3d);
4714 DestroyWindow(window);
4715 return;
4718 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4719 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4721 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
4723 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4724 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
4725 IDirect3DCubeTexture9_Release(texture);
4726 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4727 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
4728 IDirect3DCubeTexture9_Release(texture);
4729 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4730 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
4731 IDirect3DCubeTexture9_Release(texture);
4733 else
4735 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4736 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
4737 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4738 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
4739 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4740 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
4742 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
4743 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
4744 IDirect3DCubeTexture9_Release(texture);
4746 test_cube_texture_mipmap_gen(device);
4747 test_cube_texture_levels(device);
4749 refcount = IDirect3DDevice9_Release(device);
4750 ok(!refcount, "Device has %u references left.\n", refcount);
4751 IDirect3D9_Release(d3d);
4752 DestroyWindow(window);
4755 static void test_mipmap_gen(void)
4757 D3DTEXTUREFILTERTYPE filter_type;
4758 IDirect3DTexture9 *texture;
4759 IDirect3DSurface9 *surface;
4760 IDirect3DDevice9 *device;
4761 D3DSURFACE_DESC desc;
4762 D3DLOCKED_RECT lr;
4763 IDirect3D9 *d3d;
4764 ULONG refcount;
4765 unsigned int i;
4766 DWORD levels;
4767 HWND window;
4768 HRESULT hr;
4770 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4772 skip("Failed to create D3D object, skipping tests.\n");
4773 return;
4776 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4777 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
4779 skip("No mipmap generation support, skipping tests.\n");
4780 IDirect3D9_Release(d3d);
4781 return;
4784 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4785 0, 0, 640, 480, 0, 0, 0, 0);
4786 if (!(device = create_device(d3d, window, window, TRUE)))
4788 skip("Failed to create a D3D device, skipping tests.\n");
4789 IDirect3D9_Release(d3d);
4790 DestroyWindow(window);
4791 return;
4794 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4795 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4796 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4797 IDirect3DTexture9_Release(texture);
4799 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4800 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4801 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4803 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4804 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
4805 "Got unexpected filter_type %#x.\n", filter_type);
4806 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
4807 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4808 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
4809 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4810 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4811 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
4812 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
4813 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4815 levels = IDirect3DTexture9_GetLevelCount(texture);
4816 ok(levels == 1, "Got unexpected levels %u.\n", levels);
4818 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
4820 surface = NULL;
4821 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
4822 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4823 if (surface)
4824 IDirect3DSurface9_Release(surface);
4826 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
4827 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4829 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
4830 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4831 if (SUCCEEDED(hr))
4833 hr = IDirect3DTexture9_UnlockRect(texture, i);
4834 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
4837 IDirect3DTexture9_Release(texture);
4839 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
4840 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4841 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4842 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
4843 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4844 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4846 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
4847 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4848 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4849 levels = IDirect3DTexture9_GetLevelCount(texture);
4850 ok(levels == 1, "Got unexpected levels %u.\n", levels);
4851 IDirect3DTexture9_Release(texture);
4853 refcount = IDirect3DDevice9_Release(device);
4854 ok(!refcount, "Device has %u references left.\n", refcount);
4855 IDirect3D9_Release(d3d);
4856 DestroyWindow(window);
4859 static void test_filter(void)
4861 static const struct
4863 DWORD magfilter, minfilter, mipfilter;
4864 BOOL has_texture;
4865 HRESULT result;
4867 tests[] =
4869 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4870 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4871 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4872 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
4873 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
4875 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4876 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4877 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
4878 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
4880 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4881 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4882 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
4883 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
4884 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
4886 IDirect3DTexture9 *texture;
4887 IDirect3DDevice9 *device;
4888 IDirect3D9 *d3d;
4889 unsigned int i;
4890 ULONG refcount;
4891 DWORD passes;
4892 HWND window;
4893 HRESULT hr;
4895 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4897 skip("Failed to create D3D object, skipping tests.\n");
4898 return;
4901 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4902 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4904 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
4905 IDirect3D9_Release(d3d);
4906 return;
4909 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4910 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4912 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
4913 IDirect3D9_Release(d3d);
4914 return;
4917 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4918 0, 0, 640, 480, 0, 0, 0, 0);
4919 if (!(device = create_device(d3d, window, window, TRUE)))
4921 skip("Failed to create a D3D device, skipping tests.\n");
4922 IDirect3D9_Release(d3d);
4923 DestroyWindow(window);
4924 return;
4927 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
4928 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
4929 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4931 /* Needed for ValidateDevice(). */
4932 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4933 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
4935 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
4937 if (tests[i].has_texture)
4939 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
4940 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4942 else
4944 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4945 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4948 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
4949 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4950 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
4951 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4952 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
4953 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4955 passes = 0xdeadbeef;
4956 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
4957 ok(hr == tests[i].result,
4958 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
4959 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
4960 tests[i].mipfilter, tests[i].has_texture);
4961 if (SUCCEEDED(hr))
4962 ok(!!passes, "Got unexpected passes %#x.\n", passes);
4963 else
4964 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
4967 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4968 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4969 IDirect3DTexture9_Release(texture);
4971 refcount = IDirect3DDevice9_Release(device);
4972 ok(!refcount, "Device has %u references left.\n", refcount);
4973 IDirect3D9_Release(d3d);
4974 DestroyWindow(window);
4977 static void test_get_texture(void)
4979 IDirect3DBaseTexture9 *texture;
4980 IDirect3DDevice9 *device;
4981 IDirect3D9 *d3d;
4982 ULONG refcount;
4983 HWND window;
4984 HRESULT hr;
4986 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
4988 skip("Failed to create D3D object, skipping tests.\n");
4989 return;
4992 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4993 0, 0, 640, 480, 0, 0, 0, 0);
4994 if (!(device = create_device(d3d, window, window, TRUE)))
4996 skip("Failed to create a D3D device, skipping tests.\n");
4997 IDirect3D9_Release(d3d);
4998 DestroyWindow(window);
4999 return;
5002 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
5003 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5004 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5005 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
5006 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5007 ok(!texture, "Got unexpected texture %p.\n", texture);
5009 refcount = IDirect3DDevice9_Release(device);
5010 ok(!refcount, "Device has %u references left.\n", refcount);
5011 IDirect3D9_Release(d3d);
5012 DestroyWindow(window);
5015 static void test_lod(void)
5017 IDirect3DTexture9 *texture;
5018 IDirect3DDevice9 *device;
5019 IDirect3D9 *d3d;
5020 ULONG refcount;
5021 HWND window;
5022 HRESULT hr;
5023 DWORD ret;
5025 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5027 skip("Failed to create D3D object, skipping tests.\n");
5028 return;
5031 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5032 0, 0, 640, 480, 0, 0, 0, 0);
5033 if (!(device = create_device(d3d, window, window, TRUE)))
5035 skip("Failed to create a D3D device, skipping tests.\n");
5036 IDirect3D9_Release(d3d);
5037 DestroyWindow(window);
5038 return;
5041 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
5042 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5043 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5045 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
5046 * return a HRESULT, so it can't return a normal error. Instead, the call
5047 * is simply ignored. */
5048 ret = IDirect3DTexture9_SetLOD(texture, 0);
5049 ok(!ret, "Got unexpected ret %u.\n", ret);
5050 ret = IDirect3DTexture9_SetLOD(texture, 1);
5051 ok(!ret, "Got unexpected ret %u.\n", ret);
5052 ret = IDirect3DTexture9_SetLOD(texture, 2);
5053 ok(!ret, "Got unexpected ret %u.\n", ret);
5054 ret = IDirect3DTexture9_GetLOD(texture);
5055 ok(!ret, "Got unexpected ret %u.\n", ret);
5057 IDirect3DTexture9_Release(texture);
5058 refcount = IDirect3DDevice9_Release(device);
5059 ok(!refcount, "Device has %u references left.\n", refcount);
5060 IDirect3D9_Release(d3d);
5061 DestroyWindow(window);
5064 static void test_surface_get_container(void)
5066 IDirect3DTexture9 *texture = NULL;
5067 IDirect3DSurface9 *surface = NULL;
5068 IDirect3DDevice9 *device;
5069 IUnknown *container;
5070 IDirect3D9 *d3d;
5071 ULONG refcount;
5072 HWND window;
5073 HRESULT hr;
5075 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5077 skip("Failed to create D3D object, skipping tests.\n");
5078 return;
5081 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5082 0, 0, 640, 480, 0, 0, 0, 0);
5083 if (!(device = create_device(d3d, window, window, TRUE)))
5085 skip("Failed to create a D3D device, skipping tests.\n");
5086 IDirect3D9_Release(d3d);
5087 DestroyWindow(window);
5088 return;
5091 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
5092 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5093 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5094 ok(!!texture, "Got unexpected texture %p.\n", texture);
5096 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5097 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5098 ok(!!surface, "Got unexpected surface %p.\n", surface);
5100 /* These should work... */
5101 container = NULL;
5102 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
5103 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5104 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5105 IUnknown_Release(container);
5107 container = NULL;
5108 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
5109 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5110 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5111 IUnknown_Release(container);
5113 container = NULL;
5114 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
5115 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5116 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5117 IUnknown_Release(container);
5119 container = NULL;
5120 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
5121 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5122 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5123 IUnknown_Release(container);
5125 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5126 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
5127 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5128 ok(!container, "Got unexpected container %p.\n", container);
5130 IDirect3DSurface9_Release(surface);
5131 IDirect3DTexture9_Release(texture);
5132 refcount = IDirect3DDevice9_Release(device);
5133 ok(!refcount, "Device has %u references left.\n", refcount);
5134 IDirect3D9_Release(d3d);
5135 DestroyWindow(window);
5138 static void test_surface_alignment(void)
5140 IDirect3DSurface9 *surface;
5141 IDirect3DDevice9 *device;
5142 D3DLOCKED_RECT lr;
5143 unsigned int i, j;
5144 IDirect3D9 *d3d;
5145 ULONG refcount;
5146 HWND window;
5147 HRESULT hr;
5149 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5151 skip("Failed to create D3D object, skipping tests.\n");
5152 return;
5155 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5156 0, 0, 640, 480, 0, 0, 0, 0);
5157 if (!(device = create_device(d3d, window, window, TRUE)))
5159 skip("Failed to create a D3D device, skipping tests.\n");
5160 IDirect3D9_Release(d3d);
5161 DestroyWindow(window);
5162 return;
5165 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
5166 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
5167 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
5168 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5170 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5171 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5172 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
5173 /* Some applications also depend on the exact pitch, rather than just the
5174 * alignment. */
5175 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
5176 hr = IDirect3DSurface9_UnlockRect(surface);
5177 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5178 IDirect3DSurface9_Release(surface);
5180 for (i = 0; i < 5; ++i)
5182 IDirect3DTexture9 *texture;
5183 unsigned int level_count;
5184 D3DSURFACE_DESC desc;
5185 int expected_pitch;
5187 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
5188 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
5189 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5190 if (FAILED(hr))
5192 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
5193 continue;
5196 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
5197 for (j = 0; j < level_count; ++j)
5199 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
5200 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
5201 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
5202 hr = IDirect3DTexture9_UnlockRect(texture, j);
5203 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
5205 expected_pitch = ((desc.Width + 3) >> 2) << 3;
5206 if (i > 0)
5207 expected_pitch <<= 1;
5208 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
5209 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
5211 IDirect3DTexture9_Release(texture);
5214 refcount = IDirect3DDevice9_Release(device);
5215 ok(!refcount, "Device has %u references left.\n", refcount);
5216 IDirect3D9_Release(d3d);
5217 DestroyWindow(window);
5220 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
5221 * different from regular formats. This test verifies we return the correct
5222 * memory offsets. */
5223 static void test_lockrect_offset(void)
5225 static const struct
5227 D3DFORMAT format;
5228 const char *name;
5229 unsigned int block_width;
5230 unsigned int block_height;
5231 unsigned int block_size;
5233 dxt_formats[] =
5235 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
5236 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
5237 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
5238 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
5239 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
5240 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
5242 unsigned int expected_offset, offset, i;
5243 const RECT rect = {60, 60, 68, 68};
5244 IDirect3DSurface9 *surface;
5245 D3DLOCKED_RECT locked_rect;
5246 IDirect3DDevice9 *device;
5247 int expected_pitch;
5248 IDirect3D9 *d3d;
5249 ULONG refcount;
5250 HWND window;
5251 BYTE *base;
5252 HRESULT hr;
5254 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5256 skip("Failed to create D3D object, skipping tests.\n");
5257 return;
5260 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5261 0, 0, 640, 480, 0, 0, 0, 0);
5262 if (!(device = create_device(d3d, window, window, TRUE)))
5264 skip("Failed to create a D3D device, skipping tests.\n");
5265 IDirect3D9_Release(d3d);
5266 DestroyWindow(window);
5267 return;
5270 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
5272 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5273 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
5275 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
5276 continue;
5279 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5280 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
5281 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5283 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5284 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5286 base = locked_rect.pBits;
5287 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
5288 * dxt_formats[i].block_size;
5289 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
5290 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
5292 hr = IDirect3DSurface9_UnlockRect(surface);
5293 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5295 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5296 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5298 offset = (BYTE *)locked_rect.pBits - base;
5299 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
5300 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
5301 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
5302 offset, dxt_formats[i].name, expected_offset);
5304 hr = IDirect3DSurface9_UnlockRect(surface);
5305 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5307 IDirect3DSurface9_Release(surface);
5310 refcount = IDirect3DDevice9_Release(device);
5311 ok(!refcount, "Device has %u references left.\n", refcount);
5312 IDirect3D9_Release(d3d);
5313 DestroyWindow(window);
5316 static void test_lockrect_invalid(void)
5318 static const struct
5320 RECT rect;
5321 HRESULT win7_result;
5323 test_data[] =
5325 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
5326 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
5327 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
5328 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
5329 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
5330 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
5331 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
5332 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
5333 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
5334 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
5335 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
5336 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
5337 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
5339 static const RECT test_rect_2 = {0, 0, 8, 8};
5340 IDirect3DSurface9 *surface = NULL;
5341 D3DLOCKED_RECT locked_rect;
5342 IDirect3DDevice9 *device;
5343 IDirect3D9 *d3d;
5344 unsigned int i;
5345 ULONG refcount;
5346 HWND window;
5347 BYTE *base;
5348 HRESULT hr;
5350 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5352 skip("Failed to create D3D object, skipping tests.\n");
5353 return;
5356 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5357 0, 0, 640, 480, 0, 0, 0, 0);
5358 if (!(device = create_device(d3d, window, window, TRUE)))
5360 skip("Failed to create a D3D device, skipping tests.\n");
5361 IDirect3D9_Release(d3d);
5362 DestroyWindow(window);
5363 return;
5366 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5367 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5368 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5369 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5370 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5371 base = locked_rect.pBits;
5372 hr = IDirect3DSurface9_UnlockRect(surface);
5373 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5375 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5377 unsigned int offset, expected_offset;
5378 const RECT *rect = &test_data[i].rect;
5380 locked_rect.pBits = (BYTE *)0xdeadbeef;
5381 locked_rect.Pitch = 0xdeadbeef;
5383 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
5384 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
5385 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
5386 * one broken. */
5387 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
5388 "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
5389 rect->left, rect->top, rect->right, rect->bottom, hr);
5390 if (FAILED(hr))
5391 continue;
5393 offset = (BYTE *)locked_rect.pBits - base;
5394 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5395 ok(offset == expected_offset,
5396 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
5397 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
5399 hr = IDirect3DSurface9_UnlockRect(surface);
5400 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5403 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5404 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
5405 locked_rect.pBits = (BYTE *)0xdeadbeef;
5406 locked_rect.Pitch = 1;
5407 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5408 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5409 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p\n",
5410 locked_rect.pBits);
5411 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d\n", locked_rect.Pitch);
5412 hr = IDirect3DSurface9_UnlockRect(surface);
5413 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5415 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
5416 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5417 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
5418 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
5419 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5420 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
5421 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
5422 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5423 hr, test_rect_2.left, test_rect_2.top, test_rect_2.right, test_rect_2.bottom);
5424 hr = IDirect3DSurface9_UnlockRect(surface);
5425 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5427 IDirect3DSurface9_Release(surface);
5428 refcount = IDirect3DDevice9_Release(device);
5429 ok(!refcount, "Device has %u references left.\n", refcount);
5430 IDirect3D9_Release(d3d);
5431 DestroyWindow(window);
5434 static void test_private_data(void)
5436 ULONG refcount, expected_refcount;
5437 IDirect3DSurface9 *surface;
5438 IDirect3DDevice9 *device;
5439 IDirect3D9 *d3d;
5440 IUnknown *ptr;
5441 HWND window;
5442 HRESULT hr;
5443 DWORD size;
5445 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5447 skip("Failed to create D3D object, skipping tests.\n");
5448 return;
5451 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5452 0, 0, 640, 480, 0, 0, 0, 0);
5453 if (!(device = create_device(d3d, window, window, TRUE)))
5455 skip("Failed to create a D3D device, skipping tests.\n");
5456 IDirect3D9_Release(d3d);
5457 DestroyWindow(window);
5458 return;
5461 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
5462 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5463 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5465 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5466 device, 0, D3DSPD_IUNKNOWN);
5467 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5468 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5469 device, 5, D3DSPD_IUNKNOWN);
5470 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5471 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5472 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
5473 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5475 refcount = get_refcount((IUnknown *)device);
5476 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5477 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5478 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5479 expected_refcount = refcount + 1;
5480 refcount = get_refcount((IUnknown *)device);
5481 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5482 hr = IDirect3DSurface9_FreePrivateData(surface, &IID_IDirect3DSurface9);
5483 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5484 expected_refcount = refcount - 1;
5485 refcount = get_refcount((IUnknown *)device);
5486 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5488 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5489 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5490 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5491 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5492 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5493 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5494 refcount = get_refcount((IUnknown *)device);
5495 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5497 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5498 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5499 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5500 size = sizeof(ptr);
5501 hr = IDirect3DSurface9_GetPrivateData(surface, &IID_IDirect3DSurface9, &ptr, &size);
5502 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5503 expected_refcount = refcount + 2;
5504 refcount = get_refcount((IUnknown *)device);
5505 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5506 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
5507 IUnknown_Release(ptr);
5509 /* Destroying the surface frees the held reference. */
5510 IDirect3DSurface9_Release(surface);
5511 expected_refcount = refcount - 3;
5512 refcount = get_refcount((IUnknown *)device);
5513 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5515 refcount = IDirect3DDevice9_Release(device);
5516 ok(!refcount, "Device has %u references left.\n", refcount);
5517 IDirect3D9_Release(d3d);
5518 DestroyWindow(window);
5521 static void test_getdc(void)
5523 static const struct
5525 const char *name;
5526 D3DFORMAT format;
5527 BOOL getdc_supported;
5529 testdata[] =
5531 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, TRUE },
5532 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, TRUE },
5533 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, TRUE },
5534 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, TRUE },
5535 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, TRUE },
5536 {"D3DFMT_R8G8B8", D3DFMT_R8G8B8, TRUE },
5537 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, FALSE}, /* Untested, card on windows didn't support it. */
5538 {"D3DFMT_V8U8", D3DFMT_V8U8, FALSE},
5539 {"D3DFMT_Q8W8V8U8", D3DFMT_Q8W8V8U8, FALSE},
5540 {"D3DFMT_A8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
5541 {"D3DFMT_X8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
5542 {"D3DFMT_R3G3B2", D3DFMT_R3G3B2, FALSE},
5543 {"D3DFMT_P8", D3DFMT_P8, FALSE},
5544 {"D3DFMT_L8", D3DFMT_L8, FALSE},
5545 {"D3DFMT_A8L8", D3DFMT_A8L8, FALSE},
5546 {"D3DFMT_DXT1", D3DFMT_DXT1, FALSE},
5547 {"D3DFMT_DXT2", D3DFMT_DXT2, FALSE},
5548 {"D3DFMT_DXT3", D3DFMT_DXT3, FALSE},
5549 {"D3DFMT_DXT4", D3DFMT_DXT4, FALSE},
5550 {"D3DFMT_DXT5", D3DFMT_DXT5, FALSE},
5552 IDirect3DTexture9 *texture;
5553 IDirect3DSurface9 *surface;
5554 IDirect3DDevice9 *device;
5555 IDirect3D9 *d3d;
5556 unsigned int i;
5557 ULONG refcount;
5558 HWND window;
5559 HRESULT hr;
5560 HDC dc;
5562 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5564 skip("Failed to create D3D object, skipping tests.\n");
5565 return;
5568 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5569 0, 0, 640, 480, 0, 0, 0, 0);
5570 if (!(device = create_device(d3d, window, window, TRUE)))
5572 skip("Failed to create a D3D device, skipping tests.\n");
5573 IDirect3D9_Release(d3d);
5574 DestroyWindow(window);
5575 return;
5578 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
5580 texture = NULL;
5581 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5582 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
5583 if (FAILED(hr))
5585 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
5586 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
5587 if (FAILED(hr))
5589 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
5590 continue;
5592 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5593 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5596 dc = (void *)0x1234;
5597 hr = IDirect3DSurface9_GetDC(surface, &dc);
5598 if (testdata[i].getdc_supported)
5599 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5600 else
5601 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5603 if (SUCCEEDED(hr))
5605 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
5606 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
5608 else
5610 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
5613 IDirect3DSurface9_Release(surface);
5614 if (texture)
5615 IDirect3DTexture9_Release(texture);
5618 refcount = IDirect3DDevice9_Release(device);
5619 ok(!refcount, "Device has %u references left.\n", refcount);
5620 IDirect3D9_Release(d3d);
5621 DestroyWindow(window);
5624 static void test_surface_dimensions(void)
5626 IDirect3DSurface9 *surface;
5627 IDirect3DDevice9 *device;
5628 IDirect3D9 *d3d;
5629 ULONG refcount;
5630 HWND window;
5631 HRESULT hr;
5633 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5635 skip("Failed to create D3D object, skipping tests.\n");
5636 return;
5639 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5640 0, 0, 640, 480, 0, 0, 0, 0);
5641 if (!(device = create_device(d3d, window, window, TRUE)))
5643 skip("Failed to create a D3D device, skipping tests.\n");
5644 IDirect3D9_Release(d3d);
5645 DestroyWindow(window);
5646 return;
5649 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
5650 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5651 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5652 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
5653 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5654 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5656 refcount = IDirect3DDevice9_Release(device);
5657 ok(!refcount, "Device has %u references left.\n", refcount);
5658 IDirect3D9_Release(d3d);
5659 DestroyWindow(window);
5662 static void test_surface_format_null(void)
5664 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
5665 IDirect3DTexture9 *texture;
5666 IDirect3DSurface9 *surface;
5667 IDirect3DSurface9 *rt, *ds;
5668 D3DLOCKED_RECT locked_rect;
5669 IDirect3DDevice9 *device;
5670 D3DSURFACE_DESC desc;
5671 IDirect3D9 *d3d;
5672 ULONG refcount;
5673 HWND window;
5674 HRESULT hr;
5676 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5678 skip("Failed to create D3D object, skipping tests.\n");
5679 return;
5682 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5683 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
5684 if (hr != D3D_OK)
5686 skip("No D3DFMT_NULL support, skipping test.\n");
5687 IDirect3D9_Release(d3d);
5688 return;
5691 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5692 0, 0, 640, 480, 0, 0, 0, 0);
5693 if (!(device = create_device(d3d, window, window, TRUE)))
5695 skip("Failed to create a D3D device, skipping tests.\n");
5696 IDirect3D9_Release(d3d);
5697 DestroyWindow(window);
5698 return;
5701 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5702 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
5703 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
5705 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5706 D3DFMT_NULL, D3DFMT_D24S8);
5707 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
5709 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
5710 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5711 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5713 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
5714 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
5716 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
5717 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
5719 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
5720 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
5722 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
5723 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5725 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
5726 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5728 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
5729 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
5731 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5732 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5734 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
5735 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5737 IDirect3DSurface9_Release(rt);
5738 IDirect3DSurface9_Release(ds);
5740 hr = IDirect3DSurface9_GetDesc(surface, &desc);
5741 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5742 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
5743 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
5745 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5746 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5747 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
5748 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
5750 hr = IDirect3DSurface9_UnlockRect(surface);
5751 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5753 IDirect3DSurface9_Release(surface);
5755 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
5756 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
5757 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5758 IDirect3DTexture9_Release(texture);
5760 refcount = IDirect3DDevice9_Release(device);
5761 ok(!refcount, "Device has %u references left.\n", refcount);
5762 IDirect3D9_Release(d3d);
5763 DestroyWindow(window);
5766 static void test_surface_double_unlock(void)
5768 static const D3DPOOL pools[] =
5770 D3DPOOL_DEFAULT,
5771 D3DPOOL_SCRATCH,
5772 D3DPOOL_SYSTEMMEM,
5774 IDirect3DSurface9 *surface;
5775 IDirect3DDevice9 *device;
5776 D3DLOCKED_RECT lr;
5777 IDirect3D9 *d3d;
5778 unsigned int i;
5779 ULONG refcount;
5780 HWND window;
5781 HRESULT hr;
5783 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5785 skip("Failed to create D3D object, skipping tests.\n");
5786 return;
5789 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5790 0, 0, 640, 480, 0, 0, 0, 0);
5791 if (!(device = create_device(d3d, window, window, TRUE)))
5793 skip("Failed to create a D3D device, skipping tests.\n");
5794 IDirect3D9_Release(d3d);
5795 DestroyWindow(window);
5796 return;
5799 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
5801 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5802 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
5803 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
5805 hr = IDirect3DSurface9_UnlockRect(surface);
5806 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5807 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5808 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
5809 hr = IDirect3DSurface9_UnlockRect(surface);
5810 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
5811 hr = IDirect3DSurface9_UnlockRect(surface);
5812 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5814 IDirect3DSurface9_Release(surface);
5817 refcount = IDirect3DDevice9_Release(device);
5818 ok(!refcount, "Device has %u references left.\n", refcount);
5819 IDirect3D9_Release(d3d);
5820 DestroyWindow(window);
5823 static void test_surface_blocks(void)
5825 static const struct
5827 D3DFORMAT fmt;
5828 const char *name;
5829 unsigned int block_width;
5830 unsigned int block_height;
5831 BOOL broken;
5832 BOOL create_size_checked, core_fmt;
5834 formats[] =
5836 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
5837 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
5838 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
5839 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
5840 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
5841 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
5842 * which doesn't match the format spec. On newer Nvidia cards
5843 * it has the correct 4x4 block size */
5844 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
5845 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
5846 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
5848 static const struct
5850 D3DPOOL pool;
5851 const char *name;
5852 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
5853 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
5854 BOOL success;
5856 pools[] =
5858 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
5859 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
5860 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
5861 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
5863 static struct
5865 D3DRESOURCETYPE rtype;
5866 const char *type_name;
5867 D3DPOOL pool;
5868 const char *pool_name;
5869 BOOL need_driver_support, need_runtime_support;
5871 create_tests[] =
5873 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
5874 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
5875 /* Managed offscreen plain surfaces are not supported */
5876 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5878 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
5879 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
5880 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
5881 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5883 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
5884 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
5885 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
5886 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5888 IDirect3DTexture9 *texture;
5889 IDirect3DCubeTexture9 *cube_texture;
5890 IDirect3DSurface9 *surface;
5891 D3DLOCKED_RECT locked_rect;
5892 IDirect3DDevice9 *device;
5893 unsigned int i, j, w, h;
5894 BOOL surface_only;
5895 IDirect3D9 *d3d;
5896 ULONG refcount;
5897 HWND window;
5898 HRESULT hr;
5899 RECT rect;
5900 BOOL tex_pow2, cube_pow2;
5901 D3DCAPS9 caps;
5903 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
5905 skip("Failed to create D3D object, skipping tests.\n");
5906 return;
5909 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5910 0, 0, 640, 480, 0, 0, 0, 0);
5911 if (!(device = create_device(d3d, window, window, TRUE)))
5913 skip("Failed to create a D3D device, skipping tests.\n");
5914 IDirect3D9_Release(d3d);
5915 DestroyWindow(window);
5916 return;
5919 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5920 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5921 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
5922 if (tex_pow2)
5923 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
5924 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
5926 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
5928 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
5930 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5931 0, D3DRTYPE_TEXTURE, formats[i].fmt);
5932 tex_support = SUCCEEDED(hr);
5933 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5934 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
5935 cube_support = SUCCEEDED(hr);
5936 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5937 0, D3DRTYPE_SURFACE, formats[i].fmt);
5938 surface_support = SUCCEEDED(hr);
5940 /* Scratch pool in general allows texture creation even if the driver does
5941 * not support the format. If the format is an extension format that is not
5942 * known to the runtime, like ATI2N, some driver support is required for
5943 * this to work.
5945 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
5946 * about ATI2N. I cannot check this because all my Vista+ machines support
5947 * ATI2N in hardware, but none of my WinXP machines do. */
5948 format_known = tex_support || cube_support || surface_support;
5950 for (w = 1; w <= 8; w++)
5952 for (h = 1; h <= 8; h++)
5954 BOOL block_aligned = TRUE;
5955 BOOL size_is_pow2;
5957 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5958 block_aligned = FALSE;
5960 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
5962 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
5964 BOOL support, pow2;
5965 HRESULT expect_hr;
5966 BOOL may_succeed = FALSE;
5967 IUnknown **check_null;
5969 if (!formats[i].core_fmt)
5971 /* AMD warns against creating ATI2N textures smaller than
5972 * the block size because the runtime cannot calculate the
5973 * correct texture size. Generalize this for all extension
5974 * formats. */
5975 if (w < formats[i].block_width || h < formats[i].block_height)
5976 continue;
5979 texture = (IDirect3DTexture9 *)0xdeadbeef;
5980 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
5981 surface = (IDirect3DSurface9 *)0xdeadbeef;
5983 switch (create_tests[j].rtype)
5985 case D3DRTYPE_TEXTURE:
5986 check_null = (IUnknown **)&texture;
5987 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
5988 formats[i].fmt, create_tests[j].pool, &texture, NULL);
5989 support = tex_support;
5990 pow2 = tex_pow2;
5991 break;
5993 case D3DRTYPE_CUBETEXTURE:
5994 if (w != h)
5995 continue;
5996 check_null = (IUnknown **)&cube_texture;
5997 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
5998 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
5999 support = cube_support;
6000 pow2 = cube_pow2;
6001 break;
6003 case D3DRTYPE_SURFACE:
6004 check_null = (IUnknown **)&surface;
6005 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
6006 formats[i].fmt, create_tests[j].pool, &surface, NULL);
6007 support = surface_support;
6008 pow2 = FALSE;
6009 break;
6011 default:
6012 check_null = NULL;
6013 pow2 = FALSE;
6014 support = FALSE;
6015 break;
6018 if (create_tests[j].need_driver_support && !support)
6019 expect_hr = D3DERR_INVALIDCALL;
6020 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
6021 expect_hr = D3DERR_INVALIDCALL;
6022 else if (formats[i].create_size_checked && !block_aligned)
6023 expect_hr = D3DERR_INVALIDCALL;
6024 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6025 expect_hr = D3DERR_INVALIDCALL;
6026 else
6027 expect_hr = D3D_OK;
6029 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6030 * does not support it. Accept scratch creation of extension formats on
6031 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6032 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6033 * support it. */
6034 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
6035 may_succeed = TRUE;
6037 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6038 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
6039 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
6040 if (FAILED(hr))
6041 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
6042 else
6043 IUnknown_Release(*check_null);
6048 surface_only = FALSE;
6049 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6050 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
6051 dynamic_tex_support = SUCCEEDED(hr);
6052 if (!dynamic_tex_support)
6054 if (!surface_support)
6056 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
6057 continue;
6059 surface_only = TRUE;
6062 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
6064 switch (pools[j].pool)
6066 case D3DPOOL_SYSTEMMEM:
6067 case D3DPOOL_MANAGED:
6068 if (surface_only)
6069 continue;
6070 /* Fall through */
6071 case D3DPOOL_DEFAULT:
6072 if (surface_only)
6074 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6075 formats[i].fmt, pools[j].pool, &surface, NULL);
6076 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6078 else
6080 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
6081 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
6082 formats[i].fmt, pools[j].pool, &texture, NULL);
6083 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6084 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6085 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
6086 IDirect3DTexture9_Release(texture);
6088 break;
6090 case D3DPOOL_SCRATCH:
6091 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6092 formats[i].fmt, pools[j].pool, &surface, NULL);
6093 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6094 break;
6096 default:
6097 break;
6100 if (formats[i].block_width > 1)
6102 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
6103 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6104 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6105 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6106 SUCCEEDED(hr) ? "succeeded" : "failed",
6107 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6108 if (SUCCEEDED(hr))
6110 hr = IDirect3DSurface9_UnlockRect(surface);
6111 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6114 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
6115 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6116 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6117 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6118 SUCCEEDED(hr) ? "succeeded" : "failed",
6119 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6120 if (SUCCEEDED(hr))
6122 hr = IDirect3DSurface9_UnlockRect(surface);
6123 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6127 if (formats[i].block_height > 1)
6129 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
6130 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6131 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6132 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6133 SUCCEEDED(hr) ? "succeeded" : "failed",
6134 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6135 if (SUCCEEDED(hr))
6137 hr = IDirect3DSurface9_UnlockRect(surface);
6138 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6141 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
6142 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6143 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6144 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6145 SUCCEEDED(hr) ? "succeeded" : "failed",
6146 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6147 if (SUCCEEDED(hr))
6149 hr = IDirect3DSurface9_UnlockRect(surface);
6150 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6154 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
6155 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6156 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
6157 hr = IDirect3DSurface9_UnlockRect(surface);
6158 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6160 IDirect3DSurface9_Release(surface);
6163 if (!dynamic_tex_support)
6165 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
6166 continue;
6169 if (formats[i].block_width == 1 && formats[i].block_height == 1)
6170 continue;
6171 if (!formats[i].core_fmt)
6172 continue;
6174 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
6175 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
6176 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
6178 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
6179 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6180 hr = IDirect3DTexture9_UnlockRect(texture, 1);
6181 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6183 rect.left = 0;
6184 rect.top = 0;
6185 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
6186 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
6187 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
6188 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6189 hr = IDirect3DTexture9_UnlockRect(texture, 1);
6190 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6192 rect.right = formats[i].block_width;
6193 rect.bottom = formats[i].block_height;
6194 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
6195 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6196 if (SUCCEEDED(hr))
6197 IDirect3DTexture9_UnlockRect(texture, 1);
6199 IDirect3DTexture9_Release(texture);
6202 refcount = IDirect3DDevice9_Release(device);
6203 ok(!refcount, "Device has %u references left.\n", refcount);
6204 IDirect3D9_Release(d3d);
6205 DestroyWindow(window);
6208 static void test_set_palette(void)
6210 IDirect3DDevice9 *device;
6211 IDirect3D9 *d3d9;
6212 UINT refcount;
6213 HWND window;
6214 HRESULT hr;
6215 PALETTEENTRY pal[256];
6216 unsigned int i;
6217 D3DCAPS9 caps;
6219 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6221 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6222 return;
6225 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6226 0, 0, 640, 480, 0, 0, 0, 0);
6227 if (!(device = create_device(d3d9, window, window, TRUE)))
6229 skip("Failed to create a D3D device, skipping tests.\n");
6230 DestroyWindow(window);
6231 return;
6234 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6236 pal[i].peRed = i;
6237 pal[i].peGreen = i;
6238 pal[i].peBlue = i;
6239 pal[i].peFlags = 0xff;
6241 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6242 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6244 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6245 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6246 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6248 pal[i].peRed = i;
6249 pal[i].peGreen = i;
6250 pal[i].peBlue = i;
6251 pal[i].peFlags = i;
6253 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
6255 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6256 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6258 else
6260 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6261 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
6264 refcount = IDirect3DDevice9_Release(device);
6265 ok(!refcount, "Device has %u references left.\n", refcount);
6266 IDirect3D9_Release(d3d9);
6267 DestroyWindow(window);
6270 static void test_swvp_buffer(void)
6272 IDirect3DDevice9 *device;
6273 IDirect3D9 *d3d9;
6274 UINT refcount;
6275 HWND window;
6276 HRESULT hr;
6277 unsigned int i;
6278 IDirect3DVertexBuffer9 *buffer;
6279 static const unsigned int bufsize = 1024;
6280 D3DVERTEXBUFFER_DESC desc;
6281 D3DPRESENT_PARAMETERS present_parameters = {0};
6282 struct
6284 float x, y, z;
6285 } *ptr, *ptr2;
6287 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6289 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6290 return;
6293 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6294 0, 0, 640, 480, 0, 0, 0, 0);
6296 present_parameters.Windowed = TRUE;
6297 present_parameters.hDeviceWindow = window;
6298 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
6299 present_parameters.BackBufferWidth = screen_width;
6300 present_parameters.BackBufferHeight = screen_height;
6301 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
6302 present_parameters.EnableAutoDepthStencil = FALSE;
6303 if (FAILED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
6304 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
6306 skip("Failed to create a D3D device, skipping tests.\n");
6307 DestroyWindow(window);
6308 IDirect3D9_Release(d3d9);
6309 return;
6312 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
6313 D3DPOOL_DEFAULT, &buffer, NULL);
6314 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6315 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
6316 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6317 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
6318 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
6319 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
6321 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
6322 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6323 for (i = 0; i < bufsize; i++)
6325 ptr[i].x = i * 1.0f;
6326 ptr[i].y = i * 2.0f;
6327 ptr[i].z = i * 3.0f;
6329 hr = IDirect3DVertexBuffer9_Unlock(buffer);
6330 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6332 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6333 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6334 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
6335 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6336 hr = IDirect3DDevice9_BeginScene(device);
6337 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6338 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6339 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6340 hr = IDirect3DDevice9_EndScene(device);
6341 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6343 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
6344 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6345 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
6346 for (i = 0; i < bufsize; i++)
6348 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6350 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
6351 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6352 break;
6355 hr = IDirect3DVertexBuffer9_Unlock(buffer);
6356 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6358 IDirect3DVertexBuffer9_Release(buffer);
6359 refcount = IDirect3DDevice9_Release(device);
6360 ok(!refcount, "Device has %u references left.\n", refcount);
6361 IDirect3D9_Release(d3d9);
6362 DestroyWindow(window);
6365 static void test_npot_textures(void)
6367 IDirect3DDevice9 *device = NULL;
6368 IDirect3D9 *d3d9;
6369 ULONG refcount;
6370 HWND window = NULL;
6371 HRESULT hr;
6372 D3DCAPS9 caps;
6373 IDirect3DTexture9 *texture;
6374 IDirect3DCubeTexture9 *cube_texture;
6375 IDirect3DVolumeTexture9 *volume_texture;
6376 struct
6378 D3DPOOL pool;
6379 const char *pool_name;
6380 HRESULT hr;
6382 pools[] =
6384 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
6385 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
6386 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
6387 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
6389 unsigned int i, levels;
6390 BOOL tex_pow2, cube_pow2, vol_pow2;
6392 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6394 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6395 return;
6398 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6399 0, 0, 640, 480, 0, 0, 0, 0);
6400 if (!(device = create_device(d3d9, window, window, TRUE)))
6402 skip("Failed to create a D3D device, skipping tests.\n");
6403 goto done;
6406 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6407 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6408 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
6409 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6410 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6411 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
6412 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
6414 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
6416 for (levels = 0; levels <= 2; levels++)
6418 HRESULT expected;
6420 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
6421 pools[i].pool, &texture, NULL);
6422 if (!tex_pow2)
6424 expected = D3D_OK;
6426 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
6428 if (levels == 1)
6429 expected = D3D_OK;
6430 else
6431 expected = pools[i].hr;
6433 else
6435 expected = pools[i].hr;
6437 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
6438 pools[i].pool_name, levels, hr, expected);
6440 if (SUCCEEDED(hr))
6441 IDirect3DTexture9_Release(texture);
6444 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
6445 &cube_texture, NULL);
6446 if (tex_pow2)
6448 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6449 pools[i].pool_name, hr, pools[i].hr);
6451 else
6453 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6454 pools[i].pool_name, hr, D3D_OK);
6457 if (SUCCEEDED(hr))
6458 IDirect3DCubeTexture9_Release(cube_texture);
6460 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
6461 &volume_texture, NULL);
6462 if (tex_pow2)
6464 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6465 pools[i].pool_name, hr, pools[i].hr);
6467 else
6469 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6470 pools[i].pool_name, hr, D3D_OK);
6473 if (SUCCEEDED(hr))
6474 IDirect3DVolumeTexture9_Release(volume_texture);
6477 done:
6478 if (device)
6480 refcount = IDirect3DDevice9_Release(device);
6481 ok(!refcount, "Device has %u references left.\n", refcount);
6483 IDirect3D9_Release(d3d9);
6484 DestroyWindow(window);
6488 static void test_vidmem_accounting(void)
6490 IDirect3DDevice9 *device;
6491 IDirect3D9 *d3d9;
6492 ULONG refcount;
6493 HWND window;
6494 HRESULT hr = D3D_OK;
6495 IDirect3DTexture9 *textures[20];
6496 unsigned int i;
6497 UINT vidmem_start, vidmem_end, diff;
6499 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6501 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6502 return;
6505 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6506 0, 0, 640, 480, 0, 0, 0, 0);
6507 if (!(device = create_device(d3d9, window, window, TRUE)))
6509 skip("Failed to create a D3D device, skipping tests.\n");
6510 IDirect3D9_Release(d3d9);
6511 DestroyWindow(window);
6512 return;
6515 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
6516 memset(textures, 0, sizeof(textures));
6517 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
6519 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
6520 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
6521 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
6522 * E_FAIL is returned on address space or system memory exhaustion */
6523 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
6524 "Failed to create texture, hr %#x.\n", hr);
6526 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
6528 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
6529 diff = vidmem_start - vidmem_end;
6530 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
6531 2 * i, diff / 1024 / 1024);
6533 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
6535 if (textures[i])
6536 IDirect3DTexture9_Release(textures[i]);
6539 refcount = IDirect3DDevice9_Release(device);
6540 ok(!refcount, "Device has %u references left.\n", refcount);
6541 IDirect3D9_Release(d3d9);
6542 DestroyWindow(window);
6545 static void test_volume_locking(void)
6547 IDirect3DDevice9 *device;
6548 IDirect3D9 *d3d9;
6549 HWND window;
6550 HRESULT hr;
6551 IDirect3DVolumeTexture9 *texture;
6552 unsigned int i;
6553 D3DLOCKED_BOX locked_box;
6554 ULONG refcount;
6555 D3DCAPS9 caps;
6556 static const struct
6558 D3DPOOL pool;
6559 DWORD usage;
6560 HRESULT create_hr, lock_hr;
6562 tests[] =
6564 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
6565 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6566 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
6567 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6568 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
6569 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6570 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
6571 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6574 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6576 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6577 return;
6580 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6581 0, 0, 640, 480, 0, 0, 0, 0);
6582 if (!(device = create_device(d3d9, window, window, TRUE)))
6584 skip("Failed to create a D3D device, skipping tests.\n");
6585 IDirect3D9_Release(d3d9);
6586 DestroyWindow(window);
6587 return;
6590 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6591 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6592 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6594 skip("Volume textures not supported, skipping test.\n");
6595 goto out;
6598 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6600 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
6601 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
6602 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
6603 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
6604 if (FAILED(hr))
6605 continue;
6607 locked_box.pBits = (void *)0xdeadbeef;
6608 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
6609 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
6610 if (SUCCEEDED(hr))
6612 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
6613 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6615 else
6617 ok (locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
6619 IDirect3DVolumeTexture9_Release(texture);
6622 out:
6623 refcount = IDirect3DDevice9_Release(device);
6624 ok(!refcount, "Device has %u references left.\n", refcount);
6625 IDirect3D9_Release(d3d9);
6626 DestroyWindow(window);
6629 static void test_update_volumetexture(void)
6631 IDirect3DDevice9 *device;
6632 IDirect3D9 *d3d9;
6633 HWND window;
6634 HRESULT hr;
6635 IDirect3DVolumeTexture9 *src, *dst;
6636 unsigned int i;
6637 D3DLOCKED_BOX locked_box;
6638 ULONG refcount;
6639 D3DCAPS9 caps;
6640 static const struct
6642 D3DPOOL src_pool, dst_pool;
6643 HRESULT hr;
6645 tests[] =
6647 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6648 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6649 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
6650 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6652 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6653 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6654 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6655 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6657 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6658 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6659 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6660 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6662 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6663 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6664 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6665 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6667 static const struct
6669 UINT src_size, dst_size;
6670 UINT src_lvl, dst_lvl;
6671 D3DFORMAT src_fmt, dst_fmt;
6673 tests2[] =
6675 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6676 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6677 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6678 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6679 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6680 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
6681 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
6682 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
6685 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6687 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6688 return;
6691 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6692 0, 0, 640, 480, 0, 0, 0, 0);
6693 if (!(device = create_device(d3d9, window, window, TRUE)))
6695 skip("Failed to create a D3D device, skipping tests.\n");
6696 IDirect3D9_Release(d3d9);
6697 DestroyWindow(window);
6698 return;
6701 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6702 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6703 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6705 skip("Volume textures not supported, skipping test.\n");
6706 goto out;
6709 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6711 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6712 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6714 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
6715 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
6716 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6717 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
6718 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
6719 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6721 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
6722 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6723 *((DWORD *)locked_box.pBits) = 0x11223344;
6724 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
6725 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6727 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
6728 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
6729 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
6731 if (SUCCEEDED(hr))
6733 DWORD content = *((DWORD *)locked_box.pBits);
6734 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
6735 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6736 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
6737 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
6738 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6740 IDirect3DVolumeTexture9_Release(src);
6741 IDirect3DVolumeTexture9_Release(dst);
6744 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
6746 skip("Mipmapped volume maps not supported.\n");
6747 goto out;
6750 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
6752 hr = IDirect3DDevice9_CreateVolumeTexture(device,
6753 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
6754 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
6755 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6756 hr = IDirect3DDevice9_CreateVolumeTexture(device,
6757 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
6758 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
6759 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6761 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
6762 if (FAILED(hr))
6763 todo_wine ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
6764 else
6765 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
6767 IDirect3DVolumeTexture9_Release(src);
6768 IDirect3DVolumeTexture9_Release(dst);
6771 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
6772 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
6773 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
6774 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
6775 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
6777 * I'm not adding tests for this behavior until an application needs it. */
6779 out:
6780 refcount = IDirect3DDevice9_Release(device);
6781 ok(!refcount, "Device has %u references left.\n", refcount);
6782 IDirect3D9_Release(d3d9);
6783 DestroyWindow(window);
6786 static void test_create_rt_ds_fail(void)
6788 IDirect3DDevice9 *device;
6789 HWND window;
6790 HRESULT hr;
6791 ULONG refcount;
6792 IDirect3D9 *d3d9;
6793 IDirect3DSurface9 *surface;
6795 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6797 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6798 return;
6801 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6802 0, 0, 640, 480, 0, 0, 0, 0);
6803 if (!(device = create_device(d3d9, window, window, TRUE)))
6805 skip("Failed to create a D3D device, skipping tests.\n");
6806 IDirect3D9_Release(d3d9);
6807 DestroyWindow(window);
6808 return;
6811 /* Output pointer == NULL segfaults on Windows. */
6813 surface = (IDirect3DSurface9 *)0xdeadbeef;
6814 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
6815 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
6816 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
6817 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6818 if (SUCCEEDED(hr))
6819 IDirect3DSurface9_Release(surface);
6821 surface = (IDirect3DSurface9 *)0xdeadbeef;
6822 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
6823 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
6824 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
6825 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6826 if (SUCCEEDED(hr))
6827 IDirect3DSurface9_Release(surface);
6829 refcount = IDirect3DDevice9_Release(device);
6830 ok(!refcount, "Device has %u references left.\n", refcount);
6831 IDirect3D9_Release(d3d9);
6832 DestroyWindow(window);
6835 static void test_volume_blocks(void)
6837 IDirect3DDevice9 *device;
6838 IDirect3D9 *d3d9;
6839 UINT refcount;
6840 HWND window;
6841 HRESULT hr;
6842 D3DCAPS9 caps;
6843 IDirect3DVolumeTexture9 *texture;
6844 unsigned int w, h, d, i, j;
6845 static const struct
6847 D3DFORMAT fmt;
6848 const char *name;
6849 unsigned int block_width;
6850 unsigned int block_height;
6851 unsigned int block_depth;
6852 unsigned int block_size;
6853 BOOL broken;
6854 BOOL create_size_checked, core_fmt;
6856 formats[] =
6858 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
6859 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
6860 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, FALSE, TRUE, TRUE },
6861 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6862 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6863 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6864 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6865 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6866 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
6867 * which doesn't match the format spec. On newer Nvidia cards
6868 * it has the correct 4x4 block size */
6869 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, TRUE, FALSE, FALSE},
6870 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, TRUE, FALSE, TRUE },
6871 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, TRUE, FALSE, TRUE },
6873 static const struct
6875 D3DPOOL pool;
6876 const char *name;
6877 BOOL need_driver_support, need_runtime_support;
6879 create_tests[] =
6881 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6882 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6883 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
6884 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
6886 static const struct
6888 unsigned int x, y, z, x2, y2, z2;
6890 offset_tests[] =
6892 {0, 0, 0, 8, 8, 8},
6893 {0, 0, 3, 8, 8, 8},
6894 {0, 4, 0, 8, 8, 8},
6895 {0, 4, 3, 8, 8, 8},
6896 {4, 0, 0, 8, 8, 8},
6897 {4, 0, 3, 8, 8, 8},
6898 {4, 4, 0, 8, 8, 8},
6899 {4, 4, 3, 8, 8, 8},
6901 D3DBOX box;
6902 D3DLOCKED_BOX locked_box;
6903 BYTE *base;
6904 INT expected_row_pitch, expected_slice_pitch;
6905 BOOL support, support_2d;
6906 BOOL pow2;
6907 unsigned int offset, expected_offset;
6909 if (!(d3d9 = pDirect3DCreate9(D3D_SDK_VERSION)))
6911 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6912 return;
6915 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6916 0, 0, 640, 480, 0, 0, 0, 0);
6917 if (!(device = create_device(d3d9, window, window, TRUE)))
6919 skip("Failed to create a D3D device, skipping tests.\n");
6920 IDirect3D9_Release(d3d9);
6921 DestroyWindow(window);
6922 return;
6924 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6925 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6926 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6928 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
6930 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6931 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
6932 support = SUCCEEDED(hr);
6933 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6934 0, D3DRTYPE_TEXTURE, formats[i].fmt);
6935 support_2d = SUCCEEDED(hr);
6937 /* Test creation restrictions */
6938 for (w = 1; w <= 8; w++)
6940 for (h = 1; h <= 8; h++)
6942 for (d = 1; d <= 8; d++)
6944 HRESULT expect_hr;
6945 BOOL size_is_pow2;
6946 BOOL block_aligned = TRUE;
6948 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6949 block_aligned = FALSE;
6951 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
6953 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
6955 BOOL may_succeed = FALSE;
6956 BOOL todo = FALSE;
6958 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
6959 expect_hr = D3DERR_INVALIDCALL;
6960 else if (formats[i].create_size_checked && !block_aligned)
6961 expect_hr = D3DERR_INVALIDCALL;
6962 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6963 expect_hr = D3DERR_INVALIDCALL;
6964 else if (create_tests[j].need_driver_support && !support)
6966 todo = support_2d;
6967 expect_hr = D3DERR_INVALIDCALL;
6969 else
6970 expect_hr = D3D_OK;
6972 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
6973 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
6974 formats[i].fmt, create_tests[j].pool, &texture, NULL);
6976 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6977 * does not support it. Accept scratch creation of extension formats on
6978 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6979 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6980 * support it. */
6981 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
6982 may_succeed = TRUE;
6984 if (todo)
6986 todo_wine ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6987 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
6988 hr, formats[i].name, create_tests[j].name, w, h, d);
6990 else
6992 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6993 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
6994 hr, formats[i].name, create_tests[j].name, w, h, d);
6997 if (FAILED(hr))
6998 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
6999 else
7000 IDirect3DVolumeTexture9_Release(texture);
7006 if (!support && !formats[i].core_fmt)
7007 continue;
7009 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
7010 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
7011 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7013 /* Test lockrect offset */
7014 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
7016 unsigned int bytes_per_pixel;
7017 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
7019 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7020 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7022 base = locked_box.pBits;
7023 if (formats[i].broken)
7025 expected_row_pitch = bytes_per_pixel * 24;
7027 else
7029 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
7030 * formats[i].block_size;
7032 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
7033 locked_box.RowPitch, formats[i].name, expected_row_pitch);
7035 if (formats[i].broken)
7037 expected_slice_pitch = expected_row_pitch * 8;
7039 else
7041 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
7042 * expected_row_pitch;
7044 ok(locked_box.SlicePitch == expected_slice_pitch,
7045 "Got unexpected slice pitch %d for format %s, expected %d.\n",
7046 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
7048 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7049 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
7051 box.Left = offset_tests[j].x;
7052 box.Top = offset_tests[j].y;
7053 box.Front = offset_tests[j].z;
7054 box.Right = offset_tests[j].x2;
7055 box.Bottom = offset_tests[j].y2;
7056 box.Back = offset_tests[j].z2;
7057 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7058 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
7060 offset = (BYTE *)locked_box.pBits - base;
7061 if (formats[i].broken)
7063 expected_offset = box.Front * expected_slice_pitch
7064 + box.Top * expected_row_pitch
7065 + box.Left * bytes_per_pixel;
7067 else
7069 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
7070 + (box.Top / formats[i].block_height) * expected_row_pitch
7071 + (box.Left / formats[i].block_width) * formats[i].block_size;
7073 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
7074 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
7076 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7077 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7080 /* Test partial block locks */
7081 box.Front = 0;
7082 box.Back = 1;
7083 if (formats[i].block_width > 1)
7085 box.Left = formats[i].block_width >> 1;
7086 box.Top = 0;
7087 box.Right = formats[i].block_width;
7088 box.Bottom = formats[i].block_height;
7089 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7090 ok(FAILED(hr) || broken(formats[i].broken),
7091 "Partial block lock succeeded, expected failure, format %s.\n",
7092 formats[i].name);
7093 if (SUCCEEDED(hr))
7095 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7096 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7099 box.Left = 0;
7100 box.Top = 0;
7101 box.Right = formats[i].block_width >> 1;
7102 box.Bottom = formats[i].block_height;
7103 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7104 ok(FAILED(hr) || broken(formats[i].broken),
7105 "Partial block lock succeeded, expected failure, format %s.\n",
7106 formats[i].name);
7107 if (SUCCEEDED(hr))
7109 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7110 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7114 if (formats[i].block_height > 1)
7116 box.Left = 0;
7117 box.Top = formats[i].block_height >> 1;
7118 box.Right = formats[i].block_width;
7119 box.Bottom = formats[i].block_height;
7120 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7121 ok(FAILED(hr) || broken(formats[i].broken),
7122 "Partial block lock succeeded, expected failure, format %s.\n",
7123 formats[i].name);
7124 if (SUCCEEDED(hr))
7126 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7127 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7130 box.Left = 0;
7131 box.Top = 0;
7132 box.Right = formats[i].block_width;
7133 box.Bottom = formats[i].block_height >> 1;
7134 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7135 ok(FAILED(hr) || broken(formats[i].broken),
7136 "Partial block lock succeeded, expected failure, format %s.\n",
7137 formats[i].name);
7138 if (SUCCEEDED(hr))
7140 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7141 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7145 /* Test full block lock */
7146 box.Left = 0;
7147 box.Top = 0;
7148 box.Right = formats[i].block_width;
7149 box.Bottom = formats[i].block_height;
7150 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7151 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7152 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7153 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7155 IDirect3DVolumeTexture9_Release(texture);
7157 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
7158 * does not allocate surfaces smaller than the blocksize properly. */
7159 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
7161 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
7162 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
7164 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
7165 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
7166 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7167 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7169 box.Left = box.Top = box.Front = 0;
7170 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
7171 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
7172 box.Back = 1;
7173 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
7174 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
7175 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7176 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7178 box.Right = formats[i].block_width;
7179 box.Bottom = formats[i].block_height;
7180 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
7181 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7182 if (SUCCEEDED(hr))
7183 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7185 IDirect3DVolumeTexture9_Release(texture);
7189 refcount = IDirect3DDevice9_Release(device);
7190 ok(!refcount, "Device has %u references left.\n", refcount);
7191 IDirect3D9_Release(d3d9);
7192 DestroyWindow(window);
7195 static void test_lockbox_invalid(void)
7197 static const struct
7199 D3DBOX box;
7200 HRESULT result;
7202 test_data[] =
7204 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
7205 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
7206 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
7207 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
7208 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
7209 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
7210 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
7211 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
7212 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
7213 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
7214 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
7215 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
7216 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
7217 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
7219 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
7220 IDirect3DVolumeTexture9 *texture = NULL;
7221 D3DLOCKED_BOX locked_box;
7222 IDirect3DDevice9 *device;
7223 IDirect3D9 *d3d;
7224 unsigned int i;
7225 ULONG refcount;
7226 HWND window;
7227 BYTE *base;
7228 HRESULT hr;
7230 if (!(d3d = pDirect3DCreate9(D3D_SDK_VERSION)))
7232 skip("Failed to create D3D object, skipping tests.\n");
7233 return;
7236 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7237 0, 0, 640, 480, 0, 0, 0, 0);
7238 if (!(device = create_device(d3d, window, window, TRUE)))
7240 skip("Failed to create a D3D device, skipping tests.\n");
7241 IDirect3D9_Release(d3d);
7242 DestroyWindow(window);
7243 return;
7246 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
7247 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
7248 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7249 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7250 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7251 base = locked_box.pBits;
7252 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7253 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7255 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
7257 unsigned int offset, expected_offset;
7258 const D3DBOX *box = &test_data[i].box;
7260 locked_box.pBits = (BYTE *)0xdeadbeef;
7261 locked_box.RowPitch = 0xdeadbeef;
7262 locked_box.SlicePitch = 0xdeadbeef;
7264 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
7265 /* Unlike surfaces, volumes properly check the box even in Windows XP */
7266 ok(hr == test_data[i].result,
7267 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
7268 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
7269 test_data[i].result);
7270 if (FAILED(hr))
7271 continue;
7273 offset = (BYTE *)locked_box.pBits - base;
7274 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
7275 ok(offset == expected_offset,
7276 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
7277 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
7279 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7280 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7283 /* locked_box = NULL throws an exception on Windows */
7284 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7285 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7286 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7287 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7288 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7289 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7290 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7291 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7293 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7294 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7295 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7296 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7297 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7298 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7299 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7300 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7301 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
7302 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7303 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
7304 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
7305 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7306 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7308 IDirect3DVolumeTexture9_Release(texture);
7309 refcount = IDirect3DDevice9_Release(device);
7310 ok(!refcount, "Device has %u references left.\n", refcount);
7311 IDirect3D9_Release(d3d);
7312 DestroyWindow(window);
7315 START_TEST(device)
7317 HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
7318 WNDCLASS wc = {0};
7320 wc.lpfnWndProc = DefWindowProc;
7321 wc.lpszClassName = "d3d9_test_wc";
7322 RegisterClass(&wc);
7324 if (!d3d9_handle)
7326 skip("Could not load d3d9.dll\n");
7327 goto out;
7330 pDirect3DCreate9 = (void *)GetProcAddress( d3d9_handle, "Direct3DCreate9" );
7331 ok(pDirect3DCreate9 != NULL, "Failed to get address of Direct3DCreate9\n");
7332 if (pDirect3DCreate9)
7334 IDirect3D9 *d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
7335 if(!d3d9)
7337 skip("could not create D3D9 object\n");
7338 goto out;
7340 IDirect3D9_Release(d3d9);
7342 screen_width = GetSystemMetrics(SM_CXSCREEN);
7343 screen_height = GetSystemMetrics(SM_CYSCREEN);
7345 test_fpu_setup();
7346 test_multi_device();
7347 test_display_formats();
7348 test_display_modes();
7349 test_swapchain();
7350 test_refcount();
7351 test_mipmap_levels();
7352 test_checkdevicemultisampletype();
7353 test_cursor();
7354 test_cursor_pos();
7355 test_reset_fullscreen();
7356 test_reset();
7357 test_scene();
7358 test_limits();
7359 test_depthstenciltest();
7360 test_get_rt();
7361 test_draw_indexed();
7362 test_null_stream();
7363 test_lights();
7364 test_set_stream_source();
7365 test_scissor_size();
7366 test_wndproc();
7367 test_wndproc_windowed();
7368 test_window_style();
7369 test_mode_change();
7370 test_device_window_reset();
7371 test_reset_resources();
7372 test_set_rt_vp_scissor();
7373 test_volume_get_container();
7374 test_volume_resource();
7375 test_vb_lock_flags();
7376 test_vertex_buffer_alignment();
7377 test_query_support();
7378 test_occlusion_query_states();
7379 test_get_set_vertex_shader();
7380 test_vertex_shader_constant();
7381 test_get_set_pixel_shader();
7382 test_pixel_shader_constant();
7383 test_wrong_shader();
7384 test_texture_stage_states();
7385 test_cube_textures();
7386 test_mipmap_gen();
7387 test_filter();
7388 test_get_texture();
7389 test_lod();
7390 test_surface_get_container();
7391 test_surface_alignment();
7392 test_lockrect_offset();
7393 test_lockrect_invalid();
7394 test_private_data();
7395 test_getdc();
7396 test_surface_dimensions();
7397 test_surface_format_null();
7398 test_surface_double_unlock();
7399 test_surface_blocks();
7400 test_set_palette();
7401 test_swvp_buffer();
7402 test_npot_textures();
7403 test_vidmem_accounting();
7404 test_volume_locking();
7405 test_update_volumetexture();
7406 test_create_rt_ds_fail();
7407 test_volume_blocks();
7408 test_lockbox_invalid();
7411 out:
7412 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));