d3d9/tests: Test that Direct3D9 doesn't modify the pixel format of the window it...
[wine/multimedia.git] / dlls / d3d9 / tests / device.c
blob07b1c39a1973364236d158667d31ecd669188f56
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 <d3d9.h>
26 #include "wine/test.h"
28 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
29 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
31 static INT screen_width;
32 static INT screen_height;
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 (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&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 = Direct3DCreate9(D3D_SDK_VERSION);
195 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
196 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
197 100, 100, 160, 160, NULL, NULL, NULL, NULL);
198 ok(hwnd != NULL, "Failed to create window\n");
199 if (!pD3d || !hwnd) goto cleanup;
201 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
202 ZeroMemory( &d3dpp, sizeof(d3dpp) );
203 d3dpp.Windowed = TRUE;
204 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
205 d3dpp.BackBufferFormat = d3ddm.Format;
207 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
208 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
209 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
210 if (FAILED(hr)) {
211 skip("failed to create a d3d device\n");
212 goto cleanup;
215 check_mipmap_levels(pDevice, 32, 32, 6);
216 check_mipmap_levels(pDevice, 256, 1, 9);
217 check_mipmap_levels(pDevice, 1, 256, 9);
218 check_mipmap_levels(pDevice, 1, 1, 1);
220 cleanup:
221 if (pDevice)
223 UINT refcount = IDirect3DDevice9_Release( pDevice );
224 ok(!refcount, "Device has %u references left.\n", refcount);
226 if (pD3d) IDirect3D9_Release( pD3d );
227 DestroyWindow( hwnd );
230 static void test_checkdevicemultisampletype(void)
233 HRESULT hr;
234 HWND hwnd = NULL;
236 IDirect3D9 *pD3d = NULL;
237 IDirect3DDevice9 *pDevice = NULL;
238 D3DPRESENT_PARAMETERS d3dpp;
239 D3DDISPLAYMODE d3ddm;
240 DWORD qualityLevels;
242 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
243 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
244 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
245 100, 100, 160, 160, NULL, NULL, NULL, NULL);
246 ok(hwnd != NULL, "Failed to create window\n");
247 if (!pD3d || !hwnd) goto cleanup;
249 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
250 ZeroMemory( &d3dpp, sizeof(d3dpp) );
251 d3dpp.Windowed = TRUE;
252 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
253 d3dpp.BackBufferFormat = d3ddm.Format;
255 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, hwnd,
256 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
257 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to create IDirect3D9Device (%08x)\n", hr);
258 if (FAILED(hr)) {
259 skip("failed to create a d3d device\n");
260 goto cleanup;
263 qualityLevels = 0;
265 hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE,
266 D3DMULTISAMPLE_NONE, &qualityLevels);
267 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
268 if(hr == D3DERR_NOTAVAILABLE)
270 skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
271 goto cleanup;
273 ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
275 hr = IDirect3D9_CheckDeviceMultiSampleType(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, FALSE,
276 D3DMULTISAMPLE_NONE, &qualityLevels);
277 ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
278 ok(qualityLevels == 1,"qualitylevel is not 1 but %d\n",qualityLevels);
280 cleanup:
281 if (pDevice)
283 UINT refcount = IDirect3DDevice9_Release( pDevice );
284 ok(!refcount, "Device has %u references left.\n", refcount);
286 if (pD3d) IDirect3D9_Release( pD3d );
287 DestroyWindow( hwnd );
290 static void test_swapchain(void)
292 HRESULT hr;
293 HWND hwnd = NULL;
294 IDirect3D9 *pD3d = NULL;
295 IDirect3DDevice9 *pDevice = NULL;
296 IDirect3DSwapChain9 *swapchain0 = NULL;
297 IDirect3DSwapChain9 *swapchain1 = NULL;
298 IDirect3DSwapChain9 *swapchain2 = NULL;
299 IDirect3DSwapChain9 *swapchain3 = NULL;
300 IDirect3DSwapChain9 *swapchainX = NULL;
301 IDirect3DSurface9 *backbuffer = NULL;
302 D3DPRESENT_PARAMETERS d3dpp;
303 D3DDISPLAYMODE d3ddm;
305 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
306 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
307 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
308 100, 100, 160, 160, NULL, NULL, NULL, NULL);
309 ok(hwnd != NULL, "Failed to create window\n");
310 if (!pD3d || !hwnd) goto cleanup;
312 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
313 ZeroMemory( &d3dpp, sizeof(d3dpp) );
314 d3dpp.Windowed = TRUE;
315 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
316 d3dpp.BackBufferFormat = d3ddm.Format;
317 d3dpp.BackBufferCount = 0;
319 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
320 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
321 ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
322 "Failed to create IDirect3D9Device (%08x)\n", hr);
323 if (FAILED(hr)) goto cleanup;
325 /* Check if the back buffer count was modified */
326 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
328 /* Get the implicit swapchain */
329 hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &swapchain0);
330 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
331 if(swapchain0) IDirect3DSwapChain9_Release(swapchain0);
333 /* Check if there is a back buffer */
334 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
335 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
336 ok(backbuffer != NULL, "The back buffer is NULL\n");
337 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
339 /* Try to get a nonexistent swapchain */
340 hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
341 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
342 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
343 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
345 /* Create a bunch of swapchains */
346 d3dpp.BackBufferCount = 0;
347 hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain1);
348 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
349 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
351 d3dpp.BackBufferCount = 1;
352 hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain2);
353 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
355 d3dpp.BackBufferCount = 2;
356 hr = IDirect3DDevice9_CreateAdditionalSwapChain(pDevice, &d3dpp, &swapchain3);
357 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
358 if(SUCCEEDED(hr)) {
359 /* Swapchain 3, created with backbuffercount 2 */
360 backbuffer = (void *) 0xdeadbeef;
361 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
362 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
363 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
364 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
366 backbuffer = (void *) 0xdeadbeef;
367 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
368 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
369 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
370 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
372 backbuffer = (void *) 0xdeadbeef;
373 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
374 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
375 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
376 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
378 backbuffer = (void *) 0xdeadbeef;
379 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
380 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
381 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
382 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
385 /* Check the back buffers of the swapchains */
386 /* Swapchain 1, created with backbuffercount 0 */
387 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
388 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
389 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
390 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
392 backbuffer = (void *) 0xdeadbeef;
393 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
394 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
395 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
396 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
398 /* Swapchain 2 - created with backbuffercount 1 */
399 backbuffer = (void *) 0xdeadbeef;
400 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
401 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
402 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
403 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
405 backbuffer = (void *) 0xdeadbeef;
406 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
407 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
408 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
409 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
411 backbuffer = (void *) 0xdeadbeef;
412 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
413 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
414 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
415 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
417 /* Try getSwapChain on a manually created swapchain
418 * it should fail, apparently GetSwapChain only returns implicit swapchains
420 swapchainX = (void *) 0xdeadbeef;
421 hr = IDirect3DDevice9_GetSwapChain(pDevice, 1, &swapchainX);
422 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
423 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
424 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
426 cleanup:
427 if(swapchain1) IDirect3DSwapChain9_Release(swapchain1);
428 if(swapchain2) IDirect3DSwapChain9_Release(swapchain2);
429 if(swapchain3) IDirect3DSwapChain9_Release(swapchain3);
430 if (pDevice)
432 UINT refcount = IDirect3DDevice9_Release(pDevice);
433 ok(!refcount, "Device has %u references left.\n", refcount);
435 if (pD3d) IDirect3D9_Release(pD3d);
436 DestroyWindow( hwnd );
439 static void test_refcount(void)
441 HRESULT hr;
442 HWND hwnd = NULL;
443 IDirect3D9 *pD3d = NULL;
444 IDirect3D9 *pD3d2 = NULL;
445 IDirect3DDevice9 *pDevice = NULL;
446 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
447 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
448 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
449 IDirect3DVertexShader9 *pVertexShader = NULL;
450 IDirect3DPixelShader9 *pPixelShader = NULL;
451 IDirect3DCubeTexture9 *pCubeTexture = NULL;
452 IDirect3DTexture9 *pTexture = NULL;
453 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
454 IDirect3DVolume9 *pVolumeLevel = NULL;
455 IDirect3DSurface9 *pStencilSurface = NULL;
456 IDirect3DSurface9 *pOffscreenSurface = NULL;
457 IDirect3DSurface9 *pRenderTarget = NULL;
458 IDirect3DSurface9 *pRenderTarget2 = NULL;
459 IDirect3DSurface9 *pRenderTarget3 = NULL;
460 IDirect3DSurface9 *pTextureLevel = NULL;
461 IDirect3DSurface9 *pBackBuffer = NULL;
462 IDirect3DStateBlock9 *pStateBlock = NULL;
463 IDirect3DStateBlock9 *pStateBlock1 = NULL;
464 IDirect3DSwapChain9 *pSwapChain = NULL;
465 IDirect3DQuery9 *pQuery = NULL;
466 D3DPRESENT_PARAMETERS d3dpp;
467 D3DDISPLAYMODE d3ddm;
468 int refcount = 0, tmp;
470 D3DVERTEXELEMENT9 decl[] =
472 D3DDECL_END()
475 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
476 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
477 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
478 100, 100, 160, 160, NULL, NULL, NULL, NULL);
479 ok(hwnd != NULL, "Failed to create window\n");
480 if (!pD3d || !hwnd) goto cleanup;
482 CHECK_REFCOUNT( pD3d, 1 );
484 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
485 ZeroMemory( &d3dpp, sizeof(d3dpp) );
486 d3dpp.Windowed = TRUE;
487 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
488 d3dpp.BackBufferFormat = d3ddm.Format;
489 d3dpp.EnableAutoDepthStencil = TRUE;
490 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
492 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
493 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
494 ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
495 "Failed to create IDirect3D9Device (%08x)\n", hr);
496 if (FAILED(hr)) goto cleanup;
498 refcount = get_refcount( (IUnknown *)pDevice );
499 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
501 CHECK_REFCOUNT( pD3d, 2 );
503 hr = IDirect3DDevice9_GetDirect3D(pDevice, &pD3d2);
504 CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
506 ok(pD3d2 == pD3d, "Expected IDirect3D9 pointers to be equal\n");
507 CHECK_REFCOUNT( pD3d, 3 );
508 CHECK_RELEASE_REFCOUNT( pD3d, 2 );
511 * Check refcount of implicit surfaces and implicit swapchain. Findings:
512 * - the container is the device OR swapchain
513 * - they hold a reference to the device
514 * - they are created with a refcount of 0 (Get/Release returns original refcount)
515 * - they are not freed if refcount reaches 0.
516 * - the refcount is not forwarded to the container.
518 hr = IDirect3DDevice9_GetSwapChain(pDevice, 0, &pSwapChain);
519 CHECK_CALL( hr, "GetSwapChain", pDevice, ++refcount);
520 if (pSwapChain)
522 CHECK_REFCOUNT( pSwapChain, 1);
524 hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
525 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
526 CHECK_REFCOUNT( pSwapChain, 1);
527 if(pRenderTarget)
529 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
530 CHECK_REFCOUNT( pRenderTarget, 1);
532 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
533 CHECK_REFCOUNT(pDevice, refcount);
534 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
535 CHECK_REFCOUNT(pDevice, refcount);
537 hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget);
538 CHECK_CALL( hr, "GetRenderTarget", pDevice, refcount);
539 CHECK_REFCOUNT( pRenderTarget, 2);
540 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
541 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
542 CHECK_REFCOUNT( pDevice, --refcount);
544 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
545 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
546 CHECK_REFCOUNT(pDevice, ++refcount);
547 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
548 CHECK_REFCOUNT(pDevice, --refcount);
551 /* Render target and back buffer are identical. */
552 hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, 0, &pBackBuffer);
553 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
554 if(pBackBuffer)
556 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
557 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
558 pRenderTarget, pBackBuffer);
559 pBackBuffer = NULL;
561 CHECK_REFCOUNT( pDevice, --refcount);
563 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pStencilSurface);
564 CHECK_CALL( hr, "GetDepthStencilSurface", pDevice, ++refcount);
565 CHECK_REFCOUNT( pSwapChain, 1);
566 if(pStencilSurface)
568 CHECK_SURFACE_CONTAINER( pStencilSurface, IID_IDirect3DDevice9, pDevice);
569 CHECK_REFCOUNT( pStencilSurface, 1);
571 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
572 CHECK_REFCOUNT(pDevice, refcount);
573 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
574 CHECK_REFCOUNT(pDevice, refcount);
576 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
577 CHECK_REFCOUNT( pDevice, --refcount);
579 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
580 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
581 CHECK_REFCOUNT(pDevice, ++refcount);
582 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
583 CHECK_REFCOUNT(pDevice, --refcount);
584 pStencilSurface = NULL;
587 CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
588 CHECK_REFCOUNT( pDevice, --refcount);
590 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
591 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
592 CHECK_REFCOUNT(pDevice, ++refcount);
593 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
594 CHECK_REFCOUNT(pDevice, --refcount);
595 pSwapChain = NULL;
598 /* Buffers */
599 hr = IDirect3DDevice9_CreateIndexBuffer( pDevice, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL );
600 CHECK_CALL( hr, "CreateIndexBuffer", pDevice, ++refcount );
601 if(pIndexBuffer)
603 tmp = get_refcount( (IUnknown *)pIndexBuffer );
605 hr = IDirect3DDevice9_SetIndices(pDevice, pIndexBuffer);
606 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
607 hr = IDirect3DDevice9_SetIndices(pDevice, NULL);
608 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
611 hr = IDirect3DDevice9_CreateVertexBuffer( pDevice, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
612 CHECK_CALL( hr, "CreateVertexBuffer", pDevice, ++refcount );
613 if(pVertexBuffer)
615 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
616 UINT offset = ~0;
617 UINT stride = ~0;
619 tmp = get_refcount( (IUnknown *)pVertexBuffer );
621 hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, pVertexBuffer, 0, 3 * sizeof(float));
622 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
623 hr = IDirect3DDevice9_SetStreamSource(pDevice, 0, NULL, 0, 0);
624 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
626 hr = IDirect3DDevice9_GetStreamSource(pDevice, 0, &pVBuf, &offset, &stride);
627 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
628 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
629 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
630 ok(offset==0, "offset not 0 (got %u)!\n", offset);
632 /* Shaders */
633 hr = IDirect3DDevice9_CreateVertexDeclaration( pDevice, decl, &pVertexDeclaration );
634 CHECK_CALL( hr, "CreateVertexDeclaration", pDevice, ++refcount );
635 hr = IDirect3DDevice9_CreateVertexShader( pDevice, simple_vs, &pVertexShader );
636 CHECK_CALL( hr, "CreateVertexShader", pDevice, ++refcount );
637 hr = IDirect3DDevice9_CreatePixelShader( pDevice, simple_ps, &pPixelShader );
638 CHECK_CALL( hr, "CreatePixelShader", pDevice, ++refcount );
639 /* Textures */
640 hr = IDirect3DDevice9_CreateTexture( pDevice, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL );
641 CHECK_CALL( hr, "CreateTexture", pDevice, ++refcount );
642 if (pTexture)
644 tmp = get_refcount( (IUnknown *)pTexture );
646 /* SetTexture should not increase refcounts */
647 hr = IDirect3DDevice9_SetTexture(pDevice, 0, (IDirect3DBaseTexture9 *) pTexture);
648 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
649 hr = IDirect3DDevice9_SetTexture(pDevice, 0, NULL);
650 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
652 /* This should not increment device refcount */
653 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
654 CHECK_CALL( hr, "GetSurfaceLevel", pDevice, refcount );
655 /* But should increment texture's refcount */
656 CHECK_REFCOUNT( pTexture, tmp+1 );
657 /* Because the texture and surface refcount are identical */
658 if (pTextureLevel)
660 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
661 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
662 CHECK_REFCOUNT ( pTexture , tmp+2 );
663 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
664 CHECK_REFCOUNT ( pTexture , tmp+1 );
665 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
666 CHECK_REFCOUNT ( pTextureLevel, tmp );
669 hr = IDirect3DDevice9_CreateCubeTexture( pDevice, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL );
670 CHECK_CALL( hr, "CreateCubeTexture", pDevice, ++refcount );
671 hr = IDirect3DDevice9_CreateVolumeTexture( pDevice, 32, 32, 2, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL );
672 CHECK_CALL( hr, "CreateVolumeTexture", pDevice, ++refcount );
673 if (pVolumeTexture)
675 tmp = get_refcount( (IUnknown *)pVolumeTexture );
677 /* This should not increment device refcount */
678 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
679 CHECK_CALL( hr, "GetVolumeLevel", pDevice, refcount );
680 /* But should increment volume texture's refcount */
681 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
682 /* Because the volume texture and volume refcount are identical */
683 if (pVolumeLevel)
685 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
686 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
687 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
688 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
689 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
690 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
691 CHECK_REFCOUNT ( pVolumeLevel , tmp );
694 /* Surfaces */
695 hr = IDirect3DDevice9_CreateDepthStencilSurface( pDevice, 32, 32, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL );
696 CHECK_CALL( hr, "CreateDepthStencilSurface", pDevice, ++refcount );
697 CHECK_REFCOUNT( pStencilSurface, 1 );
698 hr = IDirect3DDevice9_CreateOffscreenPlainSurface( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL );
699 CHECK_CALL( hr, "CreateOffscreenPlainSurface", pDevice, ++refcount );
700 CHECK_REFCOUNT( pOffscreenSurface, 1 );
701 hr = IDirect3DDevice9_CreateRenderTarget( pDevice, 32, 32, D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL );
702 CHECK_CALL( hr, "CreateRenderTarget", pDevice, ++refcount );
703 CHECK_REFCOUNT( pRenderTarget3, 1 );
704 /* Misc */
705 hr = IDirect3DDevice9_CreateStateBlock( pDevice, D3DSBT_ALL, &pStateBlock );
706 CHECK_CALL( hr, "CreateStateBlock", pDevice, ++refcount );
707 hr = IDirect3DDevice9_CreateAdditionalSwapChain( pDevice, &d3dpp, &pSwapChain );
708 CHECK_CALL( hr, "CreateAdditionalSwapChain", pDevice, ++refcount );
709 if(pSwapChain)
711 /* check implicit back buffer */
712 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
713 CHECK_CALL( hr, "GetBackBuffer", pDevice, ++refcount);
714 CHECK_REFCOUNT( pSwapChain, 1);
715 if(pBackBuffer)
717 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
718 CHECK_REFCOUNT( pBackBuffer, 1);
719 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
720 CHECK_REFCOUNT( pDevice, --refcount);
722 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
723 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
724 CHECK_REFCOUNT(pDevice, ++refcount);
725 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
726 CHECK_REFCOUNT(pDevice, --refcount);
727 pBackBuffer = NULL;
729 CHECK_REFCOUNT( pSwapChain, 1);
731 hr = IDirect3DDevice9_CreateQuery( pDevice, D3DQUERYTYPE_EVENT, &pQuery );
732 CHECK_CALL( hr, "CreateQuery", pDevice, ++refcount );
734 hr = IDirect3DDevice9_BeginStateBlock( pDevice );
735 CHECK_CALL( hr, "BeginStateBlock", pDevice, refcount );
736 hr = IDirect3DDevice9_EndStateBlock( pDevice, &pStateBlock1 );
737 CHECK_CALL( hr, "EndStateBlock", pDevice, ++refcount );
739 /* The implicit render target is not freed if refcount reaches 0.
740 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
741 hr = IDirect3DDevice9_GetRenderTarget(pDevice, 0, &pRenderTarget2);
742 CHECK_CALL( hr, "GetRenderTarget", pDevice, ++refcount);
743 if(pRenderTarget2)
745 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
746 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
747 pRenderTarget, pRenderTarget2);
748 CHECK_REFCOUNT( pDevice, --refcount);
749 pRenderTarget2 = NULL;
751 pRenderTarget = NULL;
753 cleanup:
754 CHECK_RELEASE(pDevice, pDevice, --refcount);
756 /* Buffers */
757 CHECK_RELEASE(pVertexBuffer, pDevice, --refcount);
758 CHECK_RELEASE(pIndexBuffer, pDevice, --refcount);
759 /* Shaders */
760 CHECK_RELEASE(pVertexDeclaration, pDevice, --refcount);
761 CHECK_RELEASE(pVertexShader, pDevice, --refcount);
762 CHECK_RELEASE(pPixelShader, pDevice, --refcount);
763 /* Textures */
764 CHECK_RELEASE(pTextureLevel, pDevice, --refcount);
765 CHECK_RELEASE(pCubeTexture, pDevice, --refcount);
766 CHECK_RELEASE(pVolumeTexture, pDevice, --refcount);
767 /* Surfaces */
768 CHECK_RELEASE(pStencilSurface, pDevice, --refcount);
769 CHECK_RELEASE(pOffscreenSurface, pDevice, --refcount);
770 CHECK_RELEASE(pRenderTarget3, pDevice, --refcount);
771 /* Misc */
772 CHECK_RELEASE(pStateBlock, pDevice, --refcount);
773 CHECK_RELEASE(pSwapChain, pDevice, --refcount);
774 CHECK_RELEASE(pQuery, pDevice, --refcount);
775 /* This will destroy device - cannot check the refcount here */
776 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
778 if (pD3d) CHECK_RELEASE_REFCOUNT( pD3d, 0);
780 DestroyWindow( hwnd );
783 static void test_cursor(void)
785 HRESULT hr;
786 HWND hwnd = NULL;
787 IDirect3D9 *pD3d = NULL;
788 IDirect3DDevice9 *pDevice = NULL;
789 D3DPRESENT_PARAMETERS d3dpp;
790 D3DDISPLAYMODE d3ddm;
791 CURSORINFO info;
792 IDirect3DSurface9 *cursor = NULL;
793 HCURSOR cur;
795 memset(&info, 0, sizeof(info));
796 info.cbSize = sizeof(info);
797 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
798 cur = info.hCursor;
800 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
801 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
802 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
803 100, 100, 160, 160, NULL, NULL, NULL, NULL);
804 ok(hwnd != NULL, "Failed to create window\n");
805 if (!pD3d || !hwnd) goto cleanup;
807 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
808 ZeroMemory( &d3dpp, sizeof(d3dpp) );
809 d3dpp.Windowed = TRUE;
810 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
811 d3dpp.BackBufferFormat = d3ddm.Format;
813 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
814 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
815 ok(hr == S_OK || hr == D3DERR_NOTAVAILABLE,
816 "Failed to create IDirect3D9Device (%08x)\n", hr);
817 if (FAILED(hr)) goto cleanup;
819 IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, 0);
820 ok(cursor != NULL, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
822 /* Initially hidden */
823 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
824 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
826 /* Not enabled without a surface*/
827 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
828 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
830 /* Fails */
831 hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, NULL);
832 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
834 hr = IDirect3DDevice9_SetCursorProperties(pDevice, 0, 0, cursor);
835 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
837 IDirect3DSurface9_Release(cursor);
839 memset(&info, 0, sizeof(info));
840 info.cbSize = sizeof(info);
841 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
842 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
843 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
845 /* Still hidden */
846 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
847 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
849 /* Enabled now*/
850 hr = IDirect3DDevice9_ShowCursor(pDevice, TRUE);
851 ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
853 /* GDI cursor unchanged */
854 memset(&info, 0, sizeof(info));
855 info.cbSize = sizeof(info);
856 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
857 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
858 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
860 cleanup:
861 if (pDevice)
863 UINT refcount = IDirect3DDevice9_Release(pDevice);
864 ok(!refcount, "Device has %u references left.\n", refcount);
866 if (pD3d) IDirect3D9_Release(pD3d);
867 DestroyWindow( hwnd );
870 static void test_reset(void)
872 HRESULT hr;
873 HWND hwnd = NULL;
874 RECT winrect;
875 IDirect3D9 *pD3d = NULL;
876 D3DPRESENT_PARAMETERS d3dpp;
877 D3DDISPLAYMODE d3ddm, d3ddm2;
878 D3DVIEWPORT9 vp;
879 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
880 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
881 IDirect3DSwapChain9 *pSwapchain;
882 IDirect3DSurface9 *surface;
883 IDirect3DTexture9 *texture;
884 IDirect3DVertexShader9 *shader;
885 UINT i, adapter_mode_count;
886 D3DLOCKED_RECT lockrect;
887 IDirect3DDevice9 *device1 = NULL;
888 IDirect3DDevice9 *device2 = NULL;
889 D3DCAPS9 caps;
890 DWORD value;
891 struct
893 UINT w;
894 UINT h;
895 } *modes = NULL;
896 UINT mode_count = 0;
898 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
899 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
900 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
901 100, 100, 160, 160, NULL, NULL, NULL, NULL);
902 ok(hwnd != NULL, "Failed to create window\n");
903 if (!pD3d || !hwnd) goto cleanup;
905 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
906 adapter_mode_count = IDirect3D9_GetAdapterModeCount(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format);
907 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
908 for(i = 0; i < adapter_mode_count; ++i)
910 UINT j;
911 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
912 hr = IDirect3D9_EnumAdapterModes(pD3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
913 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
915 for (j = 0; j < mode_count; ++j)
917 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
918 break;
920 if (j == mode_count)
922 modes[j].w = d3ddm2.Width;
923 modes[j].h = d3ddm2.Height;
924 ++mode_count;
927 /* We use them as invalid modes */
928 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
929 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
930 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
931 d3ddm2.Width, d3ddm2.Height);
932 goto cleanup;
936 if (mode_count < 2)
938 skip("Less than 2 modes supported, skipping mode tests\n");
939 goto cleanup;
942 i = 0;
943 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
945 ZeroMemory( &d3dpp, sizeof(d3dpp) );
946 d3dpp.Windowed = FALSE;
947 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
948 d3dpp.BackBufferWidth = modes[i].w;
949 d3dpp.BackBufferHeight = modes[i].h;
950 d3dpp.BackBufferFormat = d3ddm.Format;
951 d3dpp.EnableAutoDepthStencil = TRUE;
952 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
954 hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
955 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device1);
956 if (FAILED(hr))
958 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
959 goto cleanup;
961 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
962 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
964 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
965 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
967 width = GetSystemMetrics(SM_CXSCREEN);
968 height = GetSystemMetrics(SM_CYSCREEN);
969 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
970 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
972 hr = IDirect3DDevice9_GetViewport(device1, &vp);
973 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
974 if(SUCCEEDED(hr))
976 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
977 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
978 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
979 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
980 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
981 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
984 i = 1;
985 vp.X = 10;
986 vp.Y = 20;
987 vp.MinZ = 2;
988 vp.MaxZ = 3;
989 hr = IDirect3DDevice9_SetViewport(device1, &vp);
990 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
992 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
993 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
994 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
995 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
996 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
998 ZeroMemory( &d3dpp, sizeof(d3dpp) );
999 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1000 d3dpp.Windowed = FALSE;
1001 d3dpp.BackBufferWidth = modes[i].w;
1002 d3dpp.BackBufferHeight = modes[i].h;
1003 d3dpp.BackBufferFormat = d3ddm.Format;
1004 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1005 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1006 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1007 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1009 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1010 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1011 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1013 ZeroMemory(&vp, sizeof(vp));
1014 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1015 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1016 if(SUCCEEDED(hr))
1018 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1019 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1020 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1021 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1022 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1023 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1026 width = GetSystemMetrics(SM_CXSCREEN);
1027 height = GetSystemMetrics(SM_CYSCREEN);
1028 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1029 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1031 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1032 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1033 if(SUCCEEDED(hr))
1035 ZeroMemory(&d3dpp, sizeof(d3dpp));
1036 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1037 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1038 if(SUCCEEDED(hr))
1040 ok(d3dpp.BackBufferWidth == modes[i].w, "Back buffer width is %u, expected %u\n",
1041 d3dpp.BackBufferWidth, modes[i].w);
1042 ok(d3dpp.BackBufferHeight == modes[i].h, "Back buffer height is %u, expected %u\n",
1043 d3dpp.BackBufferHeight, modes[i].h);
1045 IDirect3DSwapChain9_Release(pSwapchain);
1048 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1049 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1050 d3dpp.Windowed = TRUE;
1051 d3dpp.BackBufferWidth = 400;
1052 d3dpp.BackBufferHeight = 300;
1053 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1054 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1055 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1056 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1058 width = GetSystemMetrics(SM_CXSCREEN);
1059 height = GetSystemMetrics(SM_CYSCREEN);
1060 ok(width == orig_width, "Screen width is %d\n", width);
1061 ok(height == orig_height, "Screen height is %d\n", height);
1063 ZeroMemory(&vp, sizeof(vp));
1064 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1065 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1066 if(SUCCEEDED(hr))
1068 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1069 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1070 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1071 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1072 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1073 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1076 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1077 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1078 if(SUCCEEDED(hr))
1080 ZeroMemory(&d3dpp, sizeof(d3dpp));
1081 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1082 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1083 if(SUCCEEDED(hr))
1085 ok(d3dpp.BackBufferWidth == 400, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1086 ok(d3dpp.BackBufferHeight == 300, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1088 IDirect3DSwapChain9_Release(pSwapchain);
1091 winrect.left = 0;
1092 winrect.top = 0;
1093 winrect.right = 200;
1094 winrect.bottom = 150;
1095 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1096 ok(SetWindowPos(hwnd, NULL, 0, 0,
1097 winrect.right-winrect.left,
1098 winrect.bottom-winrect.top,
1099 SWP_NOMOVE|SWP_NOZORDER),
1100 "SetWindowPos failed\n");
1102 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1103 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1104 d3dpp.Windowed = TRUE;
1105 d3dpp.BackBufferWidth = 0;
1106 d3dpp.BackBufferHeight = 0;
1107 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1108 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1109 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1110 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1112 ZeroMemory(&vp, sizeof(vp));
1113 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1114 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1115 if(SUCCEEDED(hr))
1117 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1118 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1119 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
1120 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
1121 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1122 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1125 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &pSwapchain);
1126 ok(hr == D3D_OK, "IDirect3DDevice9_GetSwapChain returned %08x\n", hr);
1127 if(SUCCEEDED(hr))
1129 ZeroMemory(&d3dpp, sizeof(d3dpp));
1130 hr = IDirect3DSwapChain9_GetPresentParameters(pSwapchain, &d3dpp);
1131 ok(hr == D3D_OK, "IDirect3DSwapChain9_GetPresentParameters returned %08x\n", hr);
1132 if(SUCCEEDED(hr))
1134 ok(d3dpp.BackBufferWidth == 200, "Back buffer width is %d\n", d3dpp.BackBufferWidth);
1135 ok(d3dpp.BackBufferHeight == 150, "Back buffer height is %d\n", d3dpp.BackBufferHeight);
1137 IDirect3DSwapChain9_Release(pSwapchain);
1140 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1141 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1142 d3dpp.Windowed = TRUE;
1143 d3dpp.BackBufferWidth = 400;
1144 d3dpp.BackBufferHeight = 300;
1146 /* _Reset fails if there is a resource in the default pool */
1147 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1148 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1149 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1150 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1151 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1152 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1153 IDirect3DSurface9_Release(surface);
1154 /* Reset again to get the device out of the lost state */
1155 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1156 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1157 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1158 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1160 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1162 IDirect3DVolumeTexture9 *volume_texture;
1164 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1165 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1166 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1167 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1168 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1169 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1170 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1171 hr, D3DERR_DEVICENOTRESET);
1172 IDirect3DVolumeTexture9_Release(volume_texture);
1173 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1174 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1175 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1176 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1178 else
1180 skip("Volume textures not supported.\n");
1183 /* Scratch, sysmem and managed pools are fine */
1184 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1185 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1186 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1187 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1188 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1189 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1190 IDirect3DSurface9_Release(surface);
1192 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1193 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1194 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1195 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1196 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1197 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1198 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1199 IDirect3DSurface9_Release(surface);
1201 /* The depth stencil should get reset to the auto depth stencil when present. */
1202 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
1203 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
1205 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1206 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1207 ok(surface == NULL, "Depth stencil should be NULL\n");
1209 d3dpp.EnableAutoDepthStencil = TRUE;
1210 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1211 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1212 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1214 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1215 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1216 ok(surface != NULL, "Depth stencil should not be NULL\n");
1217 if (surface) IDirect3DSurface9_Release(surface);
1219 d3dpp.EnableAutoDepthStencil = FALSE;
1220 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1221 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1223 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
1224 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
1225 ok(surface == NULL, "Depth stencil should be NULL\n");
1227 /* Will a sysmem or scratch survive while locked */
1228 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
1229 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1230 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1231 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1232 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1233 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1234 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1235 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1236 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1237 IDirect3DSurface9_UnlockRect(surface);
1238 IDirect3DSurface9_Release(surface);
1240 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1241 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1242 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
1243 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
1244 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1245 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1246 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1247 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1248 IDirect3DSurface9_UnlockRect(surface);
1249 IDirect3DSurface9_Release(surface);
1251 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
1252 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
1253 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1254 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1255 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1256 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1257 IDirect3DTexture9_Release(texture);
1259 /* A reference held to an implicit surface causes failures as well */
1260 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1261 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
1262 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1263 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1264 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1265 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1266 IDirect3DSurface9_Release(surface);
1267 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1268 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1269 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1270 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1272 /* Shaders are fine as well */
1273 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
1274 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
1275 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1276 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1277 IDirect3DVertexShader9_Release(shader);
1279 /* Try setting invalid modes */
1280 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1281 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1282 d3dpp.Windowed = FALSE;
1283 d3dpp.BackBufferWidth = 32;
1284 d3dpp.BackBufferHeight = 32;
1285 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1286 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
1287 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1288 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1290 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1291 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1292 d3dpp.Windowed = FALSE;
1293 d3dpp.BackBufferWidth = 801;
1294 d3dpp.BackBufferHeight = 600;
1295 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1296 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
1297 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1298 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1300 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1301 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1302 d3dpp.Windowed = FALSE;
1303 d3dpp.BackBufferWidth = 0;
1304 d3dpp.BackBufferHeight = 0;
1305 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1306 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
1307 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1308 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1310 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1312 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1313 d3dpp.Windowed = TRUE;
1314 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1315 d3dpp.BackBufferFormat = d3ddm.Format;
1316 d3dpp.EnableAutoDepthStencil = FALSE;
1317 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1319 hr = IDirect3D9_CreateDevice(pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1320 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1321 if (FAILED(hr))
1323 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
1324 goto cleanup;
1327 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
1328 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1330 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1331 d3dpp.Windowed = TRUE;
1332 d3dpp.BackBufferWidth = 400;
1333 d3dpp.BackBufferHeight = 300;
1334 d3dpp.EnableAutoDepthStencil = TRUE;
1335 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1337 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
1338 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
1340 if (FAILED(hr)) goto cleanup;
1342 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
1343 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
1344 ok(surface != NULL, "Depth stencil should not be NULL\n");
1345 if (surface) IDirect3DSurface9_Release(surface);
1347 cleanup:
1348 HeapFree(GetProcessHeap(), 0, modes);
1349 if (device2)
1351 UINT refcount = IDirect3DDevice9_Release(device2);
1352 ok(!refcount, "Device has %u references left.\n", refcount);
1354 if (device1)
1356 UINT refcount = IDirect3DDevice9_Release(device1);
1357 ok(!refcount, "Device has %u references left.\n", refcount);
1359 if (pD3d) IDirect3D9_Release(pD3d);
1360 if (hwnd) DestroyWindow(hwnd);
1363 /* Test adapter display modes */
1364 static void test_display_modes(void)
1366 D3DDISPLAYMODE dmode;
1367 IDirect3D9 *pD3d;
1369 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
1370 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1371 if(!pD3d) return;
1373 #define TEST_FMT(x,r) do { \
1374 HRESULT res = IDirect3D9_EnumAdapterModes(pD3d, 0, (x), 0, &dmode); \
1375 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
1376 } while(0)
1378 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
1379 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
1380 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1381 /* D3DFMT_R5G6B5 */
1382 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
1383 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
1384 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
1385 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
1386 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
1387 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
1388 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
1389 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
1390 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
1391 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
1392 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
1393 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
1395 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
1396 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
1398 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
1399 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
1400 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
1402 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
1403 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
1404 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
1405 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
1406 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
1407 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
1409 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
1410 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
1411 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
1412 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
1413 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
1414 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
1415 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
1416 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
1417 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
1418 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
1420 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
1421 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
1422 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
1423 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
1424 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
1425 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
1426 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
1427 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
1428 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
1429 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
1431 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
1432 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
1433 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
1434 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
1435 /* Floating point formats */
1436 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
1437 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
1438 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
1440 /* IEEE formats */
1441 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
1442 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
1443 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
1445 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
1447 TEST_FMT(0, D3DERR_INVALIDCALL);
1449 IDirect3D9_Release(pD3d);
1452 static void test_scene(void)
1454 HRESULT hr;
1455 HWND hwnd = NULL;
1456 IDirect3D9 *pD3d = NULL;
1457 IDirect3DDevice9 *pDevice = NULL;
1458 D3DPRESENT_PARAMETERS d3dpp;
1459 D3DDISPLAYMODE d3ddm;
1460 IDirect3DSurface9 *pSurface1 = NULL, *pSurface2 = NULL, *pSurface3 = NULL, *pRenderTarget = NULL;
1461 IDirect3DSurface9 *pBackBuffer = NULL, *pDepthStencil = NULL;
1462 RECT rect = {0, 0, 128, 128};
1463 D3DCAPS9 caps;
1465 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
1466 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1467 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1468 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1469 ok(hwnd != NULL, "Failed to create window\n");
1470 if (!pD3d || !hwnd) goto cleanup;
1472 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1473 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1474 d3dpp.Windowed = TRUE;
1475 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1476 d3dpp.BackBufferWidth = 800;
1477 d3dpp.BackBufferHeight = 600;
1478 d3dpp.BackBufferFormat = d3ddm.Format;
1479 d3dpp.EnableAutoDepthStencil = TRUE;
1480 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1482 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1483 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1484 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1485 if(!pDevice)
1487 skip("Failed to create a d3d device\n");
1488 goto cleanup;
1491 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
1492 memset(&caps, 0, sizeof(caps));
1493 hr = IDirect3DDevice9_GetDeviceCaps(pDevice, &caps);
1494 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
1495 if(FAILED(hr)) goto cleanup;
1497 /* Test an EndScene without BeginScene. Should return an error */
1498 hr = IDirect3DDevice9_EndScene(pDevice);
1499 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1501 /* Test a normal BeginScene / EndScene pair, this should work */
1502 hr = IDirect3DDevice9_BeginScene(pDevice);
1503 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1504 if(SUCCEEDED(hr))
1506 hr = IDirect3DDevice9_EndScene(pDevice);
1507 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1510 /* Test another EndScene without having begun a new scene. Should return an error */
1511 hr = IDirect3DDevice9_EndScene(pDevice);
1512 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1514 /* Two nested BeginScene and EndScene calls */
1515 hr = IDirect3DDevice9_BeginScene(pDevice);
1516 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1517 hr = IDirect3DDevice9_BeginScene(pDevice);
1518 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
1519 hr = IDirect3DDevice9_EndScene(pDevice);
1520 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1521 hr = IDirect3DDevice9_EndScene(pDevice);
1522 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
1524 /* Create some surfaces to test stretchrect between the scenes */
1525 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface1, NULL);
1526 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1527 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(pDevice, 128, 128, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface2, NULL);
1528 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
1529 hr = IDirect3DDevice9_CreateDepthStencilSurface(pDevice, 800, 600, D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface3, NULL);
1530 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
1531 hr = IDirect3DDevice9_CreateRenderTarget(pDevice, 128, 128, d3ddm.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pRenderTarget, NULL);
1532 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
1534 hr = IDirect3DDevice9_GetBackBuffer(pDevice, 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
1535 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1536 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1537 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
1539 /* First make sure a simple StretchRect call works */
1540 if(pSurface1 && pSurface2) {
1541 hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1542 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1544 if(pBackBuffer && pRenderTarget) {
1545 hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1546 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1548 if(pDepthStencil && pSurface3) {
1549 HRESULT expected;
1550 if(0) /* Disabled for now because it crashes in wine */ {
1551 expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
1552 hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1553 ok( hr == expected, "IDirect3DDevice9_StretchRect returned %08x, expected %08x\n", hr, expected);
1557 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a beginScene - Endscene pair
1558 * with normal surfaces and render targets, but not depth stencil surfaces.
1560 hr = IDirect3DDevice9_BeginScene(pDevice);
1561 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1563 if(pSurface1 && pSurface2)
1565 hr = IDirect3DDevice9_StretchRect(pDevice, pSurface1, NULL, pSurface2, NULL, 0);
1566 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1568 if(pBackBuffer && pRenderTarget)
1570 hr = IDirect3DDevice9_StretchRect(pDevice, pBackBuffer, &rect, pRenderTarget, NULL, 0);
1571 ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
1573 if(pDepthStencil && pSurface3)
1575 /* This is supposed to fail inside a BeginScene - EndScene pair. */
1576 hr = IDirect3DDevice9_StretchRect(pDevice, pDepthStencil, NULL, pSurface3, NULL, 0);
1577 ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
1580 hr = IDirect3DDevice9_EndScene(pDevice);
1581 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1583 /* Does a SetRenderTarget influence BeginScene / EndScene ?
1584 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
1585 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
1587 hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pRenderTarget);
1588 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1589 hr = IDirect3DDevice9_BeginScene(pDevice);
1590 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1591 hr = IDirect3DDevice9_SetRenderTarget(pDevice, 0, pBackBuffer);
1592 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
1593 hr = IDirect3DDevice9_EndScene(pDevice);
1594 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1596 cleanup:
1597 if(pRenderTarget) IDirect3DSurface9_Release(pRenderTarget);
1598 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1599 if(pBackBuffer) IDirect3DSurface9_Release(pBackBuffer);
1600 if(pSurface1) IDirect3DSurface9_Release(pSurface1);
1601 if(pSurface2) IDirect3DSurface9_Release(pSurface2);
1602 if(pSurface3) IDirect3DSurface9_Release(pSurface3);
1603 if (pDevice)
1605 UINT refcount = IDirect3DDevice9_Release(pDevice);
1606 ok(!refcount, "Device has %u references left.\n", refcount);
1608 if (pD3d) IDirect3D9_Release(pD3d);
1609 if(hwnd) DestroyWindow(hwnd);
1612 static void test_limits(void)
1614 HRESULT hr;
1615 HWND hwnd = NULL;
1616 IDirect3D9 *pD3d = NULL;
1617 IDirect3DDevice9 *pDevice = NULL;
1618 D3DPRESENT_PARAMETERS d3dpp;
1619 D3DDISPLAYMODE d3ddm;
1620 IDirect3DTexture9 *pTexture = NULL;
1621 int i;
1623 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
1624 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1625 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1626 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1627 ok(hwnd != NULL, "Failed to create window\n");
1628 if (!pD3d || !hwnd) goto cleanup;
1630 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1631 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1632 d3dpp.Windowed = TRUE;
1633 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1634 d3dpp.BackBufferWidth = 800;
1635 d3dpp.BackBufferHeight = 600;
1636 d3dpp.BackBufferFormat = d3ddm.Format;
1637 d3dpp.EnableAutoDepthStencil = TRUE;
1638 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1640 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1641 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1642 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1643 if(!pDevice)
1645 skip("Failed to create a d3d device\n");
1646 goto cleanup;
1649 hr = IDirect3DDevice9_CreateTexture(pDevice, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTexture, NULL);
1650 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
1651 if(!pTexture) goto cleanup;
1653 /* There are 16 pixel samplers. We should be able to access all of them */
1654 for(i = 0; i < 16; i++) {
1655 hr = IDirect3DDevice9_SetTexture(pDevice, i, (IDirect3DBaseTexture9 *) pTexture);
1656 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1657 hr = IDirect3DDevice9_SetTexture(pDevice, i, NULL);
1658 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
1659 hr = IDirect3DDevice9_SetSamplerState(pDevice, i, D3DSAMP_SRGBTEXTURE, TRUE);
1660 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
1663 /* Now test all 8 textures stage states */
1664 for(i = 0; i < 8; i++) {
1665 hr = IDirect3DDevice9_SetTextureStageState(pDevice, i, D3DTSS_COLOROP, D3DTOP_ADD);
1666 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
1669 /* Investigations show that accessing higher samplers / textures stage states does not return an error either. Writing
1670 * to too high samplers(approximately sampler 40) causes memory corruption in windows, so there is no bounds checking
1671 * but how do I test that?
1673 cleanup:
1674 if(pTexture) IDirect3DTexture9_Release(pTexture);
1675 if (pDevice)
1677 UINT refcount = IDirect3D9_Release(pDevice);
1678 ok(!refcount, "Device has %u references left.\n", refcount);
1680 if (pD3d) IDirect3D9_Release(pD3d);
1681 if(hwnd) DestroyWindow(hwnd);
1684 static void test_depthstenciltest(void)
1686 HRESULT hr;
1687 HWND hwnd = NULL;
1688 IDirect3D9 *pD3d = NULL;
1689 IDirect3DDevice9 *pDevice = NULL;
1690 D3DPRESENT_PARAMETERS d3dpp;
1691 D3DDISPLAYMODE d3ddm;
1692 IDirect3DSurface9 *pDepthStencil = NULL;
1693 IDirect3DSurface9 *pDepthStencil2 = NULL;
1694 DWORD state;
1696 pD3d = Direct3DCreate9(D3D_SDK_VERSION);
1697 ok(pD3d != NULL, "Failed to create IDirect3D9 object\n");
1698 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1699 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1700 ok(hwnd != NULL, "Failed to create window\n");
1701 if (!pD3d || !hwnd) goto cleanup;
1703 IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
1704 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1705 d3dpp.Windowed = TRUE;
1706 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1707 d3dpp.BackBufferWidth = 800;
1708 d3dpp.BackBufferHeight = 600;
1709 d3dpp.BackBufferFormat = d3ddm.Format;
1710 d3dpp.EnableAutoDepthStencil = TRUE;
1711 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1713 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1714 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1715 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1716 if(!pDevice)
1718 skip("Failed to create a d3d device\n");
1719 goto cleanup;
1722 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1723 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1725 /* Try to clear */
1726 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1727 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1729 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
1730 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1732 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
1733 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
1734 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
1735 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
1737 /* This left the render states untouched! */
1738 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1739 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1740 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1741 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
1742 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1743 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
1744 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
1745 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1746 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
1747 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
1748 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1749 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
1751 /* This is supposed to fail now */
1752 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1753 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1755 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
1756 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
1758 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
1759 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
1761 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1762 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1763 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1765 /* Now it works again */
1766 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
1767 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1769 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1770 if(pDevice) IDirect3D9_Release(pDevice);
1772 /* Now see if autodepthstencil disable is honored. First, without a format set */
1773 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1774 d3dpp.Windowed = TRUE;
1775 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1776 d3dpp.BackBufferWidth = 800;
1777 d3dpp.BackBufferHeight = 600;
1778 d3dpp.BackBufferFormat = d3ddm.Format;
1779 d3dpp.EnableAutoDepthStencil = FALSE;
1780 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
1782 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1783 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1784 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1785 if(!pDevice)
1787 skip("Failed to create a d3d device\n");
1788 goto cleanup;
1791 pDepthStencil = NULL;
1792 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1793 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1794 if(pDepthStencil) {
1795 IDirect3DSurface9_Release(pDepthStencil);
1796 pDepthStencil = NULL;
1799 /* Check the depth test state */
1800 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1801 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1802 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1804 if(pDevice) IDirect3D9_Release(pDevice);
1806 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
1807 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1808 d3dpp.Windowed = TRUE;
1809 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1810 d3dpp.BackBufferWidth = 800;
1811 d3dpp.BackBufferHeight = 600;
1812 d3dpp.BackBufferFormat = d3ddm.Format;
1813 d3dpp.EnableAutoDepthStencil = FALSE;
1814 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
1816 hr = IDirect3D9_CreateDevice( pD3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
1817 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice );
1818 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
1819 if(!pDevice)
1821 skip("Failed to create a d3d device\n");
1822 goto cleanup;
1825 pDepthStencil = NULL;
1826 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
1827 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
1828 if(pDepthStencil) {
1829 IDirect3DSurface9_Release(pDepthStencil);
1830 pDepthStencil = NULL;
1833 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
1834 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
1835 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
1837 cleanup:
1838 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
1839 if (pDevice)
1841 UINT refcount = IDirect3D9_Release(pDevice);
1842 ok(!refcount, "Device has %u references left.\n", refcount);
1844 if (pD3d) IDirect3D9_Release(pD3d);
1845 if(hwnd) DestroyWindow(hwnd);
1848 static void test_get_rt(void)
1850 IDirect3DSurface9 *backbuffer, *rt;
1851 IDirect3DDevice9 *device;
1852 IDirect3D9 *d3d9;
1853 D3DCAPS9 caps;
1854 HWND window;
1855 HRESULT hr;
1856 ULONG ref;
1857 UINT i;
1859 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
1861 skip("Failed to create IDirect3D9 object, skipping tests.\n");
1862 return;
1865 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1866 0, 0, 128, 128, 0, 0, 0, 0);
1867 device = create_device(d3d9, window, window, TRUE);
1868 if (!device)
1870 skip("Failed to create a D3D device, skipping tests.\n");
1871 goto done;
1874 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
1875 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
1876 ok(!!backbuffer, "Got a NULL backbuffer.\n");
1878 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1879 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1881 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
1883 rt = backbuffer;
1884 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
1885 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
1886 ok(!rt, "Got rt %p.\n", rt);
1889 IDirect3DSurface9_Release(backbuffer);
1891 ref = IDirect3DDevice9_Release(device);
1892 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
1893 done:
1894 IDirect3D9_Release(d3d9);
1895 DestroyWindow(window);
1898 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
1899 static void test_draw_indexed(void)
1901 static const struct {
1902 float position[3];
1903 DWORD color;
1904 } quad[] = {
1905 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
1906 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
1907 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
1908 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
1910 WORD indices[] = {0, 1, 2, 3, 0, 2};
1912 static const D3DVERTEXELEMENT9 decl_elements[] = {
1913 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1914 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
1915 D3DDECL_END()
1918 IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1919 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
1920 IDirect3DIndexBuffer9 *index_buffer = NULL;
1921 D3DPRESENT_PARAMETERS present_parameters;
1922 IDirect3DDevice9 *device = NULL;
1923 IDirect3D9 *d3d9;
1924 HRESULT hr;
1925 HWND hwnd;
1926 void *ptr;
1928 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", 0,
1929 0, 0, 10, 10, 0, 0, 0, 0);
1930 if (!hwnd)
1932 skip("Failed to create window\n");
1933 return;
1936 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
1937 if (!d3d9)
1939 skip("Failed to create IDirect3D9 object\n");
1940 goto cleanup;
1943 ZeroMemory(&present_parameters, sizeof(present_parameters));
1944 present_parameters.Windowed = TRUE;
1945 present_parameters.hDeviceWindow = hwnd;
1946 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
1948 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1949 NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
1950 if (FAILED(hr) || !device)
1952 skip("Failed to create device\n");
1953 goto cleanup;
1956 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1957 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1958 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1959 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1961 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
1962 ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
1963 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1964 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1965 memcpy(ptr, quad, sizeof(quad));
1966 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
1967 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1968 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
1969 ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
1971 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
1972 ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
1973 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
1974 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
1975 memcpy(ptr, indices, sizeof(indices));
1976 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
1977 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
1978 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1979 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
1980 hr = IDirect3DDevice9_BeginScene(device);
1981 ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1983 /* NULL index buffer. Should fail */
1984 hr = IDirect3DDevice9_SetIndices(device, NULL);
1985 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1986 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1987 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1988 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1989 hr, D3DERR_INVALIDCALL);
1991 /* Valid index buffer, NULL vertex declaration. Should fail */
1992 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
1993 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
1994 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
1995 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
1996 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
1997 hr, D3DERR_INVALIDCALL);
1999 /* Valid index buffer and vertex declaration. Should succeed */
2000 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2001 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2002 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2003 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2004 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
2006 hr = IDirect3DDevice9_EndScene(device);
2007 ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2009 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2010 ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2012 IDirect3DVertexBuffer9_Release(vertex_buffer);
2013 IDirect3DIndexBuffer9_Release(index_buffer);
2014 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2016 cleanup:
2017 if (device)
2019 UINT refcount = IDirect3DDevice9_Release(device);
2020 ok(!refcount, "Device has %u references left.\n", refcount);
2022 if (d3d9) IDirect3D9_Release(d3d9);
2023 if (hwnd) DestroyWindow(hwnd);
2026 static void test_null_stream(void)
2028 IDirect3DVertexBuffer9 *buffer = NULL;
2029 D3DPRESENT_PARAMETERS present_parameters;
2030 IDirect3DDevice9 *device = NULL;
2031 IDirect3D9 *d3d9;
2032 HWND hwnd;
2033 HRESULT hr;
2034 IDirect3DVertexShader9 *shader = NULL;
2035 IDirect3DVertexDeclaration9 *decl = NULL;
2036 static const DWORD shader_code[] =
2038 0xfffe0101, /* vs_1_1 */
2039 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2040 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2041 0x0000ffff /* end */
2043 static const D3DVERTEXELEMENT9 decl_elements[] = {
2044 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2045 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2046 D3DDECL_END()
2049 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2050 ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2051 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2052 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2053 ok(hwnd != NULL, "Failed to create window\n");
2054 if (!d3d9 || !hwnd) goto cleanup;
2056 ZeroMemory(&present_parameters, sizeof(present_parameters));
2057 present_parameters.Windowed = TRUE;
2058 present_parameters.hDeviceWindow = hwnd;
2059 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2061 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
2062 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2063 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2064 if(!device)
2066 skip("Failed to create a d3d device\n");
2067 goto cleanup;
2070 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2071 if(FAILED(hr)) {
2072 skip("No vertex shader support\n");
2073 goto cleanup;
2075 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2076 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2077 if (FAILED(hr)) {
2078 skip("Vertex declaration handling not possible.\n");
2079 goto cleanup;
2081 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2082 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2083 if (FAILED(hr)) {
2084 skip("Vertex buffer handling not possible.\n");
2085 goto cleanup;
2088 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
2089 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2090 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
2091 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2092 hr = IDirect3DDevice9_SetVertexShader(device, shader);
2093 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
2094 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2095 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
2097 hr = IDirect3DDevice9_BeginScene(device);
2098 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (0x%08x)\n", hr);
2099 if(SUCCEEDED(hr)) {
2100 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
2101 ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitive failed (0x%08x)\n", hr);
2103 hr = IDirect3DDevice9_EndScene(device);
2104 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed (0x%08x)\n", hr);
2107 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2108 IDirect3DDevice9_SetVertexShader(device, NULL);
2109 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2111 cleanup:
2112 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
2113 if(decl) IDirect3DVertexDeclaration9_Release(decl);
2114 if(shader) IDirect3DVertexShader9_Release(shader);
2115 if (device)
2117 UINT refcount = IDirect3DDevice9_Release(device);
2118 ok(!refcount, "Device has %u references left.\n", refcount);
2120 if(d3d9) IDirect3D9_Release(d3d9);
2123 static void test_lights(void)
2125 D3DPRESENT_PARAMETERS present_parameters;
2126 IDirect3DDevice9 *device = NULL;
2127 IDirect3D9 *d3d9;
2128 HWND hwnd;
2129 HRESULT hr;
2130 unsigned int i;
2131 BOOL enabled;
2132 D3DCAPS9 caps;
2134 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2135 ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2136 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2137 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2138 ok(hwnd != NULL, "Failed to create window\n");
2139 if (!d3d9 || !hwnd) goto cleanup;
2141 ZeroMemory(&present_parameters, sizeof(present_parameters));
2142 present_parameters.Windowed = TRUE;
2143 present_parameters.hDeviceWindow = hwnd;
2144 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2146 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2147 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2148 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2149 "IDirect3D9_CreateDevice failed with %08x\n", hr);
2150 if(!device)
2152 skip("Failed to create a d3d device\n");
2153 goto cleanup;
2156 memset(&caps, 0, sizeof(caps));
2157 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2158 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
2160 for(i = 1; i <= caps.MaxActiveLights; i++) {
2161 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
2162 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2163 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
2164 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
2165 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2168 /* TODO: Test the rendering results in this situation */
2169 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
2170 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2171 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
2172 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2173 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2174 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
2175 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2177 for(i = 1; i <= caps.MaxActiveLights; i++) {
2178 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2179 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2182 cleanup:
2183 if (device)
2185 UINT refcount = IDirect3DDevice9_Release(device);
2186 ok(!refcount, "Device has %u references left.\n", refcount);
2188 if(d3d9) IDirect3D9_Release(d3d9);
2191 static void test_set_stream_source(void)
2193 D3DPRESENT_PARAMETERS present_parameters;
2194 IDirect3DDevice9 *device = NULL;
2195 IDirect3D9 *d3d9;
2196 HWND hwnd;
2197 HRESULT hr;
2198 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
2200 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2201 ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
2202 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2203 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2204 ok(hwnd != NULL, "Failed to create window\n");
2205 if (!d3d9 || !hwnd) goto cleanup;
2207 ZeroMemory(&present_parameters, sizeof(present_parameters));
2208 present_parameters.Windowed = TRUE;
2209 present_parameters.hDeviceWindow = hwnd;
2210 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2212 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2213 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2214 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2215 "IDirect3D9_CreateDevice failed with %08x\n", hr);
2216 if(!device)
2218 hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hwnd,
2219 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device );
2220 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
2221 "IDirect3D9_CreateDevice failed with %08x\n", hr);
2222 if(!device)
2224 skip("Failed to create a d3d device\n");
2225 goto cleanup;
2229 hr = IDirect3DDevice9_CreateVertexBuffer( device, 512, 0, 0, D3DPOOL_DEFAULT, &pVertexBuffer, NULL );
2230 ok(hr == D3D_OK, "Failed to create a vertex buffer, hr = %08x\n", hr);
2231 if (SUCCEEDED(hr)) {
2232 /* Some cards(Geforce 7400 at least) accept non-aligned offsets, others(radeon 9000 verified) reject it,
2233 * so accept both results. Wine currently rejects this to be able to optimize the vbo conversion, but writes
2234 * a WARN
2236 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 32);
2237 ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2238 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 1, 32);
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, pVertexBuffer, 2, 32);
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, pVertexBuffer, 3, 32);
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, pVertexBuffer, 4, 32);
2245 ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2247 /* Try to set the NULL buffer with an offset and stride 0 */
2248 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2249 ok(hr == D3D_OK, "Failed to set the stream source, offset 0, hr = %08x\n", hr);
2250 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2251 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 1, hr = %08x\n", hr);
2252 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2253 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 2, hr = %08x\n", hr);
2254 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2255 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Unexpected result when setting the stream source, offset 3, hr = %08x\n", hr);
2256 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2257 ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2259 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2260 ok(hr == D3D_OK, "Failed to set the stream source, offset 4, hr = %08x\n", hr);
2262 cleanup:
2263 if (pVertexBuffer) IDirect3DVertexBuffer9_Release(pVertexBuffer);
2264 if (device)
2266 UINT refcount = IDirect3DDevice9_Release(device);
2267 ok(!refcount, "Device has %u references left.\n", refcount);
2269 if(d3d9) IDirect3D9_Release(d3d9);
2272 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
2273 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
2274 * a fixed number of combinations are possible in fullscreen mode. In windowed
2275 * mode more combinations are allowed due to format conversion and this is
2276 * likely driver dependent. */
2277 static void test_display_formats(void)
2279 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
2280 unsigned int backbuffer, display;
2281 unsigned int windowed;
2282 IDirect3D9 *d3d9;
2283 BOOL should_pass;
2284 BOOL has_modes;
2285 HRESULT hr;
2287 static const struct
2289 const char *name;
2290 D3DFORMAT format;
2291 D3DFORMAT alpha_format;
2292 BOOL display;
2293 BOOL windowed;
2295 formats[] =
2297 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
2298 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
2299 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
2300 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
2301 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
2302 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
2303 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
2306 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
2308 skip("Failed to create an IDirect3D9 object, skipping test.\n");
2309 return;
2312 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
2314 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
2316 for (windowed = 0; windowed <= 1; ++windowed)
2318 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
2320 should_pass = FALSE;
2322 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
2324 D3DFORMAT backbuffer_format;
2326 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
2327 backbuffer_format = formats[display].format;
2328 else
2329 backbuffer_format = formats[backbuffer].format;
2331 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
2332 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
2333 if (hr == D3D_OK)
2335 if (windowed)
2337 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
2338 backbuffer_format, formats[display].format);
2339 should_pass = (hr == D3D_OK);
2341 else
2342 should_pass = (formats[display].format == formats[backbuffer].format
2343 || (formats[display].alpha_format
2344 && formats[display].alpha_format == formats[backbuffer].alpha_format));
2348 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
2349 formats[display].format, formats[backbuffer].format, windowed);
2350 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
2351 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
2352 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
2357 IDirect3D9_Release(d3d9);
2360 static void test_scissor_size(void)
2362 IDirect3D9 *d3d9_ptr = 0;
2363 unsigned int i;
2364 static struct {
2365 int winx; int winy; int backx; int backy; BOOL window;
2366 } scts[] = { /* scissor tests */
2367 {800, 600, 640, 480, TRUE},
2368 {800, 600, 640, 480, FALSE},
2369 {640, 480, 800, 600, TRUE},
2370 {640, 480, 800, 600, FALSE},
2373 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
2374 ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
2375 if (!d3d9_ptr){
2376 skip("Failed to create IDirect3D9 object\n");
2377 return;
2380 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
2381 IDirect3DDevice9 *device_ptr = 0;
2382 D3DPRESENT_PARAMETERS present_parameters;
2383 HRESULT hr;
2384 HWND hwnd = 0;
2385 RECT scissorrect;
2387 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
2388 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
2390 if (!scts[i].window)
2392 scts[i].backx = screen_width;
2393 scts[i].backy = screen_height;
2396 ZeroMemory(&present_parameters, sizeof(present_parameters));
2397 present_parameters.Windowed = scts[i].window;
2398 present_parameters.hDeviceWindow = hwnd;
2399 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2400 present_parameters.BackBufferWidth = scts[i].backx;
2401 present_parameters.BackBufferHeight = scts[i].backy;
2402 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
2403 present_parameters.EnableAutoDepthStencil = TRUE;
2404 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2406 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2407 if(FAILED(hr)) {
2408 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
2409 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2410 if(FAILED(hr)) {
2411 hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
2414 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
2416 if (!device_ptr)
2418 DestroyWindow(hwnd);
2419 skip("Creating the device failed\n");
2420 goto err_out;
2423 /* Check for the default scissor rect size */
2424 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2425 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2426 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);
2428 /* check the scissorrect values after a reset */
2429 present_parameters.BackBufferWidth = screen_width;
2430 present_parameters.BackBufferHeight = screen_height;
2431 hr = IDirect3DDevice9_Reset(device_ptr, &present_parameters);
2432 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2433 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
2434 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2436 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
2437 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
2438 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);
2440 if(device_ptr) {
2441 ULONG ref;
2443 ref = IDirect3DDevice9_Release(device_ptr);
2444 DestroyWindow(hwnd);
2445 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
2449 err_out:
2450 if(d3d9_ptr) IDirect3D9_Release(d3d9_ptr);
2451 return;
2454 static void test_multi_device(void)
2456 IDirect3DDevice9 *device1 = NULL, *device2 = NULL;
2457 D3DPRESENT_PARAMETERS present_parameters;
2458 HWND hwnd1 = NULL, hwnd2 = NULL;
2459 IDirect3D9 *d3d9;
2460 ULONG refcount;
2461 HRESULT hr;
2463 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2464 ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2465 if (!d3d9) goto fail;
2467 hwnd1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2468 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2469 ok(hwnd1 != NULL, "Failed to create a window.\n");
2470 if (!hwnd1) goto fail;
2472 memset(&present_parameters, 0, sizeof(present_parameters));
2473 present_parameters.Windowed = TRUE;
2474 present_parameters.hDeviceWindow = hwnd1;
2475 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2477 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd1,
2478 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device1);
2479 IDirect3D9_Release(d3d9);
2480 d3d9 = NULL;
2481 if (FAILED(hr)) {
2482 skip("Failed to create a device\n");
2483 goto fail;
2486 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2487 ok(d3d9 != NULL, "Failed to create a d3d9 object.\n");
2488 if (!d3d9) goto fail;
2490 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2491 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2492 ok(hwnd2 != NULL, "Failed to create a window.\n");
2493 if (!hwnd2) goto fail;
2495 memset(&present_parameters, 0, sizeof(present_parameters));
2496 present_parameters.Windowed = TRUE;
2497 present_parameters.hDeviceWindow = hwnd2;
2498 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2500 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd2,
2501 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device2);
2502 ok(SUCCEEDED(hr), "Failed to create a device, hr %#x\n", hr);
2503 IDirect3D9_Release(d3d9);
2504 d3d9 = NULL;
2505 if (FAILED(hr)) goto fail;
2507 fail:
2508 if (d3d9) IDirect3D9_Release(d3d9);
2509 if (device1)
2511 refcount = IDirect3DDevice9_Release(device1);
2512 ok(!refcount, "Device has %u references left.\n", refcount);
2514 if (device2)
2516 refcount = IDirect3DDevice9_Release(device2);
2517 ok(!refcount, "Device has %u references left.\n", refcount);
2519 if (hwnd1) DestroyWindow(hwnd1);
2520 if (hwnd2) DestroyWindow(hwnd2);
2523 static HWND filter_messages;
2525 enum message_window
2527 DEVICE_WINDOW,
2528 FOCUS_WINDOW,
2531 struct message
2533 UINT message;
2534 enum message_window window;
2537 static const struct message *expect_messages;
2538 static HWND device_window, focus_window;
2540 struct wndproc_thread_param
2542 HWND dummy_window;
2543 HANDLE window_created;
2544 HANDLE test_finished;
2545 BOOL running_in_foreground;
2548 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2550 if (filter_messages && filter_messages == hwnd)
2552 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2553 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2556 if (expect_messages)
2558 HWND w;
2560 switch (expect_messages->window)
2562 case DEVICE_WINDOW:
2563 w = device_window;
2564 break;
2566 case FOCUS_WINDOW:
2567 w = focus_window;
2568 break;
2570 default:
2571 w = NULL;
2572 break;
2575 if (hwnd == w && expect_messages->message == message) ++expect_messages;
2578 return DefWindowProcA(hwnd, message, wparam, lparam);
2581 static DWORD WINAPI wndproc_thread(void *param)
2583 struct wndproc_thread_param *p = param;
2584 DWORD res;
2585 BOOL ret;
2587 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2588 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2589 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2591 ret = SetEvent(p->window_created);
2592 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2594 for (;;)
2596 MSG msg;
2598 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2599 res = WaitForSingleObject(p->test_finished, 100);
2600 if (res == WAIT_OBJECT_0) break;
2601 if (res != WAIT_TIMEOUT)
2603 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2604 break;
2608 DestroyWindow(p->dummy_window);
2610 return 0;
2613 static void test_wndproc(void)
2615 struct wndproc_thread_param thread_params;
2616 IDirect3DDevice9 *device;
2617 WNDCLASSA wc = {0};
2618 IDirect3D9 *d3d9;
2619 HANDLE thread;
2620 LONG_PTR proc;
2621 ULONG ref;
2622 DWORD res, tid;
2623 HWND tmp;
2625 static const struct message messages[] =
2627 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW},
2628 {WM_ACTIVATE, FOCUS_WINDOW},
2629 {WM_SETFOCUS, FOCUS_WINDOW},
2630 {0, 0},
2633 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
2635 skip("Failed to create IDirect3D9 object, skipping tests.\n");
2636 return;
2639 wc.lpfnWndProc = test_proc;
2640 wc.lpszClassName = "d3d9_test_wndproc_wc";
2641 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2643 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
2644 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2645 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
2646 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2648 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2649 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2650 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2651 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2652 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2653 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2655 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2656 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2658 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2659 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2660 (LONG_PTR)test_proc, proc);
2661 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2662 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2663 (LONG_PTR)test_proc, proc);
2665 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2666 device_window, focus_window, thread_params.dummy_window);
2668 tmp = GetFocus();
2669 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2670 if (thread_params.running_in_foreground)
2672 tmp = GetForegroundWindow();
2673 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2674 thread_params.dummy_window, tmp);
2676 else
2677 skip("Not running in foreground, skip foreground window test\n");
2679 flush_events();
2681 expect_messages = messages;
2683 device = create_device(d3d9, device_window, focus_window, FALSE);
2684 if (!device)
2686 skip("Failed to create a D3D device, skipping tests.\n");
2687 goto done;
2690 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2691 expect_messages->message, expect_messages->window);
2692 expect_messages = NULL;
2694 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2696 tmp = GetFocus();
2697 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2698 tmp = GetForegroundWindow();
2699 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2701 SetForegroundWindow(focus_window);
2702 flush_events();
2704 filter_messages = focus_window;
2706 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2707 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2708 (LONG_PTR)test_proc, proc);
2710 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2711 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2712 (LONG_PTR)test_proc, proc);
2714 ref = IDirect3DDevice9_Release(device);
2715 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2717 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2718 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2719 (LONG_PTR)test_proc, proc);
2721 device = create_device(d3d9, focus_window, focus_window, FALSE);
2722 if (!device)
2724 skip("Failed to create a D3D device, skipping tests.\n");
2725 goto done;
2728 ref = IDirect3DDevice9_Release(device);
2729 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2731 device = create_device(d3d9, device_window, focus_window, FALSE);
2732 if (!device)
2734 skip("Failed to create a D3D device, skipping tests.\n");
2735 goto done;
2738 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
2739 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, got %#lx.\n",
2740 (LONG_PTR)test_proc, proc);
2742 ref = IDirect3DDevice9_Release(device);
2743 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2745 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2746 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
2747 (LONG_PTR)DefWindowProcA, proc);
2749 done:
2750 filter_messages = NULL;
2751 IDirect3D9_Release(d3d9);
2753 SetEvent(thread_params.test_finished);
2754 WaitForSingleObject(thread, INFINITE);
2755 CloseHandle(thread_params.test_finished);
2756 CloseHandle(thread_params.window_created);
2757 CloseHandle(thread);
2759 DestroyWindow(device_window);
2760 DestroyWindow(focus_window);
2761 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2764 static void test_wndproc_windowed(void)
2766 struct wndproc_thread_param thread_params;
2767 IDirect3DDevice9 *device;
2768 WNDCLASSA wc = {0};
2769 IDirect3D9 *d3d9;
2770 HANDLE thread;
2771 LONG_PTR proc;
2772 HRESULT hr;
2773 ULONG ref;
2774 DWORD res, tid;
2775 HWND tmp;
2777 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
2779 skip("Failed to create IDirect3D9 object, skipping tests.\n");
2780 return;
2783 wc.lpfnWndProc = test_proc;
2784 wc.lpszClassName = "d3d9_test_wndproc_wc";
2785 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2787 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
2788 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2789 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
2790 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2792 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2793 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2794 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2795 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
2796 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2797 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2799 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2800 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2802 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2803 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2804 (LONG_PTR)test_proc, proc);
2805 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2806 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2807 (LONG_PTR)test_proc, proc);
2809 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2810 device_window, focus_window, thread_params.dummy_window);
2812 tmp = GetFocus();
2813 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2814 if (thread_params.running_in_foreground)
2816 tmp = GetForegroundWindow();
2817 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2818 thread_params.dummy_window, tmp);
2820 else
2821 skip("Not running in foreground, skip foreground window test\n");
2823 filter_messages = focus_window;
2825 device = create_device(d3d9, device_window, focus_window, TRUE);
2826 if (!device)
2828 skip("Failed to create a D3D device, skipping tests.\n");
2829 goto done;
2832 tmp = GetFocus();
2833 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2834 tmp = GetForegroundWindow();
2835 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2836 thread_params.dummy_window, tmp);
2838 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2839 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2840 (LONG_PTR)test_proc, proc);
2842 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2843 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2844 (LONG_PTR)test_proc, proc);
2846 filter_messages = NULL;
2848 hr = reset_device(device, device_window, FALSE);
2849 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2851 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2852 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2853 (LONG_PTR)test_proc, proc);
2855 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2856 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2857 (LONG_PTR)test_proc, proc);
2859 hr = reset_device(device, device_window, TRUE);
2860 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
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 = focus_window;
2872 ref = IDirect3DDevice9_Release(device);
2873 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2875 filter_messages = device_window;
2877 device = create_device(d3d9, focus_window, focus_window, TRUE);
2878 if (!device)
2880 skip("Failed to create a D3D device, skipping tests.\n");
2881 goto done;
2884 filter_messages = NULL;
2886 hr = reset_device(device, focus_window, FALSE);
2887 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2889 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2890 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2891 (LONG_PTR)test_proc, proc);
2893 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2894 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2895 (LONG_PTR)test_proc, proc);
2897 hr = reset_device(device, focus_window, TRUE);
2898 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2900 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2901 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2902 (LONG_PTR)test_proc, proc);
2904 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2905 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2906 (LONG_PTR)test_proc, proc);
2908 filter_messages = device_window;
2910 ref = IDirect3DDevice9_Release(device);
2911 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2913 device = create_device(d3d9, device_window, focus_window, TRUE);
2914 if (!device)
2916 skip("Failed to create a D3D device, skipping tests.\n");
2917 goto done;
2920 filter_messages = NULL;
2922 hr = reset_device(device, device_window, FALSE);
2923 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2925 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2926 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2927 (LONG_PTR)test_proc, proc);
2929 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2930 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2931 (LONG_PTR)test_proc, proc);
2933 hr = reset_device(device, device_window, TRUE);
2934 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2936 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2937 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2938 (LONG_PTR)test_proc, proc);
2940 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2941 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2942 (LONG_PTR)test_proc, proc);
2944 filter_messages = device_window;
2946 ref = IDirect3DDevice9_Release(device);
2947 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2949 done:
2950 filter_messages = NULL;
2951 IDirect3D9_Release(d3d9);
2953 SetEvent(thread_params.test_finished);
2954 WaitForSingleObject(thread, INFINITE);
2955 CloseHandle(thread_params.test_finished);
2956 CloseHandle(thread_params.window_created);
2957 CloseHandle(thread);
2959 DestroyWindow(device_window);
2960 DestroyWindow(focus_window);
2961 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
2964 static void test_reset_fullscreen(void)
2966 WNDCLASSEXA wc = {0};
2967 IDirect3DDevice9 *device = NULL;
2968 IDirect3D9 *d3d = NULL;
2969 ATOM atom;
2970 static const struct message messages[] =
2972 {WM_ACTIVATEAPP, FOCUS_WINDOW},
2973 {0, 0},
2976 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2977 ok(d3d != NULL, "Failed to create an IDirect3D object.\n");
2978 expect_messages = messages;
2980 wc.cbSize = sizeof(wc);
2981 wc.lpfnWndProc = test_proc;
2982 wc.lpszClassName = "test_reset_fullscreen";
2984 atom = RegisterClassExA(&wc);
2985 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
2987 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
2988 0, 0, screen_width, screen_height, NULL, NULL, NULL, NULL);
2989 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
2992 * Create a device in windowed mode.
2993 * Since the device is windowed and we haven't called any methods that
2994 * could show the window (such as ShowWindow or SetWindowPos) yet,
2995 * WM_ACTIVATEAPP will not have been sent.
2997 device = create_device(d3d, device_window, focus_window, TRUE);
2998 if (!device)
3000 skip("Unable to create device. Skipping test.\n");
3001 goto cleanup;
3005 * Switch to fullscreen mode.
3006 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
3007 * message to be sent.
3009 ok(SUCCEEDED(reset_device(device, device_window, FALSE)), "Failed to reset device.\n");
3011 flush_events();
3012 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
3013 expect_messages = NULL;
3015 cleanup:
3016 if (device) IDirect3DDevice9_Release(device);
3017 if (d3d) IDirect3D9_Release(d3d);
3018 DestroyWindow(device_window);
3019 device_window = focus_window = NULL;
3020 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
3024 static inline void set_fpu_cw(WORD cw)
3026 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3027 #define D3D9_TEST_SET_FPU_CW 1
3028 __asm__ volatile ("fnclex");
3029 __asm__ volatile ("fldcw %0" : : "m" (cw));
3030 #elif defined(__i386__) && defined(_MSC_VER)
3031 #define D3D9_TEST_SET_FPU_CW 1
3032 __asm fnclex;
3033 __asm fldcw cw;
3034 #endif
3037 static inline WORD get_fpu_cw(void)
3039 WORD cw = 0;
3040 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3041 #define D3D9_TEST_GET_FPU_CW 1
3042 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3043 #elif defined(__i386__) && defined(_MSC_VER)
3044 #define D3D9_TEST_GET_FPU_CW 1
3045 __asm fnstcw cw;
3046 #endif
3047 return cw;
3050 static void test_fpu_setup(void)
3052 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
3053 D3DPRESENT_PARAMETERS present_parameters;
3054 IDirect3DDevice9 *device;
3055 HWND window = NULL;
3056 IDirect3D9 *d3d9;
3057 HRESULT hr;
3058 WORD cw;
3060 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3061 ok(!!d3d9, "Failed to create a d3d9 object.\n");
3062 if (!d3d9) return;
3064 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0, screen_width, screen_height, 0, 0, 0, 0);
3065 ok(!!window, "Failed to create a window.\n");
3066 if (!window) goto done;
3068 memset(&present_parameters, 0, sizeof(present_parameters));
3069 present_parameters.Windowed = TRUE;
3070 present_parameters.hDeviceWindow = window;
3071 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
3073 set_fpu_cw(0xf60);
3074 cw = get_fpu_cw();
3075 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3077 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3078 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
3079 if (FAILED(hr))
3081 skip("Failed to create a device, hr %#x.\n", hr);
3082 set_fpu_cw(0x37f);
3083 goto done;
3086 cw = get_fpu_cw();
3087 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3089 IDirect3DDevice9_Release(device);
3091 cw = get_fpu_cw();
3092 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3093 set_fpu_cw(0xf60);
3094 cw = get_fpu_cw();
3095 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3097 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3098 D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, &present_parameters, &device);
3099 ok(SUCCEEDED(hr), "CreateDevice failed, hr %#x.\n", hr);
3101 cw = get_fpu_cw();
3102 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3103 set_fpu_cw(0x37f);
3105 IDirect3DDevice9_Release(device);
3107 done:
3108 if (window) DestroyWindow(window);
3109 if (d3d9) IDirect3D9_Release(d3d9);
3110 #endif
3113 static void test_window_style(void)
3115 RECT focus_rect, fullscreen_rect, r;
3116 LONG device_style, device_exstyle;
3117 LONG focus_style, focus_exstyle;
3118 LONG style, expected_style;
3119 IDirect3DDevice9 *device;
3120 IDirect3D9 *d3d9;
3121 HRESULT hr;
3122 ULONG ref;
3125 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3127 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3128 return;
3131 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3132 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3133 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3134 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3136 device_style = GetWindowLongA(device_window, GWL_STYLE);
3137 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3138 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3139 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3141 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3142 GetWindowRect(focus_window, &focus_rect);
3144 device = create_device(d3d9, device_window, focus_window, FALSE);
3145 if (!device)
3147 skip("Failed to create a D3D device, skipping tests.\n");
3148 goto done;
3151 style = GetWindowLongA(device_window, GWL_STYLE);
3152 expected_style = device_style | WS_VISIBLE;
3153 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3154 expected_style, style);
3155 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3156 expected_style = device_exstyle | WS_EX_TOPMOST;
3157 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3158 expected_style, style);
3160 style = GetWindowLongA(focus_window, GWL_STYLE);
3161 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3162 focus_style, style);
3163 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3164 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3165 focus_exstyle, style);
3167 GetWindowRect(device_window, &r);
3168 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3169 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3170 r.left, r.top, r.right, r.bottom);
3171 GetClientRect(device_window, &r);
3172 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3173 GetWindowRect(focus_window, &r);
3174 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3175 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3176 r.left, r.top, r.right, r.bottom);
3178 hr = reset_device(device, device_window, TRUE);
3179 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3181 style = GetWindowLongA(device_window, GWL_STYLE);
3182 expected_style = device_style | WS_VISIBLE;
3183 ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3184 expected_style, style);
3185 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3186 expected_style = device_exstyle | WS_EX_TOPMOST;
3187 ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3188 expected_style, style);
3190 style = GetWindowLongA(focus_window, GWL_STYLE);
3191 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3192 focus_style, style);
3193 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3194 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3195 focus_exstyle, style);
3197 ref = IDirect3DDevice9_Release(device);
3198 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3200 done:
3201 IDirect3D9_Release(d3d9);
3203 DestroyWindow(device_window);
3204 DestroyWindow(focus_window);
3207 static const POINT *expect_pos;
3209 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
3211 if (message == WM_MOUSEMOVE)
3213 if (expect_pos && expect_pos->x && expect_pos->y)
3215 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
3217 ClientToScreen(window, &p);
3218 if (expect_pos->x == p.x && expect_pos->y == p.y)
3219 ++expect_pos;
3223 return DefWindowProcA(window, message, wparam, lparam);
3226 static void test_cursor_pos(void)
3228 IDirect3DSurface9 *cursor;
3229 IDirect3DDevice9 *device;
3230 WNDCLASSA wc = {0};
3231 IDirect3D9 *d3d9;
3232 UINT refcount;
3233 HWND window;
3234 HRESULT hr;
3235 BOOL ret;
3237 /* Note that we don't check for movement we're not supposed to receive.
3238 * That's because it's hard to distinguish from the user accidentally
3239 * moving the mouse. */
3240 static const POINT points[] =
3242 {50, 50},
3243 {75, 75},
3244 {100, 100},
3245 {125, 125},
3246 {150, 150},
3247 {125, 125},
3248 {150, 150},
3249 {150, 150},
3250 {0, 0},
3253 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3255 skip("Failed to create IDirect3D9 object, skipping cursor tests.\n");
3256 return;
3259 wc.lpfnWndProc = test_cursor_proc;
3260 wc.lpszClassName = "d3d9_test_cursor_wc";
3261 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3262 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3263 0, 0, 320, 240, NULL, NULL, NULL, NULL);
3264 ShowWindow(window, SW_SHOW);
3266 device = create_device(d3d9, window, window, TRUE);
3267 if (!device)
3269 skip("Failed to create a D3D device, skipping tests.\n");
3270 goto done;
3273 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
3274 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
3275 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
3276 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
3277 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
3278 IDirect3DSurface9_Release(cursor);
3279 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
3280 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
3282 flush_events();
3283 expect_pos = points;
3285 ret = SetCursorPos(50, 50);
3286 ok(ret, "Failed to set cursor position.\n");
3287 flush_events();
3289 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3290 flush_events();
3291 /* SetCursorPosition() eats duplicates. */
3292 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
3293 flush_events();
3295 ret = SetCursorPos(100, 100);
3296 ok(ret, "Failed to set cursor position.\n");
3297 flush_events();
3298 /* Even if the position was set with SetCursorPos(). */
3299 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
3300 flush_events();
3302 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3303 flush_events();
3304 ret = SetCursorPos(150, 150);
3305 ok(ret, "Failed to set cursor position.\n");
3306 flush_events();
3307 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
3308 flush_events();
3310 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
3311 flush_events();
3312 /* SetCursorPos() doesn't. */
3313 ret = SetCursorPos(150, 150);
3314 ok(ret, "Failed to set cursor position.\n");
3315 flush_events();
3317 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
3318 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
3320 refcount = IDirect3DDevice9_Release(device);
3321 ok(!refcount, "Device has %u references left.\n", refcount);
3322 done:
3323 DestroyWindow(window);
3324 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
3325 if (d3d9)
3326 IDirect3D9_Release(d3d9);
3329 static void test_mode_change(void)
3331 RECT fullscreen_rect, focus_rect, r;
3332 IDirect3DSurface9 *backbuffer;
3333 IDirect3DDevice9 *device;
3334 D3DSURFACE_DESC desc;
3335 IDirect3D9 *d3d9;
3336 DEVMODEW devmode;
3337 UINT refcount;
3338 HRESULT hr;
3339 DWORD ret;
3341 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3343 skip("Failed to create IDirect3D9 object, skipping mode change tests.\n");
3344 return;
3347 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3348 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3349 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3350 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3352 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3353 GetWindowRect(focus_window, &focus_rect);
3355 device = create_device(d3d9, device_window, focus_window, FALSE);
3356 if (!device)
3358 skip("Failed to create a D3D device, skipping tests.\n");
3359 goto done;
3362 memset(&devmode, 0, sizeof(devmode));
3363 devmode.dmSize = sizeof(devmode);
3364 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3365 devmode.dmPelsWidth = 640;
3366 devmode.dmPelsHeight = 480;
3368 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3369 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
3371 memset(&devmode, 0, sizeof(devmode));
3372 devmode.dmSize = sizeof(devmode);
3373 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3374 ok(ret, "Failed to get display mode.\n");
3375 ok(devmode.dmPelsWidth == 640, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3376 ok(devmode.dmPelsHeight == 480, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3378 GetWindowRect(device_window, &r);
3379 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3380 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3381 r.left, r.top, r.right, r.bottom);
3382 GetWindowRect(focus_window, &r);
3383 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3384 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
3385 r.left, r.top, r.right, r.bottom);
3387 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3388 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3389 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
3390 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3391 ok(desc.Width == screen_width, "Got unexpected backbuffer width %u.\n", desc.Width);
3392 ok(desc.Height == screen_height, "Got unexpected backbuffer height %u.\n", desc.Height);
3393 IDirect3DSurface9_Release(backbuffer);
3395 refcount = IDirect3DDevice9_Release(device);
3396 ok(!refcount, "Device has %u references left.\n", refcount);
3398 memset(&devmode, 0, sizeof(devmode));
3399 devmode.dmSize = sizeof(devmode);
3400 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3401 ok(ret, "Failed to get display mode.\n");
3402 ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3403 ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3405 done:
3406 DestroyWindow(device_window);
3407 DestroyWindow(focus_window);
3408 if (d3d9)
3409 IDirect3D9_Release(d3d9);
3411 memset(&devmode, 0, sizeof(devmode));
3412 devmode.dmSize = sizeof(devmode);
3413 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3414 ok(ret, "Failed to get display mode.\n");
3415 ok(devmode.dmPelsWidth == screen_width, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3416 ok(devmode.dmPelsHeight == screen_height, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3419 static void test_device_window_reset(void)
3421 RECT fullscreen_rect, device_rect, r;
3422 IDirect3DDevice9 *device;
3423 WNDCLASSA wc = {0};
3424 IDirect3D9 *d3d9;
3425 LONG_PTR proc;
3426 HRESULT hr;
3427 ULONG ref;
3429 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3431 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3432 return;
3435 wc.lpfnWndProc = test_proc;
3436 wc.lpszClassName = "d3d9_test_wndproc_wc";
3437 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3439 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3440 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3441 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3442 0, 0, screen_width / 2, screen_height / 2, 0, 0, 0, 0);
3444 SetRect(&fullscreen_rect, 0, 0, screen_width, screen_height);
3445 GetWindowRect(device_window, &device_rect);
3447 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3448 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3449 (LONG_PTR)test_proc, proc);
3450 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3451 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3452 (LONG_PTR)test_proc, proc);
3454 device = create_device(d3d9, NULL, focus_window, FALSE);
3455 if (!device)
3457 skip("Failed to create a D3D device, skipping tests.\n");
3458 goto done;
3461 GetWindowRect(focus_window, &r);
3462 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3463 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3464 r.left, r.top, r.right, r.bottom);
3465 GetWindowRect(device_window, &r);
3466 ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3467 device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
3468 r.left, r.top, r.right, r.bottom);
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 hr = reset_device(device, device_window, FALSE);
3478 ok(SUCCEEDED(hr), "Failed to reset device.\n");
3480 GetWindowRect(focus_window, &r);
3481 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
3482 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
3483 r.left, r.top, r.right, r.bottom);
3484 GetWindowRect(device_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);
3489 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3490 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3491 (LONG_PTR)test_proc, proc);
3492 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3493 ok(proc != (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3494 (LONG_PTR)test_proc, proc);
3496 ref = IDirect3DDevice9_Release(device);
3497 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3499 done:
3500 IDirect3D9_Release(d3d9);
3501 DestroyWindow(device_window);
3502 DestroyWindow(focus_window);
3503 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3506 static void test_reset_resources(void)
3508 IDirect3DSurface9 *surface, *rt;
3509 IDirect3DTexture9 *texture;
3510 IDirect3DDevice9 *device;
3511 IDirect3D9 *d3d9;
3512 unsigned int i;
3513 D3DCAPS9 caps;
3514 HWND window;
3515 HRESULT hr;
3516 ULONG ref;
3518 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3519 0, 0, 640, 480, 0, 0, 0, 0);
3521 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3523 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3524 DestroyWindow(window);
3525 return;
3528 if (!(device = create_device(d3d9, window, window, TRUE)))
3530 skip("Failed to create a D3D device, skipping tests.\n");
3531 goto done;
3534 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3535 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3537 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
3538 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
3539 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
3540 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
3541 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
3542 IDirect3DSurface9_Release(surface);
3544 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
3546 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
3547 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
3548 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
3549 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3550 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
3551 IDirect3DTexture9_Release(texture);
3552 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
3553 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
3554 IDirect3DSurface9_Release(surface);
3557 hr = reset_device(device, device_window, TRUE);
3558 ok(SUCCEEDED(hr), "Failed to reset device.\n");
3560 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
3561 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
3562 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
3563 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3564 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
3565 IDirect3DSurface9_Release(surface);
3566 IDirect3DSurface9_Release(rt);
3568 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
3570 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
3571 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
3574 ref = IDirect3DDevice9_Release(device);
3575 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3577 done:
3578 IDirect3D9_Release(d3d9);
3579 DestroyWindow(window);
3582 static void test_set_rt_vp_scissor(void)
3584 IDirect3DStateBlock9 *stateblock;
3585 IDirect3DDevice9 *device;
3586 IDirect3DSurface9 *rt;
3587 IDirect3D9 *d3d9;
3588 D3DVIEWPORT9 vp;
3589 UINT refcount;
3590 HWND window;
3591 HRESULT hr;
3592 RECT rect;
3594 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3596 skip("Failed to create IDirect3D9 object, skipping tests.\n");
3597 return;
3600 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3601 0, 0, 640, 480, 0, 0, 0, 0);
3602 if (!(device = create_device(d3d9, window, window, TRUE)))
3604 skip("Failed to create a D3D device, skipping tests.\n");
3605 DestroyWindow(window);
3606 return;
3609 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
3610 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
3611 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
3613 hr = IDirect3DDevice9_GetViewport(device, &vp);
3614 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3615 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3616 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3617 ok(vp.Width == screen_width, "Got unexpected vp.Width %u.\n", vp.Width);
3618 ok(vp.Height == screen_height, "Got unexpected vp.Height %u.\n", vp.Height);
3619 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3620 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3622 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3623 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3624 ok(rect.left == 0 && rect.top == 0 && rect.right == screen_width && rect.bottom == screen_height,
3625 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3626 rect.left, rect.top, rect.right, rect.bottom);
3628 hr = IDirect3DDevice9_BeginStateBlock(device);
3629 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
3631 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3632 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3634 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
3635 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
3636 IDirect3DStateBlock9_Release(stateblock);
3638 hr = IDirect3DDevice9_GetViewport(device, &vp);
3639 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3640 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3641 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3642 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3643 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3644 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3645 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3647 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3648 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3649 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3650 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3651 rect.left, rect.top, rect.right, rect.bottom);
3653 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3654 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3656 vp.X = 10;
3657 vp.Y = 20;
3658 vp.Width = 30;
3659 vp.Height = 40;
3660 vp.MinZ = 0.25f;
3661 vp.MaxZ = 0.75f;
3662 hr = IDirect3DDevice9_SetViewport(device, &vp);
3663 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
3665 SetRect(&rect, 50, 60, 70, 80);
3666 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
3667 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
3669 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
3670 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3672 hr = IDirect3DDevice9_GetViewport(device, &vp);
3673 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
3674 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
3675 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
3676 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
3677 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
3678 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
3679 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
3681 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
3682 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
3683 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
3684 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
3685 rect.left, rect.top, rect.right, rect.bottom);
3687 IDirect3DSurface9_Release(rt);
3688 refcount = IDirect3DDevice9_Release(device);
3689 ok(!refcount, "Device has %u references left.\n", refcount);
3690 IDirect3D9_Release(d3d9);
3691 DestroyWindow(window);
3694 static void test_volume_get_container(void)
3696 IDirect3DVolumeTexture9 *texture = NULL;
3697 IDirect3DVolume9 *volume = NULL;
3698 IDirect3DDevice9 *device;
3699 IUnknown *container;
3700 IDirect3D9 *d3d9;
3701 ULONG refcount;
3702 D3DCAPS9 caps;
3703 HWND window;
3704 HRESULT hr;
3706 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3708 skip("Failed to create d3d9 object, skipping tests.\n");
3709 return;
3712 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3713 0, 0, 640, 480, 0, 0, 0, 0);
3714 if (!(device = create_device(d3d9, window, window, TRUE)))
3716 skip("Failed to create a D3D device, skipping tests.\n");
3717 IDirect3D9_Release(d3d9);
3718 DestroyWindow(window);
3719 return;
3722 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3723 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3724 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3726 skip("No volume texture support, skipping tests.\n");
3727 IDirect3DDevice9_Release(device);
3728 IDirect3D9_Release(d3d9);
3729 DestroyWindow(window);
3730 return;
3733 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3734 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3735 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3736 ok(!!texture, "Got unexpected texture %p.\n", texture);
3738 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3739 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3740 ok(!!volume, "Got unexpected volume %p.\n", volume);
3742 /* These should work... */
3743 container = NULL;
3744 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
3745 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3746 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3747 IUnknown_Release(container);
3749 container = NULL;
3750 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
3751 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3752 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3753 IUnknown_Release(container);
3755 container = NULL;
3756 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
3757 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3758 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3759 IUnknown_Release(container);
3761 container = NULL;
3762 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
3763 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
3764 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
3765 IUnknown_Release(container);
3767 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
3768 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
3769 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3770 ok(!container, "Got unexpected container %p.\n", container);
3772 IDirect3DVolume9_Release(volume);
3773 IDirect3DVolumeTexture9_Release(texture);
3774 refcount = IDirect3DDevice9_Release(device);
3775 ok(!refcount, "Device has %u references left.\n", refcount);
3776 IDirect3D9_Release(d3d9);
3777 DestroyWindow(window);
3780 static void test_volume_resource(void)
3782 IDirect3DVolumeTexture9 *texture;
3783 IDirect3DResource9 *resource;
3784 IDirect3DVolume9 *volume;
3785 IDirect3DDevice9 *device;
3786 IDirect3D9 *d3d9;
3787 ULONG refcount;
3788 D3DCAPS9 caps;
3789 HWND window;
3790 HRESULT hr;
3792 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3794 skip("Failed to create d3d9 object, skipping tests.\n");
3795 return;
3798 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3799 0, 0, 640, 480, 0, 0, 0, 0);
3800 if (!(device = create_device(d3d9, window, window, TRUE)))
3802 skip("Failed to create a D3D device, skipping tests.\n");
3803 IDirect3D9_Release(d3d9);
3804 DestroyWindow(window);
3805 return;
3808 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3809 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3810 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
3812 skip("No volume texture support, skipping tests.\n");
3813 IDirect3DDevice9_Release(device);
3814 IDirect3D9_Release(d3d9);
3815 DestroyWindow(window);
3816 return;
3819 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
3820 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
3821 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
3822 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
3823 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
3824 IDirect3DVolumeTexture9_Release(texture);
3826 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
3827 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
3829 IDirect3DVolume9_Release(volume);
3830 refcount = IDirect3DDevice9_Release(device);
3831 ok(!refcount, "Device has %u references left.\n", refcount);
3832 IDirect3D9_Release(d3d9);
3833 DestroyWindow(window);
3836 static void test_vb_lock_flags(void)
3838 static const struct
3840 DWORD flags;
3841 const char *debug_string;
3842 HRESULT win7_result;
3844 test_data[] =
3846 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
3847 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
3848 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
3849 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
3850 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
3851 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
3852 /* Completely bogus flags aren't an error. */
3853 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
3855 IDirect3DVertexBuffer9 *buffer;
3856 IDirect3DDevice9 *device;
3857 IDirect3D9 *d3d9;
3858 unsigned int i;
3859 ULONG refcount;
3860 HWND window;
3861 HRESULT hr;
3862 void *data;
3864 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3866 skip("Failed to create d3d9 object, skipping tests.\n");
3867 return;
3870 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3871 0, 0, 640, 480, 0, 0, 0, 0);
3872 if (!(device = create_device(d3d9, window, window, TRUE)))
3874 skip("Failed to create a D3D device, skipping tests.\n");
3875 IDirect3D9_Release(d3d9);
3876 DestroyWindow(window);
3877 return;
3880 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
3881 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
3883 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
3885 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
3886 /* Windows XP always returns D3D_OK even with flags that don't make
3887 * sense. Windows 7 returns an error. At least one game (Shaiya)
3888 * depends on the Windows XP result, so mark the Windows 7 behavior as
3889 * broken. */
3890 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
3891 hr, test_data[i].debug_string);
3892 if (SUCCEEDED(hr))
3894 ok(!!data, "Got unexpected data %p.\n", data);
3895 hr = IDirect3DVertexBuffer9_Unlock(buffer);
3896 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3900 IDirect3DVertexBuffer9_Release(buffer);
3901 refcount = IDirect3DDevice9_Release(device);
3902 ok(!refcount, "Device has %u references left.\n", refcount);
3903 IDirect3D9_Release(d3d9);
3904 DestroyWindow(window);
3907 static const char *debug_d3dpool(D3DPOOL pool)
3909 switch (pool)
3911 case D3DPOOL_DEFAULT:
3912 return "D3DPOOL_DEFAULT";
3913 case D3DPOOL_SYSTEMMEM:
3914 return "D3DPOOL_SYSTEMMEM";
3915 case D3DPOOL_SCRATCH:
3916 return "D3DPOOL_SCRATCH";
3917 case D3DPOOL_MANAGED:
3918 return "D3DPOOL_MANAGED";
3919 default:
3920 return "unknown pool";
3924 static void test_vertex_buffer_alignment(void)
3926 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
3927 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
3928 IDirect3DVertexBuffer9 *buffer = NULL;
3929 const unsigned int align = 16;
3930 IDirect3DDevice9 *device;
3931 unsigned int i, j;
3932 IDirect3D9 *d3d9;
3933 ULONG refcount;
3934 HWND window;
3935 HRESULT hr;
3936 void *data;
3938 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
3940 skip("Failed to create d3d9 object, skipping tests.\n");
3941 return;
3944 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3945 0, 0, 640, 480, 0, 0, 0, 0);
3946 if (!(device = create_device(d3d9, window, window, TRUE)))
3948 skip("Failed to create a D3D device, skipping tests.\n");
3949 IDirect3D9_Release(d3d9);
3950 DestroyWindow(window);
3951 return;
3954 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
3956 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
3958 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
3959 if (pools[j] == D3DPOOL_SCRATCH)
3960 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
3961 else
3962 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
3963 debug_d3dpool(pools[j]), sizes[i], hr);
3964 if (FAILED(hr))
3965 continue;
3967 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
3968 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
3969 ok(!((DWORD_PTR)data & (align - 1)),
3970 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
3971 data, align, sizes[i], debug_d3dpool(pools[j]));
3972 hr = IDirect3DVertexBuffer9_Unlock(buffer);
3973 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
3974 IDirect3DVertexBuffer9_Release(buffer);
3978 refcount = IDirect3DDevice9_Release(device);
3979 ok(!refcount, "Device has %u references left.\n", refcount);
3980 IDirect3D9_Release(d3d9);
3981 DestroyWindow(window);
3984 static void test_query_support(void)
3986 static const D3DQUERYTYPE queries[] =
3988 D3DQUERYTYPE_VCACHE,
3989 D3DQUERYTYPE_RESOURCEMANAGER,
3990 D3DQUERYTYPE_VERTEXSTATS,
3991 D3DQUERYTYPE_EVENT,
3992 D3DQUERYTYPE_OCCLUSION,
3993 D3DQUERYTYPE_TIMESTAMP,
3994 D3DQUERYTYPE_TIMESTAMPDISJOINT,
3995 D3DQUERYTYPE_TIMESTAMPFREQ,
3996 D3DQUERYTYPE_PIPELINETIMINGS,
3997 D3DQUERYTYPE_INTERFACETIMINGS,
3998 D3DQUERYTYPE_VERTEXTIMINGS,
3999 D3DQUERYTYPE_PIXELTIMINGS,
4000 D3DQUERYTYPE_BANDWIDTHTIMINGS,
4001 D3DQUERYTYPE_CACHEUTILIZATION,
4003 IDirect3DQuery9 *query = NULL;
4004 IDirect3DDevice9 *device;
4005 IDirect3D9 *d3d9;
4006 unsigned int i;
4007 ULONG refcount;
4008 BOOL supported;
4009 HWND window;
4010 HRESULT hr;
4012 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
4014 skip("Failed to create d3d9 object, skipping tests.\n");
4015 return;
4018 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4019 0, 0, 640, 480, 0, 0, 0, 0);
4020 if (!(device = create_device(d3d9, window, window, TRUE)))
4022 skip("Failed to create a D3D device, skipping tests.\n");
4023 IDirect3D9_Release(d3d9);
4024 DestroyWindow(window);
4025 return;
4028 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
4030 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
4031 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4033 supported = hr == D3D_OK;
4035 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
4036 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
4038 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
4039 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
4041 if (query)
4043 IDirect3DQuery9_Release(query);
4044 query = NULL;
4048 refcount = IDirect3DDevice9_Release(device);
4049 ok(!refcount, "Device has %u references left.\n", refcount);
4050 IDirect3D9_Release(d3d9);
4051 DestroyWindow(window);
4054 static void test_occlusion_query_states(void)
4056 static const float point[3] = {0.0, 0.0, 0.0};
4057 IDirect3DQuery9 *query = NULL;
4058 unsigned int data_size, i;
4059 IDirect3DDevice9 *device;
4060 IDirect3D9 *d3d9;
4061 ULONG refcount;
4062 HWND window;
4063 HRESULT hr;
4064 BYTE *data;
4066 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
4068 skip("Failed to create d3d9 object, skipping tests.\n");
4069 return;
4072 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4073 0, 0, 640, 480, 0, 0, 0, 0);
4074 if (!(device = create_device(d3d9, window, window, TRUE)))
4076 skip("Failed to create a D3D device, skipping tests.\n");
4077 IDirect3D9_Release(d3d9);
4078 DestroyWindow(window);
4079 return;
4082 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
4083 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
4084 if (!query)
4086 skip("Occlusion queries are not supported, skipping tests.\n");
4087 IDirect3DDevice9_Release(device);
4088 IDirect3D9_Release(d3d9);
4089 DestroyWindow(window);
4090 return;
4093 data_size = IDirect3DQuery9_GetDataSize(query);
4094 data = HeapAlloc(GetProcessHeap(), 0, data_size);
4096 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4097 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4098 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4099 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4101 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4102 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4103 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4104 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4105 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4106 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4108 *((DWORD *)data) = 0x12345678;
4109 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
4110 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4111 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4112 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4113 if (hr == D3D_OK)
4114 ok(!*(DWORD *)data, "Got unexpected query result %u.\n", *(DWORD *)data);
4116 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4117 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
4118 hr = IDirect3DDevice9_BeginScene(device);
4119 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
4120 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
4121 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
4122 hr = IDirect3DDevice9_EndScene(device);
4123 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
4125 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4126 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4127 for (i = 0; i < 500; ++i)
4129 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
4130 break;
4131 Sleep(10);
4133 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4135 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4136 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4137 hr = IDirect3DQuery9_GetData(query, data, data_size, D3DGETDATA_FLUSH);
4138 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4140 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
4141 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4142 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4143 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4144 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
4145 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4147 HeapFree(GetProcessHeap(), 0, data);
4148 IDirect3DQuery9_Release(query);
4149 refcount = IDirect3DDevice9_Release(device);
4150 ok(!refcount, "Device has %u references left.\n", refcount);
4151 IDirect3D9_Release(d3d9);
4152 DestroyWindow(window);
4155 static void test_get_set_vertex_shader(void)
4157 IDirect3DVertexShader9 *current_shader = NULL;
4158 IDirect3DVertexShader9 *shader = NULL;
4159 IDirect3DDevice9 *device;
4160 ULONG refcount, i;
4161 IDirect3D9 *d3d;
4162 D3DCAPS9 caps;
4163 HWND window;
4164 HRESULT hr;
4166 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4168 skip("Failed to create D3D object, skipping tests.\n");
4169 return;
4172 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4173 0, 0, 640, 480, 0, 0, 0, 0);
4174 if (!(device = create_device(d3d, window, window, TRUE)))
4176 skip("Failed to create a D3D device, skipping tests.\n");
4177 IDirect3D9_Release(d3d);
4178 DestroyWindow(window);
4179 return;
4182 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4183 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4184 if (!(caps.VertexShaderVersion & 0xffff))
4186 skip("No vertex shader support, skipping tests.\n");
4187 IDirect3DDevice9_Release(device);
4188 IDirect3D9_Release(d3d);
4189 DestroyWindow(window);
4190 return;
4193 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
4194 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4195 ok(!!shader, "Got unexpected shader %p.\n", shader);
4197 /* SetVertexShader() should not touch the shader's refcount. */
4198 i = get_refcount((IUnknown *)shader);
4199 hr = IDirect3DDevice9_SetVertexShader(device, shader);
4200 refcount = get_refcount((IUnknown *)shader);
4201 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
4202 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4204 /* GetVertexShader() should increase the shader's refcount by one. */
4205 i = refcount + 1;
4206 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
4207 refcount = get_refcount((IUnknown *)shader);
4208 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
4209 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4210 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4211 IDirect3DVertexShader9_Release(current_shader);
4213 IDirect3DVertexShader9_Release(shader);
4214 refcount = IDirect3DDevice9_Release(device);
4215 ok(!refcount, "Device has %u references left.\n", refcount);
4216 IDirect3D9_Release(d3d);
4217 DestroyWindow(window);
4220 static void test_vertex_shader_constant(void)
4222 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};
4223 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4224 IDirect3DDevice9 *device;
4225 IDirect3D9 *d3d;
4226 ULONG refcount;
4227 D3DCAPS9 caps;
4228 DWORD consts;
4229 HWND window;
4230 HRESULT hr;
4232 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4234 skip("Failed to create D3D object, skipping tests.\n");
4235 return;
4238 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4239 0, 0, 640, 480, 0, 0, 0, 0);
4240 if (!(device = create_device(d3d, window, window, TRUE)))
4242 skip("Failed to create a D3D device, skipping tests.\n");
4243 IDirect3D9_Release(d3d);
4244 DestroyWindow(window);
4245 return;
4248 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4249 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4250 if (!(caps.VertexShaderVersion & 0xffff))
4252 skip("No vertex shader support, skipping tests.\n");
4253 IDirect3DDevice9_Release(device);
4254 IDirect3D9_Release(d3d);
4255 DestroyWindow(window);
4256 return;
4258 consts = caps.MaxVertexShaderConst;
4260 /* A simple check that the stuff works at all. */
4261 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
4262 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4264 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
4265 * consts from MAX - 1. */
4266 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
4267 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4268 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
4269 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4270 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
4271 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4272 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
4273 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4275 /* Constant -1. */
4276 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
4277 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4279 refcount = IDirect3DDevice9_Release(device);
4280 ok(!refcount, "Device has %u references left.\n", refcount);
4281 IDirect3D9_Release(d3d);
4282 DestroyWindow(window);
4285 static void test_get_set_pixel_shader(void)
4287 IDirect3DPixelShader9 *current_shader = NULL;
4288 IDirect3DPixelShader9 *shader = NULL;
4289 IDirect3DDevice9 *device;
4290 ULONG refcount, i;
4291 IDirect3D9 *d3d;
4292 D3DCAPS9 caps;
4293 HWND window;
4294 HRESULT hr;
4296 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4298 skip("Failed to create D3D object, skipping tests.\n");
4299 return;
4302 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4303 0, 0, 640, 480, 0, 0, 0, 0);
4304 if (!(device = create_device(d3d, window, window, TRUE)))
4306 skip("Failed to create a D3D device, skipping tests.\n");
4307 IDirect3D9_Release(d3d);
4308 DestroyWindow(window);
4309 return;
4312 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4313 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4314 if (!(caps.PixelShaderVersion & 0xffff))
4316 skip("No pixel shader support, skipping tests.\n");
4317 IDirect3DDevice9_Release(device);
4318 IDirect3D9_Release(d3d);
4319 DestroyWindow(window);
4320 return;
4323 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
4324 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
4325 ok(!!shader, "Got unexpected shader %p.\n", shader);
4327 /* SetPixelShader() should not touch the shader's refcount. */
4328 i = get_refcount((IUnknown *)shader);
4329 hr = IDirect3DDevice9_SetPixelShader(device, shader);
4330 refcount = get_refcount((IUnknown *)shader);
4331 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
4332 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4334 /* GetPixelShader() should increase the shader's refcount by one. */
4335 i = refcount + 1;
4336 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
4337 refcount = get_refcount((IUnknown *)shader);
4338 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
4339 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
4340 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
4341 IDirect3DPixelShader9_Release(current_shader);
4343 IDirect3DPixelShader9_Release(shader);
4344 refcount = IDirect3DDevice9_Release(device);
4345 ok(!refcount, "Device has %u references left.\n", refcount);
4346 IDirect3D9_Release(d3d);
4347 DestroyWindow(window);
4350 static void test_pixel_shader_constant(void)
4352 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};
4353 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
4354 IDirect3DDevice9 *device;
4355 DWORD consts = 0;
4356 IDirect3D9 *d3d;
4357 ULONG refcount;
4358 D3DCAPS9 caps;
4359 HWND window;
4360 HRESULT hr;
4362 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4364 skip("Failed to create D3D object, skipping tests.\n");
4365 return;
4368 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4369 0, 0, 640, 480, 0, 0, 0, 0);
4370 if (!(device = create_device(d3d, window, window, TRUE)))
4372 skip("Failed to create a D3D device, skipping tests.\n");
4373 IDirect3D9_Release(d3d);
4374 DestroyWindow(window);
4375 return;
4378 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4379 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4380 if (!(caps.PixelShaderVersion & 0xffff))
4382 skip("No pixel shader support, skipping tests.\n");
4383 IDirect3DDevice9_Release(device);
4384 IDirect3D9_Release(d3d);
4385 DestroyWindow(window);
4386 return;
4389 /* A simple check that the stuff works at all. */
4390 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
4391 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4393 /* Is there really no max pixel shader constant value??? Test how far I can go. */
4394 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
4395 consts = consts - 1;
4396 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
4398 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
4399 * pointless given the way the constant limit was determined. */
4400 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
4401 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4403 /* Constant -1. */
4404 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
4405 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4407 refcount = IDirect3DDevice9_Release(device);
4408 ok(!refcount, "Device has %u references left.\n", refcount);
4409 IDirect3D9_Release(d3d);
4410 DestroyWindow(window);
4413 static void test_wrong_shader(void)
4415 static const DWORD vs_3_0[] =
4417 0xfffe0300, /* vs_3_0 */
4418 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
4419 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
4420 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
4421 0x0000ffff, /* end */
4424 #if 0
4425 float4 main(const float4 color : COLOR) : SV_TARGET
4427 float4 o;
4429 o = color;
4431 return o;
4433 #endif
4434 static const DWORD ps_4_0[] =
4436 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
4437 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
4438 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
4439 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
4440 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
4441 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
4442 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
4443 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
4444 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
4445 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
4446 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
4447 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4448 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
4449 0x00000000, 0x00000000, 0x00000000,
4452 IDirect3DVertexShader9 *vs = NULL;
4453 IDirect3DPixelShader9 *ps = NULL;
4454 IDirect3DDevice9 *device;
4455 IDirect3D9 * d3d;
4456 ULONG refcount;
4457 D3DCAPS9 caps;
4458 HWND window;
4459 HRESULT hr;
4461 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4463 skip("Failed to create D3D object, skipping tests.\n");
4464 return;
4467 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4468 0, 0, 640, 480, 0, 0, 0, 0);
4469 if (!(device = create_device(d3d, window, window, TRUE)))
4471 skip("Failed to create a D3D device, skipping tests.\n");
4472 IDirect3D9_Release(d3d);
4473 DestroyWindow(window);
4474 return;
4477 /* These should always fail, regardless of supported shader version. */
4478 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
4479 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4480 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
4481 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4482 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
4483 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4485 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4486 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4487 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
4489 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
4490 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4492 else
4493 skip("This GPU supports SM3, skipping unsupported shader test.\n");
4495 refcount = IDirect3DDevice9_Release(device);
4496 ok(!refcount, "Device has %u references left.\n", refcount);
4497 IDirect3D9_Release(d3d);
4498 DestroyWindow(window);
4501 /* Test the default texture stage state values */
4502 static void test_texture_stage_states(void)
4504 IDirect3DDevice9 *device;
4505 IDirect3D9 *d3d;
4506 unsigned int i;
4507 ULONG refcount;
4508 D3DCAPS9 caps;
4509 DWORD value;
4510 HWND window;
4511 HRESULT hr;
4513 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4515 skip("Failed to create D3D object, skipping tests.\n");
4516 return;
4519 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4520 0, 0, 640, 480, 0, 0, 0, 0);
4521 if (!(device = create_device(d3d, window, window, TRUE)))
4523 skip("Failed to create a D3D device, skipping tests.\n");
4524 IDirect3D9_Release(d3d);
4525 DestroyWindow(window);
4526 return;
4529 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4530 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4532 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
4534 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
4535 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4536 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
4537 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
4538 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
4539 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4540 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
4541 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
4542 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4543 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
4544 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
4545 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4546 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
4547 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
4548 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
4549 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4550 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
4551 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
4552 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4553 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
4554 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
4555 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4556 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
4557 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
4558 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4559 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
4560 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
4561 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4562 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
4563 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
4564 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4565 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
4566 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
4567 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4568 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
4569 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
4570 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4571 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
4572 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
4573 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4574 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
4575 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
4576 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4577 ok(value == D3DTTFF_DISABLE,
4578 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
4579 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
4580 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4581 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
4582 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
4583 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4584 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
4585 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
4586 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4587 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
4588 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
4589 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4590 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
4593 refcount = IDirect3DDevice9_Release(device);
4594 ok(!refcount, "Device has %u references left.\n", refcount);
4595 IDirect3D9_Release(d3d);
4596 DestroyWindow(window);
4599 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
4601 IDirect3DCubeTexture9 *texture;
4602 IDirect3D9 *d3d;
4603 HRESULT hr;
4605 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
4606 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
4607 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4608 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
4609 IDirect3D9_Release(d3d);
4610 if (FAILED(hr))
4612 skip("No cube mipmap generation support, skipping tests.\n");
4613 return;
4616 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4617 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4618 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4619 IDirect3DCubeTexture9_Release(texture);
4621 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4622 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4623 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4624 IDirect3DCubeTexture9_Release(texture);
4627 static void test_cube_texture_levels(IDirect3DDevice9 *device)
4629 IDirect3DCubeTexture9 *texture;
4630 IDirect3DSurface9 *surface;
4631 D3DSURFACE_DESC desc;
4632 DWORD levels;
4633 HRESULT hr;
4634 D3DCAPS9 caps;
4636 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4637 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4638 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
4639 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
4641 skip("Failed to create cube texture, skipping tests.\n");
4642 return;
4645 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
4646 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
4647 ok(levels == 7, "Got unexpected levels %u.\n", levels);
4648 else
4649 ok(levels == 1, "Got unexpected levels %u.\n", levels);
4651 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
4652 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4653 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
4654 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4655 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
4656 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4658 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
4659 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4660 IDirect3DSurface9_Release(surface);
4661 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
4662 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4663 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
4664 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4666 IDirect3DCubeTexture9_Release(texture);
4669 static void test_cube_textures(void)
4671 IDirect3DCubeTexture9 *texture;
4672 IDirect3DDevice9 *device;
4673 IDirect3D9 *d3d;
4674 ULONG refcount;
4675 D3DCAPS9 caps;
4676 HWND window;
4677 HRESULT hr;
4679 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4681 skip("Failed to create D3D object, skipping tests.\n");
4682 return;
4685 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4686 0, 0, 640, 480, 0, 0, 0, 0);
4687 if (!(device = create_device(d3d, window, window, TRUE)))
4689 skip("Failed to create a D3D device, skipping tests.\n");
4690 IDirect3D9_Release(d3d);
4691 DestroyWindow(window);
4692 return;
4695 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4696 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4698 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
4700 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4701 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
4702 IDirect3DCubeTexture9_Release(texture);
4703 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4704 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
4705 IDirect3DCubeTexture9_Release(texture);
4706 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4707 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
4708 IDirect3DCubeTexture9_Release(texture);
4710 else
4712 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4713 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
4714 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4715 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
4716 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
4717 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
4719 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
4720 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
4721 IDirect3DCubeTexture9_Release(texture);
4723 test_cube_texture_mipmap_gen(device);
4724 test_cube_texture_levels(device);
4726 refcount = IDirect3DDevice9_Release(device);
4727 ok(!refcount, "Device has %u references left.\n", refcount);
4728 IDirect3D9_Release(d3d);
4729 DestroyWindow(window);
4732 static void test_mipmap_gen(void)
4734 D3DTEXTUREFILTERTYPE filter_type;
4735 IDirect3DTexture9 *texture;
4736 IDirect3DSurface9 *surface;
4737 IDirect3DDevice9 *device;
4738 D3DSURFACE_DESC desc;
4739 D3DLOCKED_RECT lr;
4740 IDirect3D9 *d3d;
4741 ULONG refcount;
4742 unsigned int i;
4743 DWORD levels;
4744 HWND window;
4745 HRESULT hr;
4747 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4749 skip("Failed to create D3D object, skipping tests.\n");
4750 return;
4753 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4754 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
4756 skip("No mipmap generation support, skipping tests.\n");
4757 IDirect3D9_Release(d3d);
4758 return;
4761 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4762 0, 0, 640, 480, 0, 0, 0, 0);
4763 if (!(device = create_device(d3d, window, window, TRUE)))
4765 skip("Failed to create a D3D device, skipping tests.\n");
4766 IDirect3D9_Release(d3d);
4767 DestroyWindow(window);
4768 return;
4771 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
4772 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4773 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4774 IDirect3DTexture9_Release(texture);
4776 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
4777 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
4778 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4780 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4781 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
4782 "Got unexpected filter_type %#x.\n", filter_type);
4783 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
4784 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4785 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
4786 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4787 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
4788 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
4789 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
4790 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4792 levels = IDirect3DTexture9_GetLevelCount(texture);
4793 ok(levels == 1, "Got unexpected levels %u.\n", levels);
4795 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
4797 surface = NULL;
4798 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
4799 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4800 if (surface)
4801 IDirect3DSurface9_Release(surface);
4803 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
4804 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4806 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
4807 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
4808 if (SUCCEEDED(hr))
4810 hr = IDirect3DTexture9_UnlockRect(texture, i);
4811 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
4814 IDirect3DTexture9_Release(texture);
4816 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
4817 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4818 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4819 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
4820 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4821 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
4823 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
4824 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4825 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4826 levels = IDirect3DTexture9_GetLevelCount(texture);
4827 ok(levels == 1, "Got unexpected levels %u.\n", levels);
4828 IDirect3DTexture9_Release(texture);
4830 refcount = IDirect3DDevice9_Release(device);
4831 ok(!refcount, "Device has %u references left.\n", refcount);
4832 IDirect3D9_Release(d3d);
4833 DestroyWindow(window);
4836 static void test_filter(void)
4838 static const struct
4840 DWORD magfilter, minfilter, mipfilter;
4841 BOOL has_texture;
4842 HRESULT result;
4844 tests[] =
4846 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4847 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4848 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4849 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
4850 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
4852 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4853 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4854 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
4855 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
4857 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4858 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
4859 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
4860 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
4861 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
4863 IDirect3DTexture9 *texture;
4864 IDirect3DDevice9 *device;
4865 IDirect3D9 *d3d;
4866 unsigned int i;
4867 ULONG refcount;
4868 DWORD passes;
4869 HWND window;
4870 HRESULT hr;
4872 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4874 skip("Failed to create D3D object, skipping tests.\n");
4875 return;
4878 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4879 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4881 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
4882 IDirect3D9_Release(d3d);
4883 return;
4886 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4887 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
4889 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
4890 IDirect3D9_Release(d3d);
4891 return;
4894 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4895 0, 0, 640, 480, 0, 0, 0, 0);
4896 if (!(device = create_device(d3d, window, window, TRUE)))
4898 skip("Failed to create a D3D device, skipping tests.\n");
4899 IDirect3D9_Release(d3d);
4900 DestroyWindow(window);
4901 return;
4904 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
4905 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
4906 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4908 /* Needed for ValidateDevice(). */
4909 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4910 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
4912 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
4914 if (tests[i].has_texture)
4916 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
4917 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4919 else
4921 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4922 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4925 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
4926 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4927 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
4928 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4929 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
4930 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
4932 passes = 0xdeadbeef;
4933 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
4934 ok(hr == tests[i].result,
4935 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
4936 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
4937 tests[i].mipfilter, tests[i].has_texture);
4938 if (SUCCEEDED(hr))
4939 ok(!!passes, "Got unexpected passes %#x.\n", passes);
4940 else
4941 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
4944 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4945 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4946 IDirect3DTexture9_Release(texture);
4948 refcount = IDirect3DDevice9_Release(device);
4949 ok(!refcount, "Device has %u references left.\n", refcount);
4950 IDirect3D9_Release(d3d);
4951 DestroyWindow(window);
4954 static void test_get_texture(void)
4956 IDirect3DBaseTexture9 *texture;
4957 IDirect3DDevice9 *device;
4958 IDirect3D9 *d3d;
4959 ULONG refcount;
4960 HWND window;
4961 HRESULT hr;
4963 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
4965 skip("Failed to create D3D object, skipping tests.\n");
4966 return;
4969 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4970 0, 0, 640, 480, 0, 0, 0, 0);
4971 if (!(device = create_device(d3d, window, window, TRUE)))
4973 skip("Failed to create a D3D device, skipping tests.\n");
4974 IDirect3D9_Release(d3d);
4975 DestroyWindow(window);
4976 return;
4979 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
4980 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4981 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4982 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
4983 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4984 ok(!texture, "Got unexpected texture %p.\n", texture);
4986 refcount = IDirect3DDevice9_Release(device);
4987 ok(!refcount, "Device has %u references left.\n", refcount);
4988 IDirect3D9_Release(d3d);
4989 DestroyWindow(window);
4992 static void test_lod(void)
4994 IDirect3DTexture9 *texture;
4995 IDirect3DDevice9 *device;
4996 IDirect3D9 *d3d;
4997 ULONG refcount;
4998 HWND window;
4999 HRESULT hr;
5000 DWORD ret;
5002 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5004 skip("Failed to create D3D object, skipping tests.\n");
5005 return;
5008 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5009 0, 0, 640, 480, 0, 0, 0, 0);
5010 if (!(device = create_device(d3d, window, window, TRUE)))
5012 skip("Failed to create a D3D device, skipping tests.\n");
5013 IDirect3D9_Release(d3d);
5014 DestroyWindow(window);
5015 return;
5018 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
5019 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5020 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5022 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
5023 * return a HRESULT, so it can't return a normal error. Instead, the call
5024 * is simply ignored. */
5025 ret = IDirect3DTexture9_SetLOD(texture, 0);
5026 ok(!ret, "Got unexpected ret %u.\n", ret);
5027 ret = IDirect3DTexture9_SetLOD(texture, 1);
5028 ok(!ret, "Got unexpected ret %u.\n", ret);
5029 ret = IDirect3DTexture9_SetLOD(texture, 2);
5030 ok(!ret, "Got unexpected ret %u.\n", ret);
5031 ret = IDirect3DTexture9_GetLOD(texture);
5032 ok(!ret, "Got unexpected ret %u.\n", ret);
5034 IDirect3DTexture9_Release(texture);
5035 refcount = IDirect3DDevice9_Release(device);
5036 ok(!refcount, "Device has %u references left.\n", refcount);
5037 IDirect3D9_Release(d3d);
5038 DestroyWindow(window);
5041 static void test_surface_get_container(void)
5043 IDirect3DTexture9 *texture = NULL;
5044 IDirect3DSurface9 *surface = NULL;
5045 IDirect3DDevice9 *device;
5046 IUnknown *container;
5047 IDirect3D9 *d3d;
5048 ULONG refcount;
5049 HWND window;
5050 HRESULT hr;
5052 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5054 skip("Failed to create D3D object, skipping tests.\n");
5055 return;
5058 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5059 0, 0, 640, 480, 0, 0, 0, 0);
5060 if (!(device = create_device(d3d, window, window, TRUE)))
5062 skip("Failed to create a D3D device, skipping tests.\n");
5063 IDirect3D9_Release(d3d);
5064 DestroyWindow(window);
5065 return;
5068 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
5069 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5070 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5071 ok(!!texture, "Got unexpected texture %p.\n", texture);
5073 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5074 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5075 ok(!!surface, "Got unexpected surface %p.\n", surface);
5077 /* These should work... */
5078 container = NULL;
5079 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
5080 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5081 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5082 IUnknown_Release(container);
5084 container = NULL;
5085 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
5086 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5087 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5088 IUnknown_Release(container);
5090 container = NULL;
5091 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
5092 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5093 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5094 IUnknown_Release(container);
5096 container = NULL;
5097 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
5098 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
5099 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5100 IUnknown_Release(container);
5102 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5103 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
5104 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5105 ok(!container, "Got unexpected container %p.\n", container);
5107 IDirect3DSurface9_Release(surface);
5108 IDirect3DTexture9_Release(texture);
5109 refcount = IDirect3DDevice9_Release(device);
5110 ok(!refcount, "Device has %u references left.\n", refcount);
5111 IDirect3D9_Release(d3d);
5112 DestroyWindow(window);
5115 static void test_surface_alignment(void)
5117 IDirect3DSurface9 *surface;
5118 IDirect3DDevice9 *device;
5119 D3DLOCKED_RECT lr;
5120 unsigned int i, j;
5121 IDirect3D9 *d3d;
5122 ULONG refcount;
5123 HWND window;
5124 HRESULT hr;
5126 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5128 skip("Failed to create D3D object, skipping tests.\n");
5129 return;
5132 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5133 0, 0, 640, 480, 0, 0, 0, 0);
5134 if (!(device = create_device(d3d, window, window, TRUE)))
5136 skip("Failed to create a D3D device, skipping tests.\n");
5137 IDirect3D9_Release(d3d);
5138 DestroyWindow(window);
5139 return;
5142 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
5143 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
5144 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
5145 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5147 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5148 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5149 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
5150 /* Some applications also depend on the exact pitch, rather than just the
5151 * alignment. */
5152 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
5153 hr = IDirect3DSurface9_UnlockRect(surface);
5154 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5155 IDirect3DSurface9_Release(surface);
5157 for (i = 0; i < 5; ++i)
5159 IDirect3DTexture9 *texture;
5160 unsigned int level_count;
5161 D3DSURFACE_DESC desc;
5162 int expected_pitch;
5164 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
5165 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
5166 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5167 if (FAILED(hr))
5169 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
5170 continue;
5173 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
5174 for (j = 0; j < level_count; ++j)
5176 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
5177 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
5178 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
5179 hr = IDirect3DTexture9_UnlockRect(texture, j);
5180 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
5182 expected_pitch = ((desc.Width + 3) >> 2) << 3;
5183 if (i > 0)
5184 expected_pitch <<= 1;
5185 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
5186 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
5188 IDirect3DTexture9_Release(texture);
5191 refcount = IDirect3DDevice9_Release(device);
5192 ok(!refcount, "Device has %u references left.\n", refcount);
5193 IDirect3D9_Release(d3d);
5194 DestroyWindow(window);
5197 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
5198 * different from regular formats. This test verifies we return the correct
5199 * memory offsets. */
5200 static void test_lockrect_offset(void)
5202 static const struct
5204 D3DFORMAT format;
5205 const char *name;
5206 unsigned int block_width;
5207 unsigned int block_height;
5208 unsigned int block_size;
5210 dxt_formats[] =
5212 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
5213 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
5214 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
5215 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
5216 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
5217 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
5219 unsigned int expected_offset, offset, i;
5220 const RECT rect = {60, 60, 68, 68};
5221 IDirect3DSurface9 *surface;
5222 D3DLOCKED_RECT locked_rect;
5223 IDirect3DDevice9 *device;
5224 int expected_pitch;
5225 IDirect3D9 *d3d;
5226 ULONG refcount;
5227 HWND window;
5228 BYTE *base;
5229 HRESULT hr;
5231 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5233 skip("Failed to create D3D object, skipping tests.\n");
5234 return;
5237 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5238 0, 0, 640, 480, 0, 0, 0, 0);
5239 if (!(device = create_device(d3d, window, window, TRUE)))
5241 skip("Failed to create a D3D device, skipping tests.\n");
5242 IDirect3D9_Release(d3d);
5243 DestroyWindow(window);
5244 return;
5247 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
5249 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5250 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
5252 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
5253 continue;
5256 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5257 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
5258 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5260 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5261 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5263 base = locked_rect.pBits;
5264 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
5265 * dxt_formats[i].block_size;
5266 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
5267 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
5269 hr = IDirect3DSurface9_UnlockRect(surface);
5270 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5272 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
5273 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5275 offset = (BYTE *)locked_rect.pBits - base;
5276 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
5277 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
5278 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
5279 offset, dxt_formats[i].name, expected_offset);
5281 hr = IDirect3DSurface9_UnlockRect(surface);
5282 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5284 IDirect3DSurface9_Release(surface);
5287 refcount = IDirect3DDevice9_Release(device);
5288 ok(!refcount, "Device has %u references left.\n", refcount);
5289 IDirect3D9_Release(d3d);
5290 DestroyWindow(window);
5293 static void test_lockrect_invalid(void)
5295 static const struct
5297 RECT rect;
5298 HRESULT win7_result;
5300 test_data[] =
5302 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
5303 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
5304 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
5305 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
5306 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
5307 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
5308 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
5309 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
5310 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
5311 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
5312 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
5313 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
5314 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
5316 static const RECT test_rect_2 = {0, 0, 8, 8};
5317 IDirect3DSurface9 *surface = NULL;
5318 D3DLOCKED_RECT locked_rect;
5319 IDirect3DDevice9 *device;
5320 IDirect3D9 *d3d;
5321 unsigned int i;
5322 ULONG refcount;
5323 HWND window;
5324 BYTE *base;
5325 HRESULT hr;
5327 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5329 skip("Failed to create D3D object, skipping tests.\n");
5330 return;
5333 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5334 0, 0, 640, 480, 0, 0, 0, 0);
5335 if (!(device = create_device(d3d, window, window, TRUE)))
5337 skip("Failed to create a D3D device, skipping tests.\n");
5338 IDirect3D9_Release(d3d);
5339 DestroyWindow(window);
5340 return;
5343 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
5344 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5345 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5346 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5347 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5348 base = locked_rect.pBits;
5349 hr = IDirect3DSurface9_UnlockRect(surface);
5350 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5352 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5354 unsigned int offset, expected_offset;
5355 const RECT *rect = &test_data[i].rect;
5357 locked_rect.pBits = (BYTE *)0xdeadbeef;
5358 locked_rect.Pitch = 0xdeadbeef;
5360 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
5361 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
5362 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
5363 * one broken. */
5364 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
5365 "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
5366 rect->left, rect->top, rect->right, rect->bottom, hr);
5367 if (FAILED(hr))
5368 continue;
5370 offset = (BYTE *)locked_rect.pBits - base;
5371 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5372 ok(offset == expected_offset,
5373 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
5374 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
5376 hr = IDirect3DSurface9_UnlockRect(surface);
5377 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5380 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5381 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
5382 locked_rect.pBits = (BYTE *)0xdeadbeef;
5383 locked_rect.Pitch = 1;
5384 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5385 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5386 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p\n",
5387 locked_rect.pBits);
5388 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d\n", locked_rect.Pitch);
5389 hr = IDirect3DSurface9_UnlockRect(surface);
5390 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5392 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
5393 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5394 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
5395 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
5396 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5397 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
5398 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
5399 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
5400 hr, test_rect_2.left, test_rect_2.top, test_rect_2.right, test_rect_2.bottom);
5401 hr = IDirect3DSurface9_UnlockRect(surface);
5402 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5404 IDirect3DSurface9_Release(surface);
5405 refcount = IDirect3DDevice9_Release(device);
5406 ok(!refcount, "Device has %u references left.\n", refcount);
5407 IDirect3D9_Release(d3d);
5408 DestroyWindow(window);
5411 static void test_private_data(void)
5413 ULONG refcount, expected_refcount;
5414 IDirect3DTexture9 *texture;
5415 IDirect3DSurface9 *surface, *surface2;
5416 IDirect3DDevice9 *device;
5417 IDirect3D9 *d3d;
5418 IUnknown *ptr;
5419 HWND window;
5420 HRESULT hr;
5421 DWORD size;
5422 DWORD data[4] = {1, 2, 3, 4};
5424 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5426 skip("Failed to create D3D object, skipping tests.\n");
5427 return;
5430 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5431 0, 0, 640, 480, 0, 0, 0, 0);
5432 if (!(device = create_device(d3d, window, window, TRUE)))
5434 skip("Failed to create a D3D device, skipping tests.\n");
5435 IDirect3D9_Release(d3d);
5436 DestroyWindow(window);
5437 return;
5440 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
5441 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5442 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5444 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5445 device, 0, D3DSPD_IUNKNOWN);
5446 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5447 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5448 device, 5, D3DSPD_IUNKNOWN);
5449 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5450 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5451 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
5452 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5454 refcount = get_refcount((IUnknown *)device);
5455 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9 /* Abuse this tag */,
5456 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5457 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5458 expected_refcount = refcount + 1;
5459 refcount = get_refcount((IUnknown *)device);
5460 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5461 hr = IDirect3DSurface9_FreePrivateData(surface, &IID_IDirect3DSurface9);
5462 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5463 expected_refcount = refcount - 1;
5464 refcount = get_refcount((IUnknown *)device);
5465 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5467 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5468 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5469 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5470 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5471 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5472 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5473 refcount = get_refcount((IUnknown *)device);
5474 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5476 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DSurface9,
5477 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5478 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5479 size = sizeof(ptr);
5480 hr = IDirect3DSurface9_GetPrivateData(surface, &IID_IDirect3DSurface9, &ptr, &size);
5481 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5482 expected_refcount = refcount + 2;
5483 refcount = get_refcount((IUnknown *)device);
5484 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5485 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
5486 IUnknown_Release(ptr);
5488 /* Destroying the surface frees the held reference. */
5489 IDirect3DSurface9_Release(surface);
5490 expected_refcount = refcount - 3;
5491 refcount = get_refcount((IUnknown *)device);
5492 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5494 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
5495 &texture, NULL);
5496 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5497 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5498 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
5499 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
5500 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
5502 hr = IDirect3DTexture9_SetPrivateData(texture, &IID_IDirect3DVertexBuffer9, data, sizeof(data), 0);
5503 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5505 memset(data, 0, sizeof(data));
5506 size = sizeof(data);
5507 hr = IDirect3DSurface9_GetPrivateData(surface, &IID_IDirect3DVertexBuffer9, data, &size);
5508 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5509 hr = IDirect3DTexture9_GetPrivateData(texture, &IID_IDirect3DVertexBuffer9, data, &size);
5510 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
5511 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
5512 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
5514 hr = IDirect3DTexture9_FreePrivateData(texture, &IID_IDirect3DVertexBuffer9);
5515 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5517 hr = IDirect3DSurface9_SetPrivateData(surface, &IID_IDirect3DVertexBuffer9, data, sizeof(data), 0);
5518 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5519 hr = IDirect3DSurface9_GetPrivateData(surface2, &IID_IDirect3DVertexBuffer9, data, &size);
5520 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5521 hr = IDirect3DSurface9_FreePrivateData(surface, &IID_IDirect3DVertexBuffer9);
5522 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5524 IDirect3DSurface9_Release(surface2);
5525 IDirect3DSurface9_Release(surface);
5526 IDirect3DTexture9_Release(texture);
5528 refcount = IDirect3DDevice9_Release(device);
5529 ok(!refcount, "Device has %u references left.\n", refcount);
5530 IDirect3D9_Release(d3d);
5531 DestroyWindow(window);
5534 static void test_getdc(void)
5536 static const struct
5538 const char *name;
5539 D3DFORMAT format;
5540 BOOL getdc_supported;
5542 testdata[] =
5544 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, TRUE },
5545 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, TRUE },
5546 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, TRUE },
5547 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, TRUE },
5548 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, TRUE },
5549 {"D3DFMT_R8G8B8", D3DFMT_R8G8B8, TRUE },
5550 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, FALSE}, /* Untested, card on windows didn't support it. */
5551 {"D3DFMT_V8U8", D3DFMT_V8U8, FALSE},
5552 {"D3DFMT_Q8W8V8U8", D3DFMT_Q8W8V8U8, FALSE},
5553 {"D3DFMT_A8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
5554 {"D3DFMT_X8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
5555 {"D3DFMT_R3G3B2", D3DFMT_R3G3B2, FALSE},
5556 {"D3DFMT_P8", D3DFMT_P8, FALSE},
5557 {"D3DFMT_L8", D3DFMT_L8, FALSE},
5558 {"D3DFMT_A8L8", D3DFMT_A8L8, FALSE},
5559 {"D3DFMT_DXT1", D3DFMT_DXT1, FALSE},
5560 {"D3DFMT_DXT2", D3DFMT_DXT2, FALSE},
5561 {"D3DFMT_DXT3", D3DFMT_DXT3, FALSE},
5562 {"D3DFMT_DXT4", D3DFMT_DXT4, FALSE},
5563 {"D3DFMT_DXT5", D3DFMT_DXT5, FALSE},
5565 IDirect3DTexture9 *texture;
5566 IDirect3DSurface9 *surface;
5567 IDirect3DDevice9 *device;
5568 IDirect3D9 *d3d;
5569 unsigned int i;
5570 ULONG refcount;
5571 HWND window;
5572 HRESULT hr;
5573 HDC dc;
5575 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5577 skip("Failed to create D3D object, skipping tests.\n");
5578 return;
5581 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5582 0, 0, 640, 480, 0, 0, 0, 0);
5583 if (!(device = create_device(d3d, window, window, TRUE)))
5585 skip("Failed to create a D3D device, skipping tests.\n");
5586 IDirect3D9_Release(d3d);
5587 DestroyWindow(window);
5588 return;
5591 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
5593 texture = NULL;
5594 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5595 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
5596 if (FAILED(hr))
5598 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
5599 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
5600 if (FAILED(hr))
5602 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
5603 continue;
5605 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5606 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5609 dc = (void *)0x1234;
5610 hr = IDirect3DSurface9_GetDC(surface, &dc);
5611 if (testdata[i].getdc_supported)
5612 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5613 else
5614 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
5616 if (SUCCEEDED(hr))
5618 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
5619 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
5621 else
5623 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
5626 IDirect3DSurface9_Release(surface);
5627 if (texture)
5628 IDirect3DTexture9_Release(texture);
5631 refcount = IDirect3DDevice9_Release(device);
5632 ok(!refcount, "Device has %u references left.\n", refcount);
5633 IDirect3D9_Release(d3d);
5634 DestroyWindow(window);
5637 static void test_surface_dimensions(void)
5639 IDirect3DSurface9 *surface;
5640 IDirect3DDevice9 *device;
5641 IDirect3D9 *d3d;
5642 ULONG refcount;
5643 HWND window;
5644 HRESULT hr;
5646 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5648 skip("Failed to create D3D object, skipping tests.\n");
5649 return;
5652 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5653 0, 0, 640, 480, 0, 0, 0, 0);
5654 if (!(device = create_device(d3d, window, window, TRUE)))
5656 skip("Failed to create a D3D device, skipping tests.\n");
5657 IDirect3D9_Release(d3d);
5658 DestroyWindow(window);
5659 return;
5662 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
5663 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5664 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5665 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
5666 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
5667 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5669 refcount = IDirect3DDevice9_Release(device);
5670 ok(!refcount, "Device has %u references left.\n", refcount);
5671 IDirect3D9_Release(d3d);
5672 DestroyWindow(window);
5675 static void test_surface_format_null(void)
5677 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
5678 IDirect3DTexture9 *texture;
5679 IDirect3DSurface9 *surface;
5680 IDirect3DSurface9 *rt, *ds;
5681 D3DLOCKED_RECT locked_rect;
5682 IDirect3DDevice9 *device;
5683 D3DSURFACE_DESC desc;
5684 IDirect3D9 *d3d;
5685 ULONG refcount;
5686 HWND window;
5687 HRESULT hr;
5689 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5691 skip("Failed to create D3D object, skipping tests.\n");
5692 return;
5695 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5696 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
5697 if (hr != D3D_OK)
5699 skip("No D3DFMT_NULL support, skipping test.\n");
5700 IDirect3D9_Release(d3d);
5701 return;
5704 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5705 0, 0, 640, 480, 0, 0, 0, 0);
5706 if (!(device = create_device(d3d, window, window, TRUE)))
5708 skip("Failed to create a D3D device, skipping tests.\n");
5709 IDirect3D9_Release(d3d);
5710 DestroyWindow(window);
5711 return;
5714 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5715 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
5716 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
5718 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5719 D3DFMT_NULL, D3DFMT_D24S8);
5720 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
5722 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
5723 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5724 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5726 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
5727 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
5729 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
5730 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
5732 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
5733 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
5735 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
5736 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5738 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
5739 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5741 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
5742 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
5744 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5745 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5747 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
5748 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
5750 IDirect3DSurface9_Release(rt);
5751 IDirect3DSurface9_Release(ds);
5753 hr = IDirect3DSurface9_GetDesc(surface, &desc);
5754 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5755 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
5756 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
5758 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
5759 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5760 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
5761 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
5763 hr = IDirect3DSurface9_UnlockRect(surface);
5764 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5766 IDirect3DSurface9_Release(surface);
5768 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
5769 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
5770 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5771 IDirect3DTexture9_Release(texture);
5773 refcount = IDirect3DDevice9_Release(device);
5774 ok(!refcount, "Device has %u references left.\n", refcount);
5775 IDirect3D9_Release(d3d);
5776 DestroyWindow(window);
5779 static void test_surface_double_unlock(void)
5781 static const D3DPOOL pools[] =
5783 D3DPOOL_DEFAULT,
5784 D3DPOOL_SCRATCH,
5785 D3DPOOL_SYSTEMMEM,
5787 IDirect3DSurface9 *surface;
5788 IDirect3DDevice9 *device;
5789 D3DLOCKED_RECT lr;
5790 IDirect3D9 *d3d;
5791 unsigned int i;
5792 ULONG refcount;
5793 HWND window;
5794 HRESULT hr;
5796 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5798 skip("Failed to create D3D object, skipping tests.\n");
5799 return;
5802 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5803 0, 0, 640, 480, 0, 0, 0, 0);
5804 if (!(device = create_device(d3d, window, window, TRUE)))
5806 skip("Failed to create a D3D device, skipping tests.\n");
5807 IDirect3D9_Release(d3d);
5808 DestroyWindow(window);
5809 return;
5812 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
5814 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
5815 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
5816 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
5818 hr = IDirect3DSurface9_UnlockRect(surface);
5819 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5820 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
5821 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
5822 hr = IDirect3DSurface9_UnlockRect(surface);
5823 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
5824 hr = IDirect3DSurface9_UnlockRect(surface);
5825 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5827 IDirect3DSurface9_Release(surface);
5830 refcount = IDirect3DDevice9_Release(device);
5831 ok(!refcount, "Device has %u references left.\n", refcount);
5832 IDirect3D9_Release(d3d);
5833 DestroyWindow(window);
5836 static void test_surface_blocks(void)
5838 static const struct
5840 D3DFORMAT fmt;
5841 const char *name;
5842 unsigned int block_width;
5843 unsigned int block_height;
5844 BOOL broken;
5845 BOOL create_size_checked, core_fmt;
5847 formats[] =
5849 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
5850 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
5851 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
5852 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
5853 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
5854 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
5855 * which doesn't match the format spec. On newer Nvidia cards
5856 * it has the correct 4x4 block size */
5857 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
5858 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
5859 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
5861 static const struct
5863 D3DPOOL pool;
5864 const char *name;
5865 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
5866 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
5867 BOOL success;
5869 pools[] =
5871 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
5872 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
5873 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
5874 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
5876 static struct
5878 D3DRESOURCETYPE rtype;
5879 const char *type_name;
5880 D3DPOOL pool;
5881 const char *pool_name;
5882 BOOL need_driver_support, need_runtime_support;
5884 create_tests[] =
5886 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
5887 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
5888 /* Managed offscreen plain surfaces are not supported */
5889 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5891 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
5892 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
5893 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
5894 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5896 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
5897 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
5898 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
5899 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5901 IDirect3DTexture9 *texture;
5902 IDirect3DCubeTexture9 *cube_texture;
5903 IDirect3DSurface9 *surface;
5904 D3DLOCKED_RECT locked_rect;
5905 IDirect3DDevice9 *device;
5906 unsigned int i, j, w, h;
5907 BOOL surface_only;
5908 IDirect3D9 *d3d;
5909 ULONG refcount;
5910 HWND window;
5911 HRESULT hr;
5912 RECT rect;
5913 BOOL tex_pow2, cube_pow2;
5914 D3DCAPS9 caps;
5916 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
5918 skip("Failed to create D3D object, skipping tests.\n");
5919 return;
5922 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5923 0, 0, 640, 480, 0, 0, 0, 0);
5924 if (!(device = create_device(d3d, window, window, TRUE)))
5926 skip("Failed to create a D3D device, skipping tests.\n");
5927 IDirect3D9_Release(d3d);
5928 DestroyWindow(window);
5929 return;
5932 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5933 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5934 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
5935 if (tex_pow2)
5936 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
5937 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
5939 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
5941 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
5943 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5944 0, D3DRTYPE_TEXTURE, formats[i].fmt);
5945 tex_support = SUCCEEDED(hr);
5946 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5947 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
5948 cube_support = SUCCEEDED(hr);
5949 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5950 0, D3DRTYPE_SURFACE, formats[i].fmt);
5951 surface_support = SUCCEEDED(hr);
5953 /* Scratch pool in general allows texture creation even if the driver does
5954 * not support the format. If the format is an extension format that is not
5955 * known to the runtime, like ATI2N, some driver support is required for
5956 * this to work.
5958 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
5959 * about ATI2N. I cannot check this because all my Vista+ machines support
5960 * ATI2N in hardware, but none of my WinXP machines do. */
5961 format_known = tex_support || cube_support || surface_support;
5963 for (w = 1; w <= 8; w++)
5965 for (h = 1; h <= 8; h++)
5967 BOOL block_aligned = TRUE;
5968 BOOL size_is_pow2;
5970 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5971 block_aligned = FALSE;
5973 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
5975 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
5977 BOOL support, pow2;
5978 HRESULT expect_hr;
5979 BOOL may_succeed = FALSE;
5980 IUnknown **check_null;
5982 if (!formats[i].core_fmt)
5984 /* AMD warns against creating ATI2N textures smaller than
5985 * the block size because the runtime cannot calculate the
5986 * correct texture size. Generalize this for all extension
5987 * formats. */
5988 if (w < formats[i].block_width || h < formats[i].block_height)
5989 continue;
5992 texture = (IDirect3DTexture9 *)0xdeadbeef;
5993 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
5994 surface = (IDirect3DSurface9 *)0xdeadbeef;
5996 switch (create_tests[j].rtype)
5998 case D3DRTYPE_TEXTURE:
5999 check_null = (IUnknown **)&texture;
6000 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
6001 formats[i].fmt, create_tests[j].pool, &texture, NULL);
6002 support = tex_support;
6003 pow2 = tex_pow2;
6004 break;
6006 case D3DRTYPE_CUBETEXTURE:
6007 if (w != h)
6008 continue;
6009 check_null = (IUnknown **)&cube_texture;
6010 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
6011 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
6012 support = cube_support;
6013 pow2 = cube_pow2;
6014 break;
6016 case D3DRTYPE_SURFACE:
6017 check_null = (IUnknown **)&surface;
6018 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
6019 formats[i].fmt, create_tests[j].pool, &surface, NULL);
6020 support = surface_support;
6021 pow2 = FALSE;
6022 break;
6024 default:
6025 check_null = NULL;
6026 pow2 = FALSE;
6027 support = FALSE;
6028 break;
6031 if (create_tests[j].need_driver_support && !support)
6032 expect_hr = D3DERR_INVALIDCALL;
6033 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
6034 expect_hr = D3DERR_INVALIDCALL;
6035 else if (formats[i].create_size_checked && !block_aligned)
6036 expect_hr = D3DERR_INVALIDCALL;
6037 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6038 expect_hr = D3DERR_INVALIDCALL;
6039 else
6040 expect_hr = D3D_OK;
6042 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6043 * does not support it. Accept scratch creation of extension formats on
6044 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6045 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6046 * support it. */
6047 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
6048 may_succeed = TRUE;
6050 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6051 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
6052 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
6053 if (FAILED(hr))
6054 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
6055 else
6056 IUnknown_Release(*check_null);
6061 surface_only = FALSE;
6062 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6063 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
6064 dynamic_tex_support = SUCCEEDED(hr);
6065 if (!dynamic_tex_support)
6067 if (!surface_support)
6069 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
6070 continue;
6072 surface_only = TRUE;
6075 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
6077 switch (pools[j].pool)
6079 case D3DPOOL_SYSTEMMEM:
6080 case D3DPOOL_MANAGED:
6081 if (surface_only)
6082 continue;
6083 /* Fall through */
6084 case D3DPOOL_DEFAULT:
6085 if (surface_only)
6087 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6088 formats[i].fmt, pools[j].pool, &surface, NULL);
6089 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6091 else
6093 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
6094 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
6095 formats[i].fmt, pools[j].pool, &texture, NULL);
6096 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6097 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6098 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
6099 IDirect3DTexture9_Release(texture);
6101 break;
6103 case D3DPOOL_SCRATCH:
6104 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6105 formats[i].fmt, pools[j].pool, &surface, NULL);
6106 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6107 break;
6109 default:
6110 break;
6113 if (formats[i].block_width > 1)
6115 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
6116 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6117 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6118 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6119 SUCCEEDED(hr) ? "succeeded" : "failed",
6120 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6121 if (SUCCEEDED(hr))
6123 hr = IDirect3DSurface9_UnlockRect(surface);
6124 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6127 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
6128 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6129 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6130 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6131 SUCCEEDED(hr) ? "succeeded" : "failed",
6132 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6133 if (SUCCEEDED(hr))
6135 hr = IDirect3DSurface9_UnlockRect(surface);
6136 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6140 if (formats[i].block_height > 1)
6142 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
6143 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6144 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6145 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6146 SUCCEEDED(hr) ? "succeeded" : "failed",
6147 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6148 if (SUCCEEDED(hr))
6150 hr = IDirect3DSurface9_UnlockRect(surface);
6151 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6154 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
6155 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6156 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6157 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6158 SUCCEEDED(hr) ? "succeeded" : "failed",
6159 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6160 if (SUCCEEDED(hr))
6162 hr = IDirect3DSurface9_UnlockRect(surface);
6163 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6167 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
6168 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6169 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
6170 hr = IDirect3DSurface9_UnlockRect(surface);
6171 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6173 IDirect3DSurface9_Release(surface);
6176 if (!dynamic_tex_support)
6178 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
6179 continue;
6182 if (formats[i].block_width == 1 && formats[i].block_height == 1)
6183 continue;
6184 if (!formats[i].core_fmt)
6185 continue;
6187 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
6188 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
6189 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
6191 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
6192 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6193 hr = IDirect3DTexture9_UnlockRect(texture, 1);
6194 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6196 rect.left = 0;
6197 rect.top = 0;
6198 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
6199 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
6200 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
6201 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6202 hr = IDirect3DTexture9_UnlockRect(texture, 1);
6203 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
6205 rect.right = formats[i].block_width;
6206 rect.bottom = formats[i].block_height;
6207 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
6208 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6209 if (SUCCEEDED(hr))
6210 IDirect3DTexture9_UnlockRect(texture, 1);
6212 IDirect3DTexture9_Release(texture);
6215 refcount = IDirect3DDevice9_Release(device);
6216 ok(!refcount, "Device has %u references left.\n", refcount);
6217 IDirect3D9_Release(d3d);
6218 DestroyWindow(window);
6221 static void test_set_palette(void)
6223 IDirect3DDevice9 *device;
6224 IDirect3D9 *d3d9;
6225 UINT refcount;
6226 HWND window;
6227 HRESULT hr;
6228 PALETTEENTRY pal[256];
6229 unsigned int i;
6230 D3DCAPS9 caps;
6232 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6234 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6235 return;
6238 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6239 0, 0, 640, 480, 0, 0, 0, 0);
6240 if (!(device = create_device(d3d9, window, window, TRUE)))
6242 skip("Failed to create a D3D device, skipping tests.\n");
6243 DestroyWindow(window);
6244 return;
6247 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6249 pal[i].peRed = i;
6250 pal[i].peGreen = i;
6251 pal[i].peBlue = i;
6252 pal[i].peFlags = 0xff;
6254 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6255 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6257 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6258 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6259 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
6261 pal[i].peRed = i;
6262 pal[i].peGreen = i;
6263 pal[i].peBlue = i;
6264 pal[i].peFlags = i;
6266 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
6268 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6269 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
6271 else
6273 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
6274 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
6277 refcount = IDirect3DDevice9_Release(device);
6278 ok(!refcount, "Device has %u references left.\n", refcount);
6279 IDirect3D9_Release(d3d9);
6280 DestroyWindow(window);
6283 static void test_swvp_buffer(void)
6285 IDirect3DDevice9 *device;
6286 IDirect3D9 *d3d9;
6287 UINT refcount;
6288 HWND window;
6289 HRESULT hr;
6290 unsigned int i;
6291 IDirect3DVertexBuffer9 *buffer;
6292 static const unsigned int bufsize = 1024;
6293 D3DVERTEXBUFFER_DESC desc;
6294 D3DPRESENT_PARAMETERS present_parameters = {0};
6295 struct
6297 float x, y, z;
6298 } *ptr, *ptr2;
6300 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6302 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6303 return;
6306 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6307 0, 0, 640, 480, 0, 0, 0, 0);
6309 present_parameters.Windowed = TRUE;
6310 present_parameters.hDeviceWindow = window;
6311 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
6312 present_parameters.BackBufferWidth = screen_width;
6313 present_parameters.BackBufferHeight = screen_height;
6314 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
6315 present_parameters.EnableAutoDepthStencil = FALSE;
6316 if (FAILED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
6317 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device)))
6319 skip("Failed to create a D3D device, skipping tests.\n");
6320 DestroyWindow(window);
6321 IDirect3D9_Release(d3d9);
6322 return;
6325 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
6326 D3DPOOL_DEFAULT, &buffer, NULL);
6327 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6328 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
6329 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6330 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
6331 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
6332 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
6334 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
6335 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6336 for (i = 0; i < bufsize; i++)
6338 ptr[i].x = i * 1.0f;
6339 ptr[i].y = i * 2.0f;
6340 ptr[i].z = i * 3.0f;
6342 hr = IDirect3DVertexBuffer9_Unlock(buffer);
6343 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6345 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6346 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6347 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
6348 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6349 hr = IDirect3DDevice9_BeginScene(device);
6350 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6351 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6352 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6353 hr = IDirect3DDevice9_EndScene(device);
6354 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6356 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
6357 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6358 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
6359 for (i = 0; i < bufsize; i++)
6361 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6363 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
6364 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6365 break;
6368 hr = IDirect3DVertexBuffer9_Unlock(buffer);
6369 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6371 IDirect3DVertexBuffer9_Release(buffer);
6372 refcount = IDirect3DDevice9_Release(device);
6373 ok(!refcount, "Device has %u references left.\n", refcount);
6374 IDirect3D9_Release(d3d9);
6375 DestroyWindow(window);
6378 static void test_npot_textures(void)
6380 IDirect3DDevice9 *device = NULL;
6381 IDirect3D9 *d3d9;
6382 ULONG refcount;
6383 HWND window = NULL;
6384 HRESULT hr;
6385 D3DCAPS9 caps;
6386 IDirect3DTexture9 *texture;
6387 IDirect3DCubeTexture9 *cube_texture;
6388 IDirect3DVolumeTexture9 *volume_texture;
6389 struct
6391 D3DPOOL pool;
6392 const char *pool_name;
6393 HRESULT hr;
6395 pools[] =
6397 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
6398 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
6399 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
6400 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
6402 unsigned int i, levels;
6403 BOOL tex_pow2, cube_pow2, vol_pow2;
6405 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6407 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6408 return;
6411 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6412 0, 0, 640, 480, 0, 0, 0, 0);
6413 if (!(device = create_device(d3d9, window, window, TRUE)))
6415 skip("Failed to create a D3D device, skipping tests.\n");
6416 goto done;
6419 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6420 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6421 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
6422 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6423 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6424 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
6425 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
6427 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
6429 for (levels = 0; levels <= 2; levels++)
6431 HRESULT expected;
6433 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
6434 pools[i].pool, &texture, NULL);
6435 if (!tex_pow2)
6437 expected = D3D_OK;
6439 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
6441 if (levels == 1)
6442 expected = D3D_OK;
6443 else
6444 expected = pools[i].hr;
6446 else
6448 expected = pools[i].hr;
6450 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
6451 pools[i].pool_name, levels, hr, expected);
6453 if (SUCCEEDED(hr))
6454 IDirect3DTexture9_Release(texture);
6457 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
6458 &cube_texture, NULL);
6459 if (tex_pow2)
6461 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6462 pools[i].pool_name, hr, pools[i].hr);
6464 else
6466 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6467 pools[i].pool_name, hr, D3D_OK);
6470 if (SUCCEEDED(hr))
6471 IDirect3DCubeTexture9_Release(cube_texture);
6473 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
6474 &volume_texture, NULL);
6475 if (tex_pow2)
6477 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6478 pools[i].pool_name, hr, pools[i].hr);
6480 else
6482 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6483 pools[i].pool_name, hr, D3D_OK);
6486 if (SUCCEEDED(hr))
6487 IDirect3DVolumeTexture9_Release(volume_texture);
6490 done:
6491 if (device)
6493 refcount = IDirect3DDevice9_Release(device);
6494 ok(!refcount, "Device has %u references left.\n", refcount);
6496 IDirect3D9_Release(d3d9);
6497 DestroyWindow(window);
6501 static void test_vidmem_accounting(void)
6503 IDirect3DDevice9 *device;
6504 IDirect3D9 *d3d9;
6505 ULONG refcount;
6506 HWND window;
6507 HRESULT hr = D3D_OK;
6508 IDirect3DTexture9 *textures[20];
6509 unsigned int i;
6510 UINT vidmem_start, vidmem_end, diff;
6512 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6514 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6515 return;
6518 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6519 0, 0, 640, 480, 0, 0, 0, 0);
6520 if (!(device = create_device(d3d9, window, window, TRUE)))
6522 skip("Failed to create a D3D device, skipping tests.\n");
6523 IDirect3D9_Release(d3d9);
6524 DestroyWindow(window);
6525 return;
6528 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
6529 memset(textures, 0, sizeof(textures));
6530 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
6532 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
6533 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
6534 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
6535 * E_FAIL is returned on address space or system memory exhaustion */
6536 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
6537 "Failed to create texture, hr %#x.\n", hr);
6539 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
6541 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
6542 diff = vidmem_start - vidmem_end;
6543 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
6544 2 * i, diff / 1024 / 1024);
6546 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
6548 if (textures[i])
6549 IDirect3DTexture9_Release(textures[i]);
6552 refcount = IDirect3DDevice9_Release(device);
6553 ok(!refcount, "Device has %u references left.\n", refcount);
6554 IDirect3D9_Release(d3d9);
6555 DestroyWindow(window);
6558 static void test_volume_locking(void)
6560 IDirect3DDevice9 *device;
6561 IDirect3D9 *d3d9;
6562 HWND window;
6563 HRESULT hr;
6564 IDirect3DVolumeTexture9 *texture;
6565 unsigned int i;
6566 D3DLOCKED_BOX locked_box;
6567 ULONG refcount;
6568 D3DCAPS9 caps;
6569 static const struct
6571 D3DPOOL pool;
6572 DWORD usage;
6573 HRESULT create_hr, lock_hr;
6575 tests[] =
6577 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
6578 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6579 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
6580 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6581 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
6582 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6583 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
6584 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6587 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6589 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6590 return;
6593 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6594 0, 0, 640, 480, 0, 0, 0, 0);
6595 if (!(device = create_device(d3d9, window, window, TRUE)))
6597 skip("Failed to create a D3D device, skipping tests.\n");
6598 IDirect3D9_Release(d3d9);
6599 DestroyWindow(window);
6600 return;
6603 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6604 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6605 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6607 skip("Volume textures not supported, skipping test.\n");
6608 goto out;
6611 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6613 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
6614 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
6615 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
6616 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
6617 if (FAILED(hr))
6618 continue;
6620 locked_box.pBits = (void *)0xdeadbeef;
6621 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
6622 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
6623 if (SUCCEEDED(hr))
6625 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
6626 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6628 else
6630 ok (locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
6632 IDirect3DVolumeTexture9_Release(texture);
6635 out:
6636 refcount = IDirect3DDevice9_Release(device);
6637 ok(!refcount, "Device has %u references left.\n", refcount);
6638 IDirect3D9_Release(d3d9);
6639 DestroyWindow(window);
6642 static void test_update_volumetexture(void)
6644 IDirect3DDevice9 *device;
6645 IDirect3D9 *d3d9;
6646 HWND window;
6647 HRESULT hr;
6648 IDirect3DVolumeTexture9 *src, *dst;
6649 unsigned int i;
6650 D3DLOCKED_BOX locked_box;
6651 ULONG refcount;
6652 D3DCAPS9 caps;
6653 static const struct
6655 D3DPOOL src_pool, dst_pool;
6656 HRESULT hr;
6658 tests[] =
6660 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6661 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6662 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
6663 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6665 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6666 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6667 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6668 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6670 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6671 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6672 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6673 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6675 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6676 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6677 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6678 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6680 static const struct
6682 UINT src_size, dst_size;
6683 UINT src_lvl, dst_lvl;
6684 D3DFORMAT src_fmt, dst_fmt;
6686 tests2[] =
6688 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6689 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6690 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6691 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6692 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6693 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
6694 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
6695 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
6698 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6700 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6701 return;
6704 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6705 0, 0, 640, 480, 0, 0, 0, 0);
6706 if (!(device = create_device(d3d9, window, window, TRUE)))
6708 skip("Failed to create a D3D device, skipping tests.\n");
6709 IDirect3D9_Release(d3d9);
6710 DestroyWindow(window);
6711 return;
6714 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6715 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6716 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6718 skip("Volume textures not supported, skipping test.\n");
6719 goto out;
6722 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6724 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6725 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6727 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
6728 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
6729 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6730 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
6731 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
6732 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6734 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
6735 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6736 *((DWORD *)locked_box.pBits) = 0x11223344;
6737 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
6738 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6740 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
6741 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
6742 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
6744 if (SUCCEEDED(hr))
6746 DWORD content = *((DWORD *)locked_box.pBits);
6747 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
6748 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6749 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
6750 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
6751 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6753 IDirect3DVolumeTexture9_Release(src);
6754 IDirect3DVolumeTexture9_Release(dst);
6757 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
6759 skip("Mipmapped volume maps not supported.\n");
6760 goto out;
6763 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
6765 hr = IDirect3DDevice9_CreateVolumeTexture(device,
6766 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
6767 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
6768 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6769 hr = IDirect3DDevice9_CreateVolumeTexture(device,
6770 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
6771 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
6772 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6774 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
6775 if (FAILED(hr))
6776 todo_wine ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
6777 else
6778 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
6780 IDirect3DVolumeTexture9_Release(src);
6781 IDirect3DVolumeTexture9_Release(dst);
6784 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
6785 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
6786 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
6787 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
6788 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
6790 * I'm not adding tests for this behavior until an application needs it. */
6792 out:
6793 refcount = IDirect3DDevice9_Release(device);
6794 ok(!refcount, "Device has %u references left.\n", refcount);
6795 IDirect3D9_Release(d3d9);
6796 DestroyWindow(window);
6799 static void test_create_rt_ds_fail(void)
6801 IDirect3DDevice9 *device;
6802 HWND window;
6803 HRESULT hr;
6804 ULONG refcount;
6805 IDirect3D9 *d3d9;
6806 IDirect3DSurface9 *surface;
6808 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6810 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6811 return;
6814 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6815 0, 0, 640, 480, 0, 0, 0, 0);
6816 if (!(device = create_device(d3d9, window, window, TRUE)))
6818 skip("Failed to create a D3D device, skipping tests.\n");
6819 IDirect3D9_Release(d3d9);
6820 DestroyWindow(window);
6821 return;
6824 /* Output pointer == NULL segfaults on Windows. */
6826 surface = (IDirect3DSurface9 *)0xdeadbeef;
6827 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
6828 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
6829 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
6830 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6831 if (SUCCEEDED(hr))
6832 IDirect3DSurface9_Release(surface);
6834 surface = (IDirect3DSurface9 *)0xdeadbeef;
6835 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
6836 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
6837 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
6838 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6839 if (SUCCEEDED(hr))
6840 IDirect3DSurface9_Release(surface);
6842 refcount = IDirect3DDevice9_Release(device);
6843 ok(!refcount, "Device has %u references left.\n", refcount);
6844 IDirect3D9_Release(d3d9);
6845 DestroyWindow(window);
6848 static void test_volume_blocks(void)
6850 IDirect3DDevice9 *device;
6851 IDirect3D9 *d3d9;
6852 UINT refcount;
6853 HWND window;
6854 HRESULT hr;
6855 D3DCAPS9 caps;
6856 IDirect3DVolumeTexture9 *texture;
6857 unsigned int w, h, d, i, j;
6858 static const struct
6860 D3DFORMAT fmt;
6861 const char *name;
6862 unsigned int block_width;
6863 unsigned int block_height;
6864 unsigned int block_depth;
6865 unsigned int block_size;
6866 BOOL broken;
6867 BOOL create_size_checked, core_fmt;
6869 formats[] =
6871 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
6872 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
6873 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, FALSE, TRUE, TRUE },
6874 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6875 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6876 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6877 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6878 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, FALSE, TRUE, TRUE },
6879 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
6880 * which doesn't match the format spec. On newer Nvidia cards
6881 * it has the correct 4x4 block size */
6882 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, TRUE, FALSE, FALSE},
6883 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, TRUE, FALSE, TRUE },
6884 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, TRUE, FALSE, TRUE },
6886 static const struct
6888 D3DPOOL pool;
6889 const char *name;
6890 BOOL need_driver_support, need_runtime_support;
6892 create_tests[] =
6894 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6895 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6896 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
6897 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
6899 static const struct
6901 unsigned int x, y, z, x2, y2, z2;
6903 offset_tests[] =
6905 {0, 0, 0, 8, 8, 8},
6906 {0, 0, 3, 8, 8, 8},
6907 {0, 4, 0, 8, 8, 8},
6908 {0, 4, 3, 8, 8, 8},
6909 {4, 0, 0, 8, 8, 8},
6910 {4, 0, 3, 8, 8, 8},
6911 {4, 4, 0, 8, 8, 8},
6912 {4, 4, 3, 8, 8, 8},
6914 D3DBOX box;
6915 D3DLOCKED_BOX locked_box;
6916 BYTE *base;
6917 INT expected_row_pitch, expected_slice_pitch;
6918 BOOL support, support_2d;
6919 BOOL pow2;
6920 unsigned int offset, expected_offset;
6922 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
6924 skip("Failed to create IDirect3D9 object, skipping tests.\n");
6925 return;
6928 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
6929 0, 0, 640, 480, 0, 0, 0, 0);
6930 if (!(device = create_device(d3d9, window, window, TRUE)))
6932 skip("Failed to create a D3D device, skipping tests.\n");
6933 IDirect3D9_Release(d3d9);
6934 DestroyWindow(window);
6935 return;
6937 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6938 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6939 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6941 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
6943 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6944 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
6945 support = SUCCEEDED(hr);
6946 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6947 0, D3DRTYPE_TEXTURE, formats[i].fmt);
6948 support_2d = SUCCEEDED(hr);
6950 /* Test creation restrictions */
6951 for (w = 1; w <= 8; w++)
6953 for (h = 1; h <= 8; h++)
6955 for (d = 1; d <= 8; d++)
6957 HRESULT expect_hr;
6958 BOOL size_is_pow2;
6959 BOOL block_aligned = TRUE;
6961 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6962 block_aligned = FALSE;
6964 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
6966 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
6968 BOOL may_succeed = FALSE;
6969 BOOL todo = FALSE;
6971 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
6972 expect_hr = D3DERR_INVALIDCALL;
6973 else if (formats[i].create_size_checked && !block_aligned)
6974 expect_hr = D3DERR_INVALIDCALL;
6975 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6976 expect_hr = D3DERR_INVALIDCALL;
6977 else if (create_tests[j].need_driver_support && !support)
6979 todo = support_2d;
6980 expect_hr = D3DERR_INVALIDCALL;
6982 else
6983 expect_hr = D3D_OK;
6985 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
6986 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
6987 formats[i].fmt, create_tests[j].pool, &texture, NULL);
6989 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6990 * does not support it. Accept scratch creation of extension formats on
6991 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6992 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6993 * support it. */
6994 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
6995 may_succeed = TRUE;
6997 if (todo)
6999 todo_wine ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
7000 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
7001 hr, formats[i].name, create_tests[j].name, w, h, d);
7003 else
7005 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
7006 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
7007 hr, formats[i].name, create_tests[j].name, w, h, d);
7010 if (FAILED(hr))
7011 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
7012 else
7013 IDirect3DVolumeTexture9_Release(texture);
7019 if (!support && !formats[i].core_fmt)
7020 continue;
7022 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
7023 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
7024 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7026 /* Test lockrect offset */
7027 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
7029 unsigned int bytes_per_pixel;
7030 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
7032 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7033 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7035 base = locked_box.pBits;
7036 if (formats[i].broken)
7038 expected_row_pitch = bytes_per_pixel * 24;
7040 else
7042 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
7043 * formats[i].block_size;
7045 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
7046 locked_box.RowPitch, formats[i].name, expected_row_pitch);
7048 if (formats[i].broken)
7050 expected_slice_pitch = expected_row_pitch * 8;
7052 else
7054 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
7055 * expected_row_pitch;
7057 ok(locked_box.SlicePitch == expected_slice_pitch,
7058 "Got unexpected slice pitch %d for format %s, expected %d.\n",
7059 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
7061 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7062 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
7064 box.Left = offset_tests[j].x;
7065 box.Top = offset_tests[j].y;
7066 box.Front = offset_tests[j].z;
7067 box.Right = offset_tests[j].x2;
7068 box.Bottom = offset_tests[j].y2;
7069 box.Back = offset_tests[j].z2;
7070 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7071 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
7073 offset = (BYTE *)locked_box.pBits - base;
7074 if (formats[i].broken)
7076 expected_offset = box.Front * expected_slice_pitch
7077 + box.Top * expected_row_pitch
7078 + box.Left * bytes_per_pixel;
7080 else
7082 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
7083 + (box.Top / formats[i].block_height) * expected_row_pitch
7084 + (box.Left / formats[i].block_width) * formats[i].block_size;
7086 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
7087 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
7089 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7090 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7093 /* Test partial block locks */
7094 box.Front = 0;
7095 box.Back = 1;
7096 if (formats[i].block_width > 1)
7098 box.Left = formats[i].block_width >> 1;
7099 box.Top = 0;
7100 box.Right = formats[i].block_width;
7101 box.Bottom = formats[i].block_height;
7102 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7103 ok(FAILED(hr) || broken(formats[i].broken),
7104 "Partial block lock succeeded, expected failure, format %s.\n",
7105 formats[i].name);
7106 if (SUCCEEDED(hr))
7108 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7109 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7112 box.Left = 0;
7113 box.Top = 0;
7114 box.Right = formats[i].block_width >> 1;
7115 box.Bottom = formats[i].block_height;
7116 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7117 ok(FAILED(hr) || broken(formats[i].broken),
7118 "Partial block lock succeeded, expected failure, format %s.\n",
7119 formats[i].name);
7120 if (SUCCEEDED(hr))
7122 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7123 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7127 if (formats[i].block_height > 1)
7129 box.Left = 0;
7130 box.Top = formats[i].block_height >> 1;
7131 box.Right = formats[i].block_width;
7132 box.Bottom = formats[i].block_height;
7133 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7134 ok(FAILED(hr) || broken(formats[i].broken),
7135 "Partial block lock succeeded, expected failure, format %s.\n",
7136 formats[i].name);
7137 if (SUCCEEDED(hr))
7139 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7140 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7143 box.Left = 0;
7144 box.Top = 0;
7145 box.Right = formats[i].block_width;
7146 box.Bottom = formats[i].block_height >> 1;
7147 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7148 ok(FAILED(hr) || broken(formats[i].broken),
7149 "Partial block lock succeeded, expected failure, format %s.\n",
7150 formats[i].name);
7151 if (SUCCEEDED(hr))
7153 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7154 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7158 /* Test full block lock */
7159 box.Left = 0;
7160 box.Top = 0;
7161 box.Right = formats[i].block_width;
7162 box.Bottom = formats[i].block_height;
7163 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
7164 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7165 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7166 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7168 IDirect3DVolumeTexture9_Release(texture);
7170 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
7171 * does not allocate surfaces smaller than the blocksize properly. */
7172 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
7174 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
7175 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
7177 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
7178 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
7179 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7180 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7182 box.Left = box.Top = box.Front = 0;
7183 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
7184 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
7185 box.Back = 1;
7186 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
7187 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
7188 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7189 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7191 box.Right = formats[i].block_width;
7192 box.Bottom = formats[i].block_height;
7193 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
7194 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7195 if (SUCCEEDED(hr))
7196 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
7198 IDirect3DVolumeTexture9_Release(texture);
7202 refcount = IDirect3DDevice9_Release(device);
7203 ok(!refcount, "Device has %u references left.\n", refcount);
7204 IDirect3D9_Release(d3d9);
7205 DestroyWindow(window);
7208 static void test_lockbox_invalid(void)
7210 static const struct
7212 D3DBOX box;
7213 HRESULT result;
7215 test_data[] =
7217 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
7218 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
7219 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
7220 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
7221 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
7222 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
7223 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
7224 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
7225 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
7226 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
7227 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
7228 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
7229 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
7230 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
7232 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
7233 IDirect3DVolumeTexture9 *texture = NULL;
7234 D3DLOCKED_BOX locked_box;
7235 IDirect3DDevice9 *device;
7236 IDirect3D9 *d3d;
7237 unsigned int i;
7238 ULONG refcount;
7239 HWND window;
7240 BYTE *base;
7241 HRESULT hr;
7243 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
7245 skip("Failed to create D3D object, skipping tests.\n");
7246 return;
7249 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7250 0, 0, 640, 480, 0, 0, 0, 0);
7251 if (!(device = create_device(d3d, window, window, TRUE)))
7253 skip("Failed to create a D3D device, skipping tests.\n");
7254 IDirect3D9_Release(d3d);
7255 DestroyWindow(window);
7256 return;
7259 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
7260 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
7261 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
7262 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7263 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7264 base = locked_box.pBits;
7265 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7266 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7268 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
7270 unsigned int offset, expected_offset;
7271 const D3DBOX *box = &test_data[i].box;
7273 locked_box.pBits = (BYTE *)0xdeadbeef;
7274 locked_box.RowPitch = 0xdeadbeef;
7275 locked_box.SlicePitch = 0xdeadbeef;
7277 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
7278 /* Unlike surfaces, volumes properly check the box even in Windows XP */
7279 ok(hr == test_data[i].result,
7280 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
7281 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
7282 test_data[i].result);
7283 if (FAILED(hr))
7284 continue;
7286 offset = (BYTE *)locked_box.pBits - base;
7287 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
7288 ok(offset == expected_offset,
7289 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
7290 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
7292 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7293 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7296 /* locked_box = NULL throws an exception on Windows */
7297 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7298 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
7299 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
7300 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7301 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7302 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7303 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7304 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7306 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7307 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7308 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7309 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7310 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7311 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7312 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7313 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7314 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
7315 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7316 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
7317 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
7318 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
7319 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7321 IDirect3DVolumeTexture9_Release(texture);
7322 refcount = IDirect3DDevice9_Release(device);
7323 ok(!refcount, "Device has %u references left.\n", refcount);
7324 IDirect3D9_Release(d3d);
7325 DestroyWindow(window);
7328 static void test_shared_handle(void)
7330 IDirect3DDevice9 *device;
7331 IDirect3D9 *d3d;
7332 ULONG refcount;
7333 HWND window;
7334 HRESULT hr;
7335 /* Native d3d9ex refuses to create a shared texture if the texture pointer
7336 * is not initialized to NULL. Make sure this doesn't cause issues here. */
7337 IDirect3DTexture9 *texture = NULL;
7338 IDirect3DSurface9 *surface = NULL;
7339 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
7340 IDirect3DIndexBuffer9 *index_buffer = NULL;
7341 HANDLE handle = NULL;
7342 void *mem;
7343 D3DCAPS9 caps;
7345 if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
7347 skip("Failed to create D3D object, skipping tests.\n");
7348 return;
7351 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7352 0, 0, 640, 480, 0, 0, 0, 0);
7353 if (!(device = create_device(d3d, window, window, TRUE)))
7355 skip("Failed to create a D3D device, skipping tests.\n");
7356 IDirect3D9_Release(d3d);
7357 DestroyWindow(window);
7358 return;
7361 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7362 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7363 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
7365 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
7366 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
7367 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7368 D3DPOOL_DEFAULT, &texture, &handle);
7369 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7370 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7371 D3DPOOL_SYSTEMMEM, &texture, &mem);
7372 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7374 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7375 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
7376 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7377 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7378 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
7379 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7381 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
7382 &vertex_buffer, &handle);
7383 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7384 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
7385 &vertex_buffer, &mem);
7386 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
7388 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
7389 &index_buffer, &handle);
7390 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7391 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
7392 &index_buffer, &mem);
7393 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7395 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7397 IDirect3DCubeTexture9 *cube_texture = NULL;
7398 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
7399 D3DPOOL_DEFAULT, &cube_texture, &handle);
7400 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7401 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
7402 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
7403 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7406 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
7408 IDirect3DVolumeTexture9 *volume_texture = NULL;
7409 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
7410 D3DPOOL_DEFAULT, &volume_texture, &handle);
7411 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7412 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
7413 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
7414 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7417 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
7418 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
7419 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7421 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
7422 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
7423 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
7425 HeapFree(GetProcessHeap(), 0, mem);
7426 refcount = IDirect3DDevice9_Release(device);
7427 ok(!refcount, "Device has %u references left.\n", refcount);
7428 IDirect3D9_Release(d3d);
7429 DestroyWindow(window);
7432 static void test_pixel_format(void)
7434 HWND hwnd, hwnd2 = NULL;
7435 HDC hdc, hdc2 = NULL;
7436 HMODULE gl = NULL;
7437 int format, test_format;
7438 PIXELFORMATDESCRIPTOR pfd;
7439 IDirect3D9 *d3d9 = NULL;
7440 IDirect3DDevice9 *device = NULL;
7441 HRESULT hr;
7442 static const float point[3] = {0.0, 0.0, 0.0};
7444 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7445 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7446 if (!hwnd)
7448 skip("Failed to create window\n");
7449 return;
7452 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7453 100, 100, 160, 160, NULL, NULL, NULL, NULL);
7455 hdc = GetDC(hwnd);
7456 if (!hdc)
7458 skip("Failed to get DC\n");
7459 goto cleanup;
7462 if (hwnd2)
7463 hdc2 = GetDC(hwnd2);
7465 gl = LoadLibraryA("opengl32.dll");
7466 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7468 format = GetPixelFormat(hdc);
7469 ok(format == 0, "new window has pixel format %d\n", format);
7471 ZeroMemory(&pfd, sizeof(pfd));
7472 pfd.nSize = sizeof(pfd);
7473 pfd.nVersion = 1;
7474 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7475 pfd.iPixelType = PFD_TYPE_RGBA;
7476 pfd.iLayerType = PFD_MAIN_PLANE;
7477 format = ChoosePixelFormat(hdc, &pfd);
7478 if (format <= 0)
7480 skip("no pixel format available\n");
7481 goto cleanup;
7484 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7486 skip("failed to set pixel format\n");
7487 goto cleanup;
7490 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7492 skip("failed to set pixel format on second window\n");
7493 if (hdc2)
7495 ReleaseDC(hwnd2, hdc2);
7496 hdc2 = NULL;
7500 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7501 if (!d3d9)
7503 skip("Failed to create IDirect3D9 object\n");
7504 goto cleanup;
7507 test_format = GetPixelFormat(hdc);
7508 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7510 if (!(device = create_device(d3d9, hwnd, hwnd, TRUE)))
7512 skip("Failed to create device\n");
7513 goto cleanup;
7516 test_format = GetPixelFormat(hdc);
7517 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7519 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7520 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
7522 test_format = GetPixelFormat(hdc);
7523 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7525 hr = IDirect3DDevice9_BeginScene(device);
7526 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
7528 test_format = GetPixelFormat(hdc);
7529 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7531 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
7532 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7534 test_format = GetPixelFormat(hdc);
7535 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7537 hr = IDirect3DDevice9_EndScene(device);
7538 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
7540 test_format = GetPixelFormat(hdc);
7541 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7543 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7544 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
7546 test_format = GetPixelFormat(hdc);
7547 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7549 if (hdc2)
7551 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
7552 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
7554 test_format = GetPixelFormat(hdc);
7555 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7557 test_format = GetPixelFormat(hdc2);
7558 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7561 cleanup:
7562 if (device)
7564 UINT refcount = IDirect3DDevice9_Release(device);
7565 ok(!refcount, "Device has %u references left.\n", refcount);
7567 if (d3d9) IDirect3D9_Release(d3d9);
7568 if (gl) FreeLibrary(gl);
7569 if (hdc) ReleaseDC(hwnd, hdc);
7570 if (hdc2) ReleaseDC(hwnd2, hdc2);
7571 if (hwnd) DestroyWindow(hwnd);
7572 if (hwnd2) DestroyWindow(hwnd2);
7575 START_TEST(device)
7577 WNDCLASSA wc = {0};
7578 IDirect3D9 *d3d9;
7580 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
7582 skip("could not create D3D9 object\n");
7583 return;
7585 IDirect3D9_Release(d3d9);
7587 wc.lpfnWndProc = DefWindowProcA;
7588 wc.lpszClassName = "d3d9_test_wc";
7589 RegisterClassA(&wc);
7591 screen_width = GetSystemMetrics(SM_CXSCREEN);
7592 screen_height = GetSystemMetrics(SM_CYSCREEN);
7594 test_fpu_setup();
7595 test_multi_device();
7596 test_display_formats();
7597 test_display_modes();
7598 test_swapchain();
7599 test_refcount();
7600 test_mipmap_levels();
7601 test_checkdevicemultisampletype();
7602 test_cursor();
7603 test_cursor_pos();
7604 test_reset_fullscreen();
7605 test_reset();
7606 test_scene();
7607 test_limits();
7608 test_depthstenciltest();
7609 test_get_rt();
7610 test_draw_indexed();
7611 test_null_stream();
7612 test_lights();
7613 test_set_stream_source();
7614 test_scissor_size();
7615 test_wndproc();
7616 test_wndproc_windowed();
7617 test_window_style();
7618 test_mode_change();
7619 test_device_window_reset();
7620 test_reset_resources();
7621 test_set_rt_vp_scissor();
7622 test_volume_get_container();
7623 test_volume_resource();
7624 test_vb_lock_flags();
7625 test_vertex_buffer_alignment();
7626 test_query_support();
7627 test_occlusion_query_states();
7628 test_get_set_vertex_shader();
7629 test_vertex_shader_constant();
7630 test_get_set_pixel_shader();
7631 test_pixel_shader_constant();
7632 test_wrong_shader();
7633 test_texture_stage_states();
7634 test_cube_textures();
7635 test_mipmap_gen();
7636 test_filter();
7637 test_get_texture();
7638 test_lod();
7639 test_surface_get_container();
7640 test_surface_alignment();
7641 test_lockrect_offset();
7642 test_lockrect_invalid();
7643 test_private_data();
7644 test_getdc();
7645 test_surface_dimensions();
7646 test_surface_format_null();
7647 test_surface_double_unlock();
7648 test_surface_blocks();
7649 test_set_palette();
7650 test_swvp_buffer();
7651 test_npot_textures();
7652 test_vidmem_accounting();
7653 test_volume_locking();
7654 test_update_volumetexture();
7655 test_create_rt_ds_fail();
7656 test_volume_blocks();
7657 test_lockbox_invalid();
7658 test_shared_handle();
7659 test_pixel_format();
7661 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));