d3d8: Fix Reset() with system memory buffers.
[wine.git] / dlls / d3d8 / tests / device.c
blobadfeca8eaf2634cfee391791c4cf303210f594a1
1 /*
2 * Copyright (C) 2006 Vitaliy Margolen
3 * Copyright (C) 2006 Chris Robinson
4 * Copyright (C) 2006 Louis Lenders
5 * Copyright 2006-2007 Henri Verbeet
6 * Copyright 2006-2007, 2011-2013 Stefan Dösinger for CodeWeavers
7 * Copyright 2013 Henri Verbeet for CodeWeavers
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 WINVER 0x0602 /* for CURSOR_SUPPRESSED */
25 #include <stdlib.h>
26 #define COBJMACROS
27 #include <initguid.h>
28 #include <d3d8.h>
29 #include "wine/test.h"
31 struct vec3
33 float x, y, z;
36 #define CREATE_DEVICE_FULLSCREEN 0x01
37 #define CREATE_DEVICE_FPU_PRESERVE 0x02
38 #define CREATE_DEVICE_SWVP_ONLY 0x04
39 #define CREATE_DEVICE_LOCKABLE_BACKBUFFER 0x08
41 struct device_desc
43 HWND device_window;
44 unsigned int width;
45 unsigned int height;
46 DWORD flags;
49 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
50 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
52 static DEVMODEW registry_mode;
54 static HRESULT (WINAPI *ValidateVertexShader)(DWORD *, DWORD *, DWORD *, int, DWORD *);
55 static HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, int, DWORD *);
57 static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
59 static const DWORD simple_vs[] = {0xFFFE0101, /* vs_1_1 */
60 0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0 */
61 0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1 */
62 0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2 */
63 0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3 */
64 0x0000FFFF}; /* END */
65 static const DWORD simple_ps[] = {0xFFFF0101, /* ps_1_1 */
66 0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
67 0x00000042, 0xB00F0000, /* tex t0 */
68 0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000, /* dp3 r0, c1, c0 */
69 0x00000005, 0x800F0000, 0x90E40000, 0x80E40000, /* mul r0, v0, r0 */
70 0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000, /* mul r0, t0, r0 */
71 0x0000FFFF}; /* END */
73 static int get_refcount(IUnknown *object)
75 IUnknown_AddRef( object );
76 return IUnknown_Release( object );
79 static HWND create_window(void)
81 RECT r = {0, 0, 640, 480};
83 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
85 return CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
86 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
89 /* try to make sure pending X events have been processed before continuing */
90 static void flush_events(void)
92 MSG msg;
93 int diff = 200;
94 int min_timeout = 100;
95 DWORD time = GetTickCount() + diff;
97 while (diff > 0)
99 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
100 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
101 diff = time - GetTickCount();
105 static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND focus_window, const struct device_desc *desc)
107 D3DPRESENT_PARAMETERS present_parameters = {0};
108 IDirect3DDevice8 *device;
109 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
111 present_parameters.BackBufferWidth = 640;
112 present_parameters.BackBufferHeight = 480;
113 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
114 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
115 present_parameters.hDeviceWindow = focus_window;
116 present_parameters.Windowed = TRUE;
117 present_parameters.EnableAutoDepthStencil = TRUE;
118 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
120 if (desc)
122 present_parameters.BackBufferWidth = desc->width;
123 present_parameters.BackBufferHeight = desc->height;
124 present_parameters.hDeviceWindow = desc->device_window;
125 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
126 if (desc->flags & CREATE_DEVICE_LOCKABLE_BACKBUFFER)
127 present_parameters.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
128 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
129 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
130 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
131 behavior_flags |= D3DCREATE_FPU_PRESERVE;
134 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
135 behavior_flags, &present_parameters, &device)))
136 return device;
138 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
139 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
140 behavior_flags, &present_parameters, &device)))
141 return device;
143 if (desc && desc->flags & CREATE_DEVICE_SWVP_ONLY)
144 return NULL;
145 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
147 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
148 behavior_flags, &present_parameters, &device)))
149 return device;
151 return NULL;
154 static HRESULT reset_device(IDirect3DDevice8 *device, const struct device_desc *desc)
156 D3DPRESENT_PARAMETERS present_parameters = {0};
158 present_parameters.BackBufferWidth = 640;
159 present_parameters.BackBufferHeight = 480;
160 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
161 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
162 present_parameters.hDeviceWindow = NULL;
163 present_parameters.Windowed = TRUE;
164 present_parameters.EnableAutoDepthStencil = TRUE;
165 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
167 if (desc)
169 present_parameters.BackBufferWidth = desc->width;
170 present_parameters.BackBufferHeight = desc->height;
171 present_parameters.hDeviceWindow = desc->device_window;
172 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
175 return IDirect3DDevice8_Reset(device, &present_parameters);
178 #define CHECK_CALL(r,c,d,rc) \
179 if (SUCCEEDED(r)) {\
180 int tmp1 = get_refcount( (IUnknown *)d ); \
181 int rc_new = rc; \
182 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
183 } else {\
184 trace("%s failed: %#08x\n", c, r); \
187 #define CHECK_RELEASE(obj,d,rc) \
188 if (obj) { \
189 int tmp1, rc_new = rc; \
190 IUnknown_Release( (IUnknown*)obj ); \
191 tmp1 = get_refcount( (IUnknown *)d ); \
192 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
195 #define CHECK_REFCOUNT(obj,rc) \
197 int rc_new = rc; \
198 int count = get_refcount( (IUnknown *)obj ); \
199 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
202 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
204 int rc_new = rc; \
205 int count = IUnknown_Release( (IUnknown *)obj ); \
206 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
209 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
211 int rc_new = rc; \
212 int count = IUnknown_AddRef( (IUnknown *)obj ); \
213 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
216 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
218 void *container_ptr = (void *)0x1337c0d3; \
219 hr = IDirect3DSurface8_GetContainer(obj, &iid, &container_ptr); \
220 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#08x, container_ptr %p. " \
221 "Expected hr %#08x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
222 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
225 static void check_mipmap_levels(IDirect3DDevice8 *device, UINT width, UINT height, UINT count)
227 IDirect3DBaseTexture8* texture = NULL;
228 HRESULT hr = IDirect3DDevice8_CreateTexture( device, width, height, 0, 0,
229 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture8**) &texture );
231 if (SUCCEEDED(hr)) {
232 DWORD levels = IDirect3DBaseTexture8_GetLevelCount(texture);
233 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
234 } else
235 trace("CreateTexture failed: %#08x\n", hr);
237 if (texture) IDirect3DBaseTexture8_Release( texture );
240 static void test_mipmap_levels(void)
242 IDirect3DDevice8 *device;
243 IDirect3D8 *d3d;
244 ULONG refcount;
245 HWND window;
247 window = create_window();
248 ok(!!window, "Failed to create a window.\n");
249 d3d = Direct3DCreate8(D3D_SDK_VERSION);
250 ok(!!d3d, "Failed to create a D3D object.\n");
251 if (!(device = create_device(d3d, window, NULL)))
253 skip("Failed to create a 3D device, skipping test.\n");
254 goto cleanup;
257 check_mipmap_levels(device, 32, 32, 6);
258 check_mipmap_levels(device, 256, 1, 9);
259 check_mipmap_levels(device, 1, 256, 9);
260 check_mipmap_levels(device, 1, 1, 1);
262 refcount = IDirect3DDevice8_Release(device);
263 ok(!refcount, "Device has %u references left.\n", refcount);
264 cleanup:
265 IDirect3D8_Release(d3d);
266 DestroyWindow(window);
269 static void test_swapchain(void)
271 IDirect3DSwapChain8 *swapchain1;
272 IDirect3DSwapChain8 *swapchain2;
273 IDirect3DSwapChain8 *swapchain3;
274 IDirect3DSurface8 *backbuffer, *stereo_buffer;
275 D3DPRESENT_PARAMETERS d3dpp;
276 IDirect3DDevice8 *device;
277 IDirect3D8 *d3d;
278 ULONG refcount;
279 HWND window, window2;
280 HRESULT hr;
281 struct device_desc device_desc;
283 window = create_window();
284 ok(!!window, "Failed to create a window.\n");
285 window2 = create_window();
286 ok(!!window2, "Failed to create a window.\n");
287 d3d = Direct3DCreate8(D3D_SDK_VERSION);
288 ok(!!d3d, "Failed to create a D3D object.\n");
289 if (!(device = create_device(d3d, window, NULL)))
291 skip("Failed to create a 3D device, skipping test.\n");
292 goto cleanup;
295 backbuffer = (void *)0xdeadbeef;
296 /* IDirect3DDevice8::GetBackBuffer crashes if a NULL output pointer is passed. */
297 hr = IDirect3DDevice8_GetBackBuffer(device, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
298 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
299 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
301 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
302 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
303 IDirect3DSurface8_Release(backbuffer);
305 /* The back buffer type value is ignored. */
306 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
307 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
308 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
309 IDirect3DSurface8_Release(stereo_buffer);
310 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
311 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
312 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
313 IDirect3DSurface8_Release(stereo_buffer);
314 hr = IDirect3DDevice8_GetBackBuffer(device, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
315 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
316 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
317 IDirect3DSurface8_Release(stereo_buffer);
319 memset(&d3dpp, 0, sizeof(d3dpp));
320 d3dpp.Windowed = TRUE;
321 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
322 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
324 /* Create a bunch of swapchains */
325 d3dpp.BackBufferCount = 0;
326 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
327 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
328 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
330 d3dpp.BackBufferCount = 1;
331 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
332 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
334 d3dpp.BackBufferCount = 2;
335 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
336 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
337 if(SUCCEEDED(hr)) {
338 /* Swapchain 3, created with backbuffercount 2 */
339 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, NULL);
340 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
342 backbuffer = (void *) 0xdeadbeef;
343 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
344 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%#08x)\n", hr);
345 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
346 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
348 /* The back buffer type value is ignored. */
349 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
350 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
351 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
352 IDirect3DSurface8_Release(stereo_buffer);
353 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
354 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
355 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
356 IDirect3DSurface8_Release(stereo_buffer);
357 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
358 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
359 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
360 IDirect3DSurface8_Release(stereo_buffer);
362 backbuffer = (void *) 0xdeadbeef;
363 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
364 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%#08x)\n", hr);
365 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
366 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
368 backbuffer = (void *) 0xdeadbeef;
369 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
370 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
371 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
372 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
374 backbuffer = (void *) 0xdeadbeef;
375 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
376 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
377 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
378 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
381 /* Check the back buffers of the swapchains */
382 /* Swapchain 1, created with backbuffercount 0 */
383 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
384 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
385 ok(backbuffer != NULL, "The back buffer is NULL (%#08x)\n", hr);
386 if(backbuffer) IDirect3DSurface8_Release(backbuffer);
388 backbuffer = (void *) 0xdeadbeef;
389 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
390 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
391 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
392 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
394 /* Swapchain 2 - created with backbuffercount 1 */
395 backbuffer = (void *) 0xdeadbeef;
396 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
397 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
398 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
399 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
401 backbuffer = (void *) 0xdeadbeef;
402 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
403 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
404 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
405 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
407 backbuffer = (void *) 0xdeadbeef;
408 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
409 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
410 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
411 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
413 IDirect3DSwapChain8_Release(swapchain3);
414 IDirect3DSwapChain8_Release(swapchain2);
415 IDirect3DSwapChain8_Release(swapchain1);
417 d3dpp.Windowed = FALSE;
418 d3dpp.hDeviceWindow = window;
419 d3dpp.BackBufferCount = 1;
420 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
421 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
422 d3dpp.hDeviceWindow = window2;
423 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
424 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
426 device_desc.width = registry_mode.dmPelsWidth;
427 device_desc.height = registry_mode.dmPelsHeight;
428 device_desc.device_window = window;
429 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
430 hr = reset_device(device, &device_desc);
431 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
433 d3dpp.hDeviceWindow = window;
434 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
436 d3dpp.hDeviceWindow = window2;
437 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
438 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
439 d3dpp.Windowed = TRUE;
440 d3dpp.hDeviceWindow = window;
441 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
442 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
443 d3dpp.hDeviceWindow = window2;
444 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
445 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
447 refcount = IDirect3DDevice8_Release(device);
448 ok(!refcount, "Device has %u references left.\n", refcount);
449 cleanup:
450 IDirect3D8_Release(d3d);
451 DestroyWindow(window2);
452 DestroyWindow(window);
455 static void test_refcount(void)
457 IDirect3DVertexBuffer8 *pVertexBuffer = NULL;
458 IDirect3DIndexBuffer8 *pIndexBuffer = NULL;
459 DWORD dVertexShader = -1;
460 DWORD dPixelShader = -1;
461 IDirect3DCubeTexture8 *pCubeTexture = NULL;
462 IDirect3DTexture8 *pTexture = NULL;
463 IDirect3DVolumeTexture8 *pVolumeTexture = NULL;
464 IDirect3DVolume8 *pVolumeLevel = NULL;
465 IDirect3DSurface8 *pStencilSurface = NULL;
466 IDirect3DSurface8 *pImageSurface = NULL;
467 IDirect3DSurface8 *pRenderTarget = NULL;
468 IDirect3DSurface8 *pRenderTarget2 = NULL;
469 IDirect3DSurface8 *pRenderTarget3 = NULL;
470 IDirect3DSurface8 *pTextureLevel = NULL;
471 IDirect3DSurface8 *pBackBuffer = NULL;
472 DWORD dStateBlock = -1;
473 IDirect3DSwapChain8 *pSwapChain = NULL;
474 D3DCAPS8 caps;
475 D3DPRESENT_PARAMETERS d3dpp;
476 IDirect3DDevice8 *device = NULL;
477 ULONG refcount = 0, tmp;
478 IDirect3D8 *d3d, *d3d2;
479 HWND window;
480 HRESULT hr;
482 DWORD decl[] =
484 D3DVSD_STREAM(0),
485 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
486 D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
487 D3DVSD_END()
490 window = create_window();
491 ok(!!window, "Failed to create a window.\n");
492 d3d = Direct3DCreate8(D3D_SDK_VERSION);
493 ok(!!d3d, "Failed to create a D3D object.\n");
495 CHECK_REFCOUNT(d3d, 1);
497 if (!(device = create_device(d3d, window, NULL)))
499 skip("Failed to create a 3D device, skipping test.\n");
500 goto cleanup;
503 IDirect3DDevice8_GetDeviceCaps(device, &caps);
505 refcount = get_refcount((IUnknown *)device);
506 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
508 CHECK_REFCOUNT(d3d, 2);
510 hr = IDirect3DDevice8_GetDirect3D(device, &d3d2);
511 CHECK_CALL(hr, "GetDirect3D", device, refcount);
513 ok(d3d2 == d3d, "Expected IDirect3D8 pointers to be equal.\n");
514 CHECK_REFCOUNT(d3d, 3);
515 CHECK_RELEASE_REFCOUNT(d3d, 2);
518 * Check refcount of implicit surfaces. Findings:
519 * - the container is the device
520 * - they hold a reference to the device
521 * - they are created with a refcount of 0 (Get/Release returns original refcount)
522 * - they are not freed if refcount reaches 0.
523 * - the refcount is not forwarded to the container.
525 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget);
526 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
527 if (pRenderTarget)
529 CHECK_SURFACE_CONTAINER(pRenderTarget, IID_IDirect3DDevice8, device);
530 CHECK_REFCOUNT(pRenderTarget, 1);
532 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
533 CHECK_REFCOUNT(device, refcount);
534 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
535 CHECK_REFCOUNT(device, refcount);
537 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget);
538 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
539 CHECK_REFCOUNT(pRenderTarget, 2);
540 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
541 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
542 CHECK_REFCOUNT(device, --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(device, ++refcount);
547 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
548 CHECK_REFCOUNT(device, --refcount);
549 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
550 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
553 /* Render target and back buffer are identical. */
554 hr = IDirect3DDevice8_GetBackBuffer(device, 0, 0, &pBackBuffer);
555 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
556 if (pBackBuffer)
558 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
559 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
560 pRenderTarget, pBackBuffer);
561 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
562 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
563 pBackBuffer = NULL;
565 CHECK_REFCOUNT(device, --refcount);
567 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &pStencilSurface);
568 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
569 if (pStencilSurface)
571 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice8, device);
572 CHECK_REFCOUNT(pStencilSurface, 1);
574 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
575 CHECK_REFCOUNT(device, refcount);
576 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
577 CHECK_REFCOUNT(device, refcount);
579 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
580 CHECK_REFCOUNT(device, --refcount);
582 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
583 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
584 CHECK_REFCOUNT(device, ++refcount);
585 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
586 CHECK_REFCOUNT(device, --refcount);
587 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
588 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
589 pStencilSurface = NULL;
592 /* Buffers */
593 hr = IDirect3DDevice8_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer);
594 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount);
595 if(pIndexBuffer)
597 tmp = get_refcount( (IUnknown *)pIndexBuffer );
599 hr = IDirect3DDevice8_SetIndices(device, pIndexBuffer, 0);
600 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
601 hr = IDirect3DDevice8_SetIndices(device, NULL, 0);
602 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
605 hr = IDirect3DDevice8_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer);
606 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
607 if(pVertexBuffer)
609 IDirect3DVertexBuffer8 *pVBuf = (void*)~0;
610 UINT stride = ~0;
612 tmp = get_refcount( (IUnknown *)pVertexBuffer );
614 hr = IDirect3DDevice8_SetStreamSource(device, 0, pVertexBuffer, 3 * sizeof(float));
615 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
616 hr = IDirect3DDevice8_SetStreamSource(device, 0, NULL, 0);
617 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
619 hr = IDirect3DDevice8_GetStreamSource(device, 0, &pVBuf, &stride);
620 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
621 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
622 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
625 /* Shaders */
626 hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_vs, &dVertexShader, 0);
627 CHECK_CALL(hr, "CreateVertexShader", device, refcount);
628 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
630 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &dPixelShader);
631 CHECK_CALL(hr, "CreatePixelShader", device, refcount);
633 /* Textures */
634 hr = IDirect3DDevice8_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture);
635 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
636 if (pTexture)
638 tmp = get_refcount( (IUnknown *)pTexture );
640 /* SetTexture should not increase refcounts */
641 hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) pTexture);
642 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
643 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
644 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
646 /* This should not increment device refcount */
647 hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
648 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
649 /* But should increment texture's refcount */
650 CHECK_REFCOUNT( pTexture, tmp+1 );
651 /* Because the texture and surface refcount are identical */
652 if (pTextureLevel)
654 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
655 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
656 CHECK_REFCOUNT ( pTexture , tmp+2 );
657 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
658 CHECK_REFCOUNT ( pTexture , tmp+1 );
659 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
660 CHECK_REFCOUNT ( pTextureLevel, tmp );
663 if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
665 hr = IDirect3DDevice8_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture);
666 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
668 else
670 skip("Cube textures not supported\n");
672 if(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
674 hr = IDirect3DDevice8_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
675 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture);
676 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
678 else
680 skip("Volume textures not supported\n");
683 if (pVolumeTexture)
685 tmp = get_refcount( (IUnknown *)pVolumeTexture );
687 /* This should not increment device refcount */
688 hr = IDirect3DVolumeTexture8_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
689 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
690 /* But should increment volume texture's refcount */
691 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
692 /* Because the volume texture and volume refcount are identical */
693 if (pVolumeLevel)
695 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
696 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
697 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
698 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
699 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
700 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
701 CHECK_REFCOUNT ( pVolumeLevel , tmp );
704 /* Surfaces */
705 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32,
706 D3DFMT_D16, D3DMULTISAMPLE_NONE, &pStencilSurface);
707 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
708 CHECK_REFCOUNT( pStencilSurface, 1);
709 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32,
710 D3DFMT_X8R8G8B8, &pImageSurface);
711 CHECK_CALL(hr, "CreateImageSurface", device, ++refcount);
712 CHECK_REFCOUNT( pImageSurface, 1);
713 hr = IDirect3DDevice8_CreateRenderTarget(device, 32, 32,
714 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget3);
715 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
716 CHECK_REFCOUNT( pRenderTarget3, 1);
717 /* Misc */
718 hr = IDirect3DDevice8_CreateStateBlock(device, D3DSBT_ALL, &dStateBlock);
719 CHECK_CALL(hr, "CreateStateBlock", device, refcount);
721 memset(&d3dpp, 0, sizeof(d3dpp));
722 d3dpp.Windowed = TRUE;
723 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
724 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
725 d3dpp.EnableAutoDepthStencil = TRUE;
726 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
727 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
728 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
729 if(pSwapChain)
731 /* check implicit back buffer */
732 hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
733 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
734 CHECK_REFCOUNT( pSwapChain, 1);
735 if(pBackBuffer)
737 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DDevice8, device);
738 CHECK_REFCOUNT( pBackBuffer, 1);
739 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
740 CHECK_REFCOUNT(device, --refcount);
742 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
743 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
744 CHECK_REFCOUNT(device, ++refcount);
745 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
746 CHECK_REFCOUNT(device, --refcount);
747 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
748 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
749 pBackBuffer = NULL;
751 CHECK_REFCOUNT( pSwapChain, 1);
754 if(pVertexBuffer)
756 BYTE *data;
757 /* Vertex buffers can be locked multiple times */
758 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
759 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
760 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
761 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
762 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
763 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
764 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
765 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
768 /* The implicit render target is not freed if refcount reaches 0.
769 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
770 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget2);
771 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
772 if (pRenderTarget2)
774 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
775 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
776 pRenderTarget, pRenderTarget2);
777 CHECK_REFCOUNT(device, --refcount);
778 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
779 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
780 pRenderTarget2 = NULL;
782 pRenderTarget = NULL;
784 cleanup:
785 CHECK_RELEASE(device, device, --refcount);
787 /* Buffers */
788 CHECK_RELEASE(pVertexBuffer, device, --refcount);
789 CHECK_RELEASE(pIndexBuffer, device, --refcount);
790 /* Shaders */
791 if (dVertexShader != ~0u)
792 IDirect3DDevice8_DeleteVertexShader(device, dVertexShader);
793 if (dPixelShader != ~0u)
794 IDirect3DDevice8_DeletePixelShader(device, dPixelShader);
795 /* Textures */
796 CHECK_RELEASE(pTexture, device, --refcount);
797 CHECK_RELEASE(pCubeTexture, device, --refcount);
798 CHECK_RELEASE(pVolumeTexture, device, --refcount);
799 /* Surfaces */
800 CHECK_RELEASE(pStencilSurface, device, --refcount);
801 CHECK_RELEASE(pImageSurface, device, --refcount);
802 CHECK_RELEASE(pRenderTarget3, device, --refcount);
803 /* Misc */
804 if (dStateBlock != ~0u)
805 IDirect3DDevice8_DeleteStateBlock(device, dStateBlock);
806 /* This will destroy device - cannot check the refcount here */
807 if (pSwapChain)
808 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
809 CHECK_RELEASE_REFCOUNT(d3d, 0);
810 DestroyWindow(window);
813 static void test_checkdevicemultisampletype(void)
815 IDirect3D8 *d3d;
816 HWND window;
817 HRESULT hr;
819 window = create_window();
820 ok(!!window, "Failed to create a window.\n");
821 d3d = Direct3DCreate8(D3D_SDK_VERSION);
822 ok(!!d3d, "Failed to create a D3D object.\n");
824 if (IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
825 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES) == D3DERR_NOTAVAILABLE)
827 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
828 goto cleanup;
831 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
832 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE);
833 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
834 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
835 65536, TRUE, D3DMULTISAMPLE_NONE);
836 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
838 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
839 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE);
840 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
841 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
842 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE);
843 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
845 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
846 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES);
847 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
849 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
850 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
851 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES);
852 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
854 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
855 D3DFMT_X8R8G8B8, TRUE, 65536);
856 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
858 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
859 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES);
860 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
862 cleanup:
863 IDirect3D8_Release(d3d);
864 DestroyWindow(window);
867 static void test_invalid_multisample(void)
869 IDirect3DDevice8 *device;
870 IDirect3DSurface8 *rt;
871 IDirect3D8 *d3d;
872 BOOL available;
873 ULONG refcount;
874 HWND window;
875 HRESULT hr;
877 window = create_window();
878 ok(!!window, "Failed to create a window.\n");
879 d3d = Direct3DCreate8(D3D_SDK_VERSION);
880 ok(!!d3d, "Failed to create a D3D object.\n");
882 if (!(device = create_device(d3d, window, NULL)))
884 skip("Failed to create a 3D device, skipping test.\n");
885 goto cleanup;
888 available = SUCCEEDED(IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
889 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES));
891 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128,
892 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, FALSE, &rt);
893 if (available)
895 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
896 IDirect3DSurface8_Release(rt);
898 else
900 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
903 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
904 available = SUCCEEDED(IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
905 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES));
906 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128,
907 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, FALSE, &rt);
908 if (available)
910 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
911 IDirect3DSurface8_Release(rt);
913 else
915 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
918 refcount = IDirect3DDevice8_Release(device);
919 ok(!refcount, "Device has %u references left.\n", refcount);
920 cleanup:
921 IDirect3D8_Release(d3d);
922 DestroyWindow(window);
925 static void test_cursor(void)
927 HMODULE user32_handle = GetModuleHandleA("user32.dll");
928 IDirect3DSurface8 *cursor = NULL;
929 IDirect3DDevice8 *device;
930 CURSORINFO info;
931 IDirect3D8 *d3d;
932 ULONG refcount;
933 HCURSOR cur;
934 HWND window;
935 HRESULT hr;
936 BOOL ret;
938 pGetCursorInfo = (void *)GetProcAddress(user32_handle, "GetCursorInfo");
939 if (!pGetCursorInfo)
941 win_skip("GetCursorInfo is not available\n");
942 return;
945 window = create_window();
946 ok(!!window, "Failed to create a window.\n");
948 ret = SetCursorPos(50, 50);
949 ok(ret, "Failed to set cursor position.\n");
950 flush_events();
952 memset(&info, 0, sizeof(info));
953 info.cbSize = sizeof(info);
954 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
955 cur = info.hCursor;
957 d3d = Direct3DCreate8(D3D_SDK_VERSION);
958 ok(!!d3d, "Failed to create a D3D object.\n");
959 if (!(device = create_device(d3d, window, NULL)))
961 skip("Failed to create a 3D device, skipping test.\n");
962 goto cleanup;
965 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
966 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
968 /* Initially hidden */
969 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
970 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
972 /* Not enabled without a surface*/
973 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
974 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
976 /* Fails */
977 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, NULL);
978 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
980 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
981 ok(hr == D3D_OK, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
983 IDirect3DSurface8_Release(cursor);
985 memset(&info, 0, sizeof(info));
986 info.cbSize = sizeof(info);
987 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
988 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
989 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
991 /* Still hidden */
992 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
993 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
995 /* Enabled now*/
996 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
997 ok(ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
999 memset(&info, 0, sizeof(info));
1000 info.cbSize = sizeof(info);
1001 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
1002 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1003 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1005 refcount = IDirect3DDevice8_Release(device);
1006 ok(!refcount, "Device has %u references left.\n", refcount);
1007 cleanup:
1008 IDirect3D8_Release(d3d);
1009 DestroyWindow(window);
1012 static const POINT *expect_pos;
1014 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
1016 if (message == WM_MOUSEMOVE)
1018 if (expect_pos && expect_pos->x && expect_pos->y)
1020 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
1022 ClientToScreen(window, &p);
1023 if (expect_pos->x == p.x && expect_pos->y == p.y)
1024 ++expect_pos;
1028 return DefWindowProcA(window, message, wparam, lparam);
1031 static void test_cursor_pos(void)
1033 IDirect3DSurface8 *cursor;
1034 IDirect3DDevice8 *device;
1035 WNDCLASSA wc = {0};
1036 IDirect3D8 *d3d8;
1037 UINT refcount;
1038 HWND window;
1039 HRESULT hr;
1040 BOOL ret;
1042 /* Note that we don't check for movement we're not supposed to receive.
1043 * That's because it's hard to distinguish from the user accidentally
1044 * moving the mouse. */
1045 static const POINT points[] =
1047 {50, 50},
1048 {75, 75},
1049 {100, 100},
1050 {125, 125},
1051 {150, 150},
1052 {125, 125},
1053 {150, 150},
1054 {150, 150},
1055 {0, 0},
1058 wc.lpfnWndProc = test_cursor_proc;
1059 wc.lpszClassName = "d3d8_test_cursor_wc";
1060 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1061 window = CreateWindowA("d3d8_test_cursor_wc", "d3d8_test", WS_POPUP | WS_SYSMENU,
1062 0, 0, 320, 240, NULL, NULL, NULL, NULL);
1063 ShowWindow(window, SW_SHOW);
1064 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1065 ok(!!d3d8, "Failed to create a D3D object.\n");
1067 if (!(device = create_device(d3d8, window, NULL)))
1069 skip("Failed to create a D3D device, skipping tests.\n");
1070 goto done;
1073 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
1074 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1075 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1076 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
1077 IDirect3DSurface8_Release(cursor);
1078 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
1079 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
1081 flush_events();
1082 expect_pos = points;
1084 ret = SetCursorPos(50, 50);
1085 ok(ret, "Failed to set cursor position.\n");
1086 flush_events();
1088 IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
1089 flush_events();
1090 /* SetCursorPosition() eats duplicates. */
1091 IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
1092 flush_events();
1094 ret = SetCursorPos(100, 100);
1095 ok(ret, "Failed to set cursor position.\n");
1096 flush_events();
1097 /* Even if the position was set with SetCursorPos(). */
1098 IDirect3DDevice8_SetCursorPosition(device, 100, 100, 0);
1099 flush_events();
1101 IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
1102 flush_events();
1103 ret = SetCursorPos(150, 150);
1104 ok(ret, "Failed to set cursor position.\n");
1105 flush_events();
1106 IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
1107 flush_events();
1109 IDirect3DDevice8_SetCursorPosition(device, 150, 150, 0);
1110 flush_events();
1111 /* SetCursorPos() doesn't. */
1112 ret = SetCursorPos(150, 150);
1113 ok(ret, "Failed to set cursor position.\n");
1114 flush_events();
1116 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
1117 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
1119 refcount = IDirect3DDevice8_Release(device);
1120 ok(!refcount, "Device has %u references left.\n", refcount);
1121 done:
1122 DestroyWindow(window);
1123 UnregisterClassA("d3d8_test_cursor_wc", GetModuleHandleA(NULL));
1124 IDirect3D8_Release(d3d8);
1127 static void test_states(void)
1129 IDirect3DDevice8 *device;
1130 IDirect3D8 *d3d;
1131 ULONG refcount;
1132 HWND window;
1133 HRESULT hr;
1135 window = create_window();
1136 ok(!!window, "Failed to create a window.\n");
1137 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1138 ok(!!d3d, "Failed to create a D3D object.\n");
1139 if (!(device = create_device(d3d, window, NULL)))
1141 skip("Failed to create a 3D device, skipping test.\n");
1142 goto cleanup;
1145 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZVISIBLE, TRUE);
1146 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, TRUE) returned %#08x\n", hr);
1147 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZVISIBLE, FALSE);
1148 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, FALSE) returned %#08x\n", hr);
1150 refcount = IDirect3DDevice8_Release(device);
1151 ok(!refcount, "Device has %u references left.\n", refcount);
1152 cleanup:
1153 IDirect3D8_Release(d3d);
1154 DestroyWindow(window);
1157 static void test_shader_versions(void)
1159 IDirect3D8 *d3d;
1160 D3DCAPS8 caps;
1161 HRESULT hr;
1163 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1164 ok(!!d3d, "Failed to create a D3D object.\n");
1166 hr = IDirect3D8_GetDeviceCaps(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
1167 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to get device caps, hr %#x.\n", hr);
1168 IDirect3D8_Release(d3d);
1169 if (FAILED(hr))
1171 skip("No Direct3D support, skipping test.\n");
1172 return;
1175 ok(caps.VertexShaderVersion <= D3DVS_VERSION(1,1),
1176 "Got unexpected VertexShaderVersion %#x.\n", caps.VertexShaderVersion);
1177 ok(caps.PixelShaderVersion <= D3DPS_VERSION(1,4),
1178 "Got unexpected PixelShaderVersion %#x.\n", caps.PixelShaderVersion);
1181 static void test_display_formats(void)
1183 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
1184 unsigned int backbuffer, display;
1185 unsigned int windowed, i;
1186 D3DDISPLAYMODE mode;
1187 IDirect3D8 *d3d8;
1188 BOOL should_pass;
1189 BOOL has_modes;
1190 HRESULT hr;
1192 static const struct
1194 const char *name;
1195 D3DFORMAT format;
1196 D3DFORMAT alpha_format;
1197 BOOL display;
1198 BOOL windowed;
1200 formats[] =
1202 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
1203 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
1204 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
1205 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
1206 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
1207 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
1210 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1211 ok(!!d3d8, "Failed to create a D3D object.\n");
1213 for (display = 0; display < ARRAY_SIZE(formats); ++display)
1215 for (i = 0, has_modes = FALSE; SUCCEEDED(IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &mode)); ++i)
1217 if (mode.Format == formats[display].format)
1219 has_modes = TRUE;
1220 break;
1224 for (windowed = 0; windowed <= 1; ++windowed)
1226 for (backbuffer = 0; backbuffer < ARRAY_SIZE(formats); ++backbuffer)
1228 should_pass = FALSE;
1230 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
1232 D3DFORMAT backbuffer_format;
1234 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
1235 backbuffer_format = formats[display].format;
1236 else
1237 backbuffer_format = formats[backbuffer].format;
1239 hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, device_type, formats[display].format,
1240 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
1241 should_pass = (hr == D3D_OK) && (formats[display].format == formats[backbuffer].format
1242 || (formats[display].alpha_format
1243 && formats[display].alpha_format == formats[backbuffer].alpha_format));
1246 hr = IDirect3D8_CheckDeviceType(d3d8, D3DADAPTER_DEFAULT, device_type,
1247 formats[display].format, formats[backbuffer].format, windowed);
1248 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
1249 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
1250 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
1255 IDirect3D8_Release(d3d8);
1258 /* Test adapter display modes */
1259 static void test_display_modes(void)
1261 UINT max_modes, i;
1262 D3DDISPLAYMODE dmode;
1263 IDirect3D8 *d3d;
1264 HRESULT res;
1266 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1267 ok(!!d3d, "Failed to create a D3D object.\n");
1269 max_modes = IDirect3D8_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT);
1270 ok(max_modes > 0 ||
1271 broken(max_modes == 0), /* VMware */
1272 "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
1274 for (i = 0; i < max_modes; ++i)
1276 res = IDirect3D8_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, i, &dmode);
1277 ok(res==D3D_OK, "EnumAdapterModes returned %#08x for mode %u!\n", res, i);
1278 if(res != D3D_OK)
1279 continue;
1281 ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
1282 "Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
1285 IDirect3D8_Release(d3d);
1288 struct mode
1290 unsigned int w;
1291 unsigned int h;
1294 static int compare_mode(const void *a, const void *b)
1296 const struct mode *mode_a = a;
1297 const struct mode *mode_b = b;
1298 unsigned int w = mode_a->w - mode_b->w;
1299 unsigned int h = mode_a->h - mode_b->h;
1300 return abs(w) >= abs(h) ? -w : -h;
1303 static void test_reset(void)
1305 UINT width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1306 UINT height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1307 IDirect3DDevice8 *device1 = NULL;
1308 IDirect3DDevice8 *device2 = NULL;
1309 struct device_desc device_desc;
1310 D3DDISPLAYMODE d3ddm, d3ddm2;
1311 D3DSURFACE_DESC surface_desc;
1312 D3DPRESENT_PARAMETERS d3dpp;
1313 IDirect3DSurface8 *surface;
1314 IDirect3DTexture8 *texture;
1315 IDirect3DVertexBuffer8 *vb;
1316 IDirect3DIndexBuffer8 *ib;
1317 UINT adapter_mode_count;
1318 D3DLOCKED_RECT lockrect;
1319 UINT mode_count = 0;
1320 DEVMODEW devmode;
1321 IDirect3D8 *d3d8;
1322 RECT winrect, client_rect;
1323 D3DVIEWPORT8 vp;
1324 D3DCAPS8 caps;
1325 DWORD shader;
1326 DWORD value;
1327 HWND window;
1328 HRESULT hr;
1329 LONG ret;
1330 UINT i;
1332 static const DWORD decl[] =
1334 D3DVSD_STREAM(0),
1335 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4),
1336 D3DVSD_END(),
1339 struct mode *modes = NULL;
1341 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1342 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1343 ok(!!window, "Failed to create a window.\n");
1344 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1345 ok(!!d3d8, "Failed to create a D3D object.\n");
1347 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1348 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1349 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
1350 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1351 for (i = 0; i < adapter_mode_count; ++i)
1353 UINT j;
1355 memset(&d3ddm2, 0, sizeof(d3ddm2));
1356 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm2);
1357 ok(SUCCEEDED(hr), "EnumAdapterModes failed, hr %#x.\n", hr);
1359 if (d3ddm2.Format != d3ddm.Format)
1360 continue;
1362 for (j = 0; j < mode_count; ++j)
1364 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1365 break;
1367 if (j == mode_count)
1369 modes[j].w = d3ddm2.Width;
1370 modes[j].h = d3ddm2.Height;
1371 ++mode_count;
1374 /* We use them as invalid modes. */
1375 if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
1376 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
1378 skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
1379 d3ddm2.Width, d3ddm2.Height);
1380 goto cleanup;
1384 if (mode_count < 2)
1386 skip("Less than 2 modes supported, skipping mode tests.\n");
1387 goto cleanup;
1390 /* Prefer higher resolutions. */
1391 qsort(modes, mode_count, sizeof(*modes), compare_mode);
1393 i = 0;
1394 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1396 device_desc.width = modes[i].w;
1397 device_desc.height = modes[i].h;
1398 device_desc.device_window = window;
1399 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1400 if (!(device1 = create_device(d3d8, window, &device_desc)))
1402 skip("Failed to create a D3D device, skipping tests.\n");
1403 goto cleanup;
1405 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1406 /* This skips the test on testbot Win 8 VMs. */
1407 if (hr == D3DERR_DEVICELOST)
1409 skip("Device is lost.\n");
1410 goto cleanup;
1412 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1414 hr = IDirect3DDevice8_GetDeviceCaps(device1, &caps);
1415 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1417 width = GetSystemMetrics(SM_CXSCREEN);
1418 height = GetSystemMetrics(SM_CYSCREEN);
1419 ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1420 ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1422 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1423 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1424 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1425 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1426 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1427 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1428 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1429 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1431 i = 1;
1432 vp.X = 10;
1433 vp.Y = 20;
1434 vp.Width = modes[i].w / 2;
1435 vp.Height = modes[i].h / 2;
1436 vp.MinZ = 0.2f;
1437 vp.MaxZ = 0.3f;
1438 hr = IDirect3DDevice8_SetViewport(device1, &vp);
1439 ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1441 hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1442 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1443 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1444 hr = IDirect3DDevice8_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1445 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1447 memset(&d3dpp, 0, sizeof(d3dpp));
1448 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1449 d3dpp.Windowed = FALSE;
1450 d3dpp.BackBufferWidth = modes[i].w;
1451 d3dpp.BackBufferHeight = modes[i].h;
1452 d3dpp.BackBufferFormat = d3ddm.Format;
1453 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1454 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1455 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1456 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1458 hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1459 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1460 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1462 memset(&vp, 0, sizeof(vp));
1463 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1464 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1465 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1466 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1467 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1468 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1469 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1470 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1472 width = GetSystemMetrics(SM_CXSCREEN);
1473 height = GetSystemMetrics(SM_CYSCREEN);
1474 ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1475 ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1477 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1478 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1479 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1480 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1481 ok(surface_desc.Width == modes[i].w, "Back buffer width is %u, expected %u.\n",
1482 surface_desc.Width, modes[i].w);
1483 ok(surface_desc.Height == modes[i].h, "Back buffer height is %u, expected %u.\n",
1484 surface_desc.Height, modes[i].h);
1485 IDirect3DSurface8_Release(surface);
1487 memset(&d3dpp, 0, sizeof(d3dpp));
1488 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1489 d3dpp.Windowed = TRUE;
1490 d3dpp.BackBufferWidth = 400;
1491 d3dpp.BackBufferHeight = 300;
1492 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1493 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1494 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1495 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1496 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1498 memset(&vp, 0, sizeof(vp));
1499 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1500 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1501 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1502 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1503 ok(vp.Width == 400, "D3DVIEWPORT->Width = %u, expected 400.\n", vp.Width);
1504 ok(vp.Height == 300, "D3DVIEWPORT->Height = %u, expected 300.\n", vp.Height);
1505 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1506 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1508 width = GetSystemMetrics(SM_CXSCREEN);
1509 height = GetSystemMetrics(SM_CYSCREEN);
1510 ok(width == orig_width, "Screen width is %u, expected %u.\n", width, orig_width);
1511 ok(height == orig_height, "Screen height is %u, expected %u.\n", height, orig_height);
1513 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1514 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1515 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1516 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1517 ok(surface_desc.Width == 400, "Back buffer width is %u, expected 400.\n",
1518 surface_desc.Width);
1519 ok(surface_desc.Height == 300, "Back buffer height is %u, expected 300.\n",
1520 surface_desc.Height);
1521 IDirect3DSurface8_Release(surface);
1523 memset(&devmode, 0, sizeof(devmode));
1524 devmode.dmSize = sizeof(devmode);
1525 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1526 devmode.dmPelsWidth = modes[1].w;
1527 devmode.dmPelsHeight = modes[1].h;
1528 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1529 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1530 width = GetSystemMetrics(SM_CXSCREEN);
1531 height = GetSystemMetrics(SM_CYSCREEN);
1532 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1533 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1535 d3dpp.BackBufferWidth = 500;
1536 d3dpp.BackBufferHeight = 400;
1537 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1538 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1539 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1540 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1541 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1543 width = GetSystemMetrics(SM_CXSCREEN);
1544 height = GetSystemMetrics(SM_CYSCREEN);
1545 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1546 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1548 ZeroMemory(&vp, sizeof(vp));
1549 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1550 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1551 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
1552 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
1553 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
1554 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
1555 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
1556 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
1558 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1559 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1560 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1561 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1562 ok(surface_desc.Width == 500, "Back buffer width is %u, expected 500.\n",
1563 surface_desc.Width);
1564 ok(surface_desc.Height == 400, "Back buffer height is %u, expected 400.\n",
1565 surface_desc.Height);
1566 IDirect3DSurface8_Release(surface);
1568 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1569 devmode.dmPelsWidth = orig_width;
1570 devmode.dmPelsHeight = orig_height;
1571 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1572 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1573 width = GetSystemMetrics(SM_CXSCREEN);
1574 height = GetSystemMetrics(SM_CYSCREEN);
1575 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1576 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1578 winrect.left = 0;
1579 winrect.top = 0;
1580 winrect.right = 200;
1581 winrect.bottom = 150;
1582 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1583 ok(SetWindowPos(window, NULL, 0, 0,
1584 winrect.right-winrect.left,
1585 winrect.bottom-winrect.top,
1586 SWP_NOMOVE|SWP_NOZORDER),
1587 "SetWindowPos failed\n");
1589 /* Windows 10 gives us a different size than we requested with some DPI scaling settings (e.g. 172%). */
1590 GetClientRect(window, &client_rect);
1592 memset(&d3dpp, 0, sizeof(d3dpp));
1593 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1594 d3dpp.Windowed = TRUE;
1595 d3dpp.BackBufferWidth = 0;
1596 d3dpp.BackBufferHeight = 0;
1597 d3dpp.BackBufferFormat = d3ddm.Format;
1598 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1599 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1600 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1601 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1603 ok(!d3dpp.BackBufferWidth, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1604 ok(!d3dpp.BackBufferHeight, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1605 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1606 d3dpp.BackBufferFormat, d3ddm.Format);
1607 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1608 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1609 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1610 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1611 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1612 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1613 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1614 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1615 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1616 d3dpp.FullScreen_RefreshRateInHz);
1617 ok(!d3dpp.FullScreen_PresentationInterval, "Got unexpected FullScreen_PresentationInterval %#x.\n",
1618 d3dpp.FullScreen_PresentationInterval);
1620 memset(&vp, 0, sizeof(vp));
1621 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1622 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1623 if (SUCCEEDED(hr))
1625 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1626 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1627 ok(vp.Width == client_rect.right, "D3DVIEWPORT->Width = %d, expected %d\n",
1628 vp.Width, client_rect.right);
1629 ok(vp.Height == client_rect.bottom, "D3DVIEWPORT->Height = %d, expected %d\n",
1630 vp.Height, client_rect.bottom);
1631 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1632 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1635 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1636 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1637 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1638 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1639 ok(surface_desc.Format == d3ddm.Format, "Got unexpected Format %#x, expected %#x.\n",
1640 surface_desc.Format, d3ddm.Format);
1641 ok(!surface_desc.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1642 ok(surface_desc.Width == client_rect.right,
1643 "Back buffer width is %u, expected %d.\n", surface_desc.Width, client_rect.right);
1644 ok(surface_desc.Height == client_rect.bottom,
1645 "Back buffer height is %u, expected %d.\n", surface_desc.Height, client_rect.bottom);
1646 IDirect3DSurface8_Release(surface);
1648 memset(&d3dpp, 0, sizeof(d3dpp));
1649 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1650 d3dpp.Windowed = TRUE;
1651 d3dpp.BackBufferWidth = 400;
1652 d3dpp.BackBufferHeight = 300;
1653 d3dpp.BackBufferFormat = d3ddm.Format;
1655 /* Reset fails if there is a resource in the default pool. */
1656 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texture);
1657 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1658 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1659 ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1660 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1661 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1662 IDirect3DTexture8_Release(texture);
1663 /* Reset again to get the device out of the lost state. */
1664 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1665 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1666 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1667 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1669 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1671 IDirect3DVolumeTexture8 *volume_texture;
1673 hr = IDirect3DDevice8_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1674 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture);
1675 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1676 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1677 ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1678 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1679 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1680 hr, D3DERR_DEVICENOTRESET);
1681 IDirect3DVolumeTexture8_Release(volume_texture);
1682 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1683 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1684 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1685 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1687 else
1689 skip("Volume textures not supported.\n");
1692 /* Scratch, sysmem and managed pool resources are fine. */
1693 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1694 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1695 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1696 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1697 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1698 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1699 IDirect3DTexture8_Release(texture);
1701 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1702 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1703 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1704 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1705 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1706 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1707 IDirect3DTexture8_Release(texture);
1709 hr = IDirect3DDevice8_CreateVertexBuffer(device1, 16, 0,
1710 D3DFVF_XYZ, D3DPOOL_SYSTEMMEM, &vb);
1711 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#x.\n", hr);
1712 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1713 ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
1714 IDirect3DVertexBuffer8_Release(vb);
1716 hr = IDirect3DDevice8_CreateIndexBuffer(device1, 16, 0,
1717 D3DFMT_INDEX16, D3DPOOL_SYSTEMMEM, &ib);
1718 ok(hr == D3D_OK, "Failed to create index buffer, hr %#x.\n", hr);
1719 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1720 ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
1721 IDirect3DIndexBuffer8_Release(ib);
1723 /* The depth stencil should get reset to the auto depth stencil when present. */
1724 hr = IDirect3DDevice8_SetRenderTarget(device1, NULL, NULL);
1725 ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1727 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1728 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1729 ok(!surface, "Depth / stencil buffer should be NULL.\n");
1731 d3dpp.EnableAutoDepthStencil = TRUE;
1732 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1733 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1734 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1736 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1737 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1738 ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1739 if (surface) IDirect3DSurface8_Release(surface);
1741 d3dpp.EnableAutoDepthStencil = FALSE;
1742 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1743 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1745 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1746 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1747 ok(!surface, "Depth / stencil buffer should be NULL.\n");
1749 /* Will a sysmem or scratch resource survive while locked? */
1750 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1751 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1752 hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1753 ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1754 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1755 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1756 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1757 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1758 IDirect3DTexture8_UnlockRect(texture, 0);
1759 IDirect3DTexture8_Release(texture);
1761 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1762 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1763 hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1764 ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1765 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1766 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1767 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1768 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1769 IDirect3DTexture8_UnlockRect(texture, 0);
1770 IDirect3DTexture8_Release(texture);
1772 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture);
1773 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1774 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1775 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1776 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1777 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1778 IDirect3DTexture8_Release(texture);
1780 /* A reference held to an implicit surface causes failures as well. */
1781 hr = IDirect3DDevice8_GetBackBuffer(device1, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1782 ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
1783 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1784 ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1785 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1786 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1787 IDirect3DSurface8_Release(surface);
1788 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1789 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1790 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1791 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1793 /* Shaders are fine as well. */
1794 hr = IDirect3DDevice8_CreateVertexShader(device1, decl, simple_vs, &shader, 0);
1795 ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
1796 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1797 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1798 hr = IDirect3DDevice8_DeleteVertexShader(device1, shader);
1799 ok(SUCCEEDED(hr), "DeleteVertexShader failed, hr %#x.\n", hr);
1801 /* Try setting invalid modes. */
1802 memset(&d3dpp, 0, sizeof(d3dpp));
1803 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1804 d3dpp.Windowed = FALSE;
1805 d3dpp.BackBufferWidth = 32;
1806 d3dpp.BackBufferHeight = 32;
1807 d3dpp.BackBufferFormat = d3ddm.Format;
1808 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1809 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1810 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1811 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1813 memset(&d3dpp, 0, sizeof(d3dpp));
1814 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1815 d3dpp.Windowed = FALSE;
1816 d3dpp.BackBufferWidth = 801;
1817 d3dpp.BackBufferHeight = 600;
1818 d3dpp.BackBufferFormat = d3ddm.Format;
1819 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1820 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1821 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1822 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1824 memset(&d3dpp, 0, sizeof(d3dpp));
1825 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1826 d3dpp.Windowed = FALSE;
1827 d3dpp.BackBufferWidth = 0;
1828 d3dpp.BackBufferHeight = 0;
1829 d3dpp.BackBufferFormat = d3ddm.Format;
1830 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1831 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1832 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1833 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1835 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1836 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1838 memset(&d3dpp, 0, sizeof(d3dpp));
1839 d3dpp.Windowed = TRUE;
1840 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1841 d3dpp.BackBufferFormat = d3ddm.Format;
1842 d3dpp.EnableAutoDepthStencil = FALSE;
1843 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1845 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1846 window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1847 if (FAILED(hr))
1849 skip("Failed to create device, hr %#x.\n", hr);
1850 goto cleanup;
1853 hr = IDirect3DDevice8_TestCooperativeLevel(device2);
1854 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1856 d3dpp.Windowed = TRUE;
1857 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1858 d3dpp.BackBufferWidth = 400;
1859 d3dpp.BackBufferHeight = 300;
1860 d3dpp.BackBufferFormat = d3ddm.Format;
1861 d3dpp.EnableAutoDepthStencil = TRUE;
1862 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1864 hr = IDirect3DDevice8_Reset(device2, &d3dpp);
1865 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1866 if (FAILED(hr))
1867 goto cleanup;
1869 hr = IDirect3DDevice8_GetDepthStencilSurface(device2, &surface);
1870 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1871 ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1872 if (surface)
1873 IDirect3DSurface8_Release(surface);
1875 cleanup:
1876 HeapFree(GetProcessHeap(), 0, modes);
1877 if (device2)
1878 IDirect3DDevice8_Release(device2);
1879 if (device1)
1880 IDirect3DDevice8_Release(device1);
1881 IDirect3D8_Release(d3d8);
1882 DestroyWindow(window);
1885 static void test_scene(void)
1887 IDirect3DDevice8 *device;
1888 IDirect3D8 *d3d;
1889 ULONG refcount;
1890 HWND window;
1891 HRESULT hr;
1893 window = create_window();
1894 ok(!!window, "Failed to create a window.\n");
1895 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1896 ok(!!d3d, "Failed to create a D3D object.\n");
1897 if (!(device = create_device(d3d, window, NULL)))
1899 skip("Failed to create a 3D device, skipping test.\n");
1900 goto cleanup;
1903 /* Test an EndScene without BeginScene. Should return an error */
1904 hr = IDirect3DDevice8_EndScene(device);
1905 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1907 /* Test a normal BeginScene / EndScene pair, this should work */
1908 hr = IDirect3DDevice8_BeginScene(device);
1909 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1910 hr = IDirect3DDevice8_EndScene(device);
1911 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1913 /* Test another EndScene without having begun a new scene. Should return an error */
1914 hr = IDirect3DDevice8_EndScene(device);
1915 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1917 /* Two nested BeginScene and EndScene calls */
1918 hr = IDirect3DDevice8_BeginScene(device);
1919 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1920 hr = IDirect3DDevice8_BeginScene(device);
1921 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1922 hr = IDirect3DDevice8_EndScene(device);
1923 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1924 hr = IDirect3DDevice8_EndScene(device);
1925 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1927 /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
1929 refcount = IDirect3DDevice8_Release(device);
1930 ok(!refcount, "Device has %u references left.\n", refcount);
1931 cleanup:
1932 IDirect3D8_Release(d3d);
1933 DestroyWindow(window);
1936 static void test_shader(void)
1938 DWORD hPixelShader = 0, hVertexShader = 0;
1939 DWORD hPixelShader2 = 0, hVertexShader2 = 0;
1940 DWORD hTempHandle;
1941 D3DCAPS8 caps;
1942 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
1943 IDirect3DDevice8 *device;
1944 IDirect3D8 *d3d;
1945 DWORD data_size;
1946 ULONG refcount;
1947 HWND window;
1948 HRESULT hr;
1949 void *data;
1951 static DWORD dwVertexDecl[] =
1953 D3DVSD_STREAM(0),
1954 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
1955 D3DVSD_END()
1957 DWORD decl_normal_float2[] =
1959 D3DVSD_STREAM(0),
1960 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
1961 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT2), /* D3DVSDE_NORMAL, Register v1 */
1962 D3DVSD_END()
1964 DWORD decl_normal_float4[] =
1966 D3DVSD_STREAM(0),
1967 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
1968 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT4), /* D3DVSDE_NORMAL, Register v1 */
1969 D3DVSD_END()
1971 DWORD decl_normal_d3dcolor[] =
1973 D3DVSD_STREAM(0),
1974 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
1975 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL, Register v1 */
1976 D3DVSD_END()
1978 const DWORD vertex_decl_size = sizeof(dwVertexDecl);
1979 const DWORD simple_vs_size = sizeof(simple_vs);
1980 const DWORD simple_ps_size = sizeof(simple_ps);
1982 window = create_window();
1983 ok(!!window, "Failed to create a window.\n");
1984 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1985 ok(!!d3d, "Failed to create a D3D object.\n");
1986 if (!(device = create_device(d3d, window, NULL)))
1988 skip("Failed to create a 3D device, skipping test.\n");
1989 goto cleanup;
1992 IDirect3DDevice8_GetDeviceCaps(device, &caps);
1994 /* Test setting and retrieving a FVF */
1995 hr = IDirect3DDevice8_SetVertexShader(device, fvf);
1996 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1997 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
1998 ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1999 ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
2001 /* First create a vertex shader */
2002 hr = IDirect3DDevice8_SetVertexShader(device, 0);
2003 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2004 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, simple_vs, &hVertexShader, 0);
2005 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2006 /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
2007 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2008 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
2009 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
2010 /* Assign the shader, then verify that GetVertexShader works */
2011 hr = IDirect3DDevice8_SetVertexShader(device, hVertexShader);
2012 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2013 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2014 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
2015 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
2016 /* Verify that we can retrieve the declaration */
2017 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, NULL, &data_size);
2018 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
2019 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
2020 data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
2021 data_size = 1;
2022 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, data, &data_size);
2023 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
2024 "expected D3DERR_INVALIDCALL\n", hr);
2025 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
2026 data_size = vertex_decl_size;
2027 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, data, &data_size);
2028 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
2029 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
2030 ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
2031 HeapFree(GetProcessHeap(), 0, data);
2032 /* Verify that we can retrieve the shader function */
2033 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, NULL, &data_size);
2034 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
2035 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
2036 data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
2037 data_size = 1;
2038 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, data, &data_size);
2039 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
2040 "expected D3DERR_INVALIDCALL\n", hr);
2041 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
2042 data_size = simple_vs_size;
2043 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, data, &data_size);
2044 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
2045 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
2046 ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
2047 HeapFree(GetProcessHeap(), 0, data);
2048 /* Delete the assigned shader. This is supposed to work */
2049 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2050 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2051 /* The shader should be unset now */
2052 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2053 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
2054 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
2056 /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
2057 * First try the fixed function shader function, then a custom one
2059 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float2, 0, &hVertexShader, 0);
2060 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2061 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float4, 0, &hVertexShader, 0);
2062 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2063 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_d3dcolor, 0, &hVertexShader, 0);
2064 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2066 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float2, simple_vs, &hVertexShader, 0);
2067 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2068 IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2070 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
2072 /* The same with a pixel shader */
2073 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader);
2074 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2075 /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
2076 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2077 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2078 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
2079 /* Assign the shader, then verify that GetPixelShader works */
2080 hr = IDirect3DDevice8_SetPixelShader(device, hPixelShader);
2081 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
2082 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2083 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2084 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
2085 /* Verify that we can retrieve the shader function */
2086 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, NULL, &data_size);
2087 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
2088 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
2089 data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
2090 data_size = 1;
2091 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, data, &data_size);
2092 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
2093 "expected D3DERR_INVALIDCALL\n", hr);
2094 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
2095 data_size = simple_ps_size;
2096 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, data, &data_size);
2097 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
2098 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
2099 ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
2100 HeapFree(GetProcessHeap(), 0, data);
2101 /* Delete the assigned shader. This is supposed to work */
2102 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2103 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2104 /* The shader should be unset now */
2105 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2106 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2107 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
2109 /* What happens if a non-bound shader is deleted? */
2110 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader);
2111 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2112 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader2);
2113 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2115 hr = IDirect3DDevice8_SetPixelShader(device, hPixelShader);
2116 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
2117 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader2);
2118 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2119 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2120 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2121 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
2122 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2123 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2125 /* Check for double delete. */
2126 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader2);
2127 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2128 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2129 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2131 else
2133 skip("Pixel shaders not supported\n");
2136 /* What happens if a non-bound shader is deleted? */
2137 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, NULL, &hVertexShader, 0);
2138 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2139 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, NULL, &hVertexShader2, 0);
2140 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2142 hr = IDirect3DDevice8_SetVertexShader(device, hVertexShader);
2143 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2144 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader2);
2145 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2146 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2147 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
2148 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
2149 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2150 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2152 /* Check for double delete. */
2153 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader2);
2154 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2155 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2156 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2158 refcount = IDirect3DDevice8_Release(device);
2159 ok(!refcount, "Device has %u references left.\n", refcount);
2160 cleanup:
2161 IDirect3D8_Release(d3d);
2162 DestroyWindow(window);
2165 static void test_limits(void)
2167 IDirect3DTexture8 *texture;
2168 IDirect3DDevice8 *device;
2169 IDirect3D8 *d3d;
2170 unsigned int i;
2171 ULONG refcount;
2172 HWND window;
2173 HRESULT hr;
2175 window = create_window();
2176 ok(!!window, "Failed to create a window.\n");
2177 d3d = Direct3DCreate8(D3D_SDK_VERSION);
2178 ok(!!d3d, "Failed to create a D3D object.\n");
2179 if (!(device = create_device(d3d, window, NULL)))
2181 skip("Failed to create a 3D device, skipping test.\n");
2182 goto cleanup;
2185 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture);
2186 ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
2188 /* There are 8 texture stages. We should be able to access all of them */
2189 for (i = 0; i < 8; ++i)
2191 hr = IDirect3DDevice8_SetTexture(device, i, (IDirect3DBaseTexture8 *)texture);
2192 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
2193 hr = IDirect3DDevice8_SetTexture(device, i, NULL);
2194 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
2195 hr = IDirect3DDevice8_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2196 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
2199 /* Investigations show that accessing higher textures stage states does
2200 * not return an error either. Writing to too high texture stages
2201 * (approximately texture 40) causes memory corruption in windows, so
2202 * there is no bounds checking. */
2203 IDirect3DTexture8_Release(texture);
2204 refcount = IDirect3DDevice8_Release(device);
2205 ok(!refcount, "Device has %u references left.\n", refcount);
2206 cleanup:
2207 IDirect3D8_Release(d3d);
2208 DestroyWindow(window);
2211 static void test_lights(void)
2213 IDirect3DDevice8 *device;
2214 IDirect3D8 *d3d8;
2215 ULONG refcount;
2216 HWND window;
2217 HRESULT hr;
2218 unsigned int i;
2219 BOOL enabled;
2220 D3DCAPS8 caps;
2222 window = create_window();
2223 ok(!!window, "Failed to create a window.\n");
2224 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2225 ok(!!d3d8, "Failed to create a D3D object.\n");
2226 if (!(device = create_device(d3d8, window, NULL)))
2228 skip("Failed to create a 3D device, skipping test.\n");
2229 goto cleanup;
2232 memset(&caps, 0, sizeof(caps));
2233 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
2234 ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
2236 for(i = 1; i <= caps.MaxActiveLights; i++) {
2237 hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
2238 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2239 hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
2240 ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
2241 "GetLightEnable on light %u failed with %08x\n", i, hr);
2242 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2245 /* TODO: Test the rendering results in this situation */
2246 hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
2247 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2248 hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
2249 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2250 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2251 hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
2252 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2254 for(i = 1; i <= caps.MaxActiveLights; i++) {
2255 hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
2256 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2259 refcount = IDirect3DDevice8_Release(device);
2260 ok(!refcount, "Device has %u references left.\n", refcount);
2261 cleanup:
2262 IDirect3D8_Release(d3d8);
2263 DestroyWindow(window);
2266 static void test_render_zero_triangles(void)
2268 IDirect3DDevice8 *device;
2269 IDirect3D8 *d3d8;
2270 ULONG refcount;
2271 HWND window;
2272 HRESULT hr;
2274 static const struct
2276 struct vec3 position;
2277 struct vec3 normal;
2278 DWORD diffuse;
2280 quad[] =
2282 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2283 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2284 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2285 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2288 window = create_window();
2289 ok(!!window, "Failed to create a window.\n");
2290 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2291 ok(!!d3d8, "Failed to create a D3D object.\n");
2292 if (!(device = create_device(d3d8, window, NULL)))
2294 skip("Failed to create a 3D device, skipping test.\n");
2295 goto cleanup;
2298 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2299 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2301 hr = IDirect3DDevice8_BeginScene(device);
2302 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2303 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
2304 0 /* PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
2305 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2306 hr = IDirect3DDevice8_EndScene(device);
2307 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2309 IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2311 refcount = IDirect3DDevice8_Release(device);
2312 ok(!refcount, "Device has %u references left.\n", refcount);
2313 cleanup:
2314 IDirect3D8_Release(d3d8);
2315 DestroyWindow(window);
2318 static void test_depth_stencil_reset(void)
2320 D3DPRESENT_PARAMETERS present_parameters;
2321 D3DDISPLAYMODE display_mode;
2322 IDirect3DSurface8 *surface, *orig_rt;
2323 IDirect3DDevice8 *device = NULL;
2324 IDirect3D8 *d3d8;
2325 UINT refcount;
2326 HRESULT hr;
2327 HWND hwnd;
2329 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2330 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2331 ok(!!hwnd, "Failed to create a window.\n");
2332 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2333 ok(!!d3d8, "Failed to create a D3D object.\n");
2335 IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
2336 memset(&present_parameters, 0, sizeof(present_parameters));
2337 present_parameters.Windowed = TRUE;
2338 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2339 present_parameters.BackBufferFormat = display_mode.Format;
2340 present_parameters.EnableAutoDepthStencil = TRUE;
2341 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2343 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2344 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
2345 if(FAILED(hr))
2347 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2348 goto cleanup;
2351 hr = IDirect3DDevice8_GetRenderTarget(device, &orig_rt);
2352 ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2354 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2355 ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
2357 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2358 ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
2360 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
2361 ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2362 ok(surface == orig_rt, "Render target is %p, should be %p\n", surface, orig_rt);
2363 if (surface) IDirect3DSurface8_Release(surface);
2364 IDirect3DSurface8_Release(orig_rt);
2366 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2367 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2368 ok(surface == NULL, "Depth stencil should be NULL\n");
2370 present_parameters.EnableAutoDepthStencil = TRUE;
2371 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2372 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2373 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2375 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2376 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2377 ok(surface != NULL, "Depth stencil should not be NULL\n");
2378 if (surface) IDirect3DSurface8_Release(surface);
2380 present_parameters.EnableAutoDepthStencil = FALSE;
2381 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2382 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2384 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2385 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2386 ok(surface == NULL, "Depth stencil should be NULL\n");
2388 refcount = IDirect3DDevice8_Release(device);
2389 ok(!refcount, "Device has %u references left.\n", refcount);
2390 device = NULL;
2392 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
2394 ZeroMemory( &present_parameters, sizeof(present_parameters) );
2395 present_parameters.Windowed = TRUE;
2396 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2397 present_parameters.BackBufferFormat = display_mode.Format;
2398 present_parameters.EnableAutoDepthStencil = FALSE;
2399 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2401 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2402 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2404 if(FAILED(hr))
2406 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2407 goto cleanup;
2410 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2411 ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
2413 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2414 present_parameters.Windowed = TRUE;
2415 present_parameters.BackBufferWidth = 400;
2416 present_parameters.BackBufferHeight = 300;
2417 present_parameters.EnableAutoDepthStencil = TRUE;
2418 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2420 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2421 ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
2423 if (FAILED(hr)) goto cleanup;
2425 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2426 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2427 ok(surface != NULL, "Depth stencil should not be NULL\n");
2428 if (surface) IDirect3DSurface8_Release(surface);
2430 cleanup:
2431 if (device)
2433 refcount = IDirect3DDevice8_Release(device);
2434 ok(!refcount, "Device has %u references left.\n", refcount);
2436 IDirect3D8_Release(d3d8);
2437 DestroyWindow(hwnd);
2440 static HWND filter_messages;
2442 enum message_window
2444 DEVICE_WINDOW,
2445 FOCUS_WINDOW,
2448 struct message
2450 UINT message;
2451 enum message_window window;
2452 BOOL check_wparam;
2453 WPARAM expect_wparam;
2454 HRESULT device_state;
2455 WINDOWPOS *store_wp;
2458 static const struct message *expect_messages;
2459 static HWND device_window, focus_window;
2460 static LONG windowposchanged_received, syscommand_received;
2461 static IDirect3DDevice8 *focus_test_device;
2463 struct wndproc_thread_param
2465 HWND dummy_window;
2466 HANDLE window_created;
2467 HANDLE test_finished;
2468 BOOL running_in_foreground;
2471 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2473 HRESULT hr;
2475 if (filter_messages && filter_messages == hwnd)
2477 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2478 todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2481 if (expect_messages)
2483 HWND w;
2485 switch (expect_messages->window)
2487 case DEVICE_WINDOW:
2488 w = device_window;
2489 break;
2491 case FOCUS_WINDOW:
2492 w = focus_window;
2493 break;
2495 default:
2496 w = NULL;
2497 break;
2500 if (hwnd == w && expect_messages->message == message)
2502 if (expect_messages->check_wparam)
2503 ok(wparam == expect_messages->expect_wparam,
2504 "Got unexpected wparam %lx for message %x, expected %lx.\n",
2505 wparam, message, expect_messages->expect_wparam);
2507 if (expect_messages->store_wp)
2508 *expect_messages->store_wp = *(WINDOWPOS *)lparam;
2510 if (focus_test_device)
2512 hr = IDirect3DDevice8_TestCooperativeLevel(focus_test_device);
2513 /* Wined3d marks the device lost earlier than Windows (it follows ddraw
2514 * behavior. See test_wndproc before the focus_loss_messages sequence
2515 * about the D3DERR_DEVICENOTRESET behavior, */
2516 todo_wine_if(message != WM_ACTIVATEAPP || hr == D3D_OK)
2517 ok(hr == expect_messages->device_state,
2518 "Got device state %#x on message %#x, expected %#x.\n",
2519 hr, message, expect_messages->device_state);
2522 ++expect_messages;
2526 /* KDE randomly does something with the hidden window during the
2527 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
2528 * message. A WM_WINDOWPOSCHANGED message is not generated, so
2529 * just flag WM_WINDOWPOSCHANGED as bad. */
2530 if (message == WM_WINDOWPOSCHANGED)
2531 InterlockedIncrement(&windowposchanged_received);
2532 else if (message == WM_SYSCOMMAND)
2533 InterlockedIncrement(&syscommand_received);
2535 return DefWindowProcA(hwnd, message, wparam, lparam);
2538 static DWORD WINAPI wndproc_thread(void *param)
2540 struct wndproc_thread_param *p = param;
2541 DWORD res;
2542 BOOL ret;
2544 p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2545 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
2546 registry_mode.dmPelsHeight, 0, 0, 0, 0);
2547 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2549 ret = SetEvent(p->window_created);
2550 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2552 for (;;)
2554 MSG msg;
2556 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2557 res = WaitForSingleObject(p->test_finished, 100);
2558 if (res == WAIT_OBJECT_0) break;
2559 if (res != WAIT_TIMEOUT)
2561 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2562 break;
2566 DestroyWindow(p->dummy_window);
2568 return 0;
2571 static void test_wndproc(void)
2573 struct wndproc_thread_param thread_params;
2574 struct device_desc device_desc;
2575 IDirect3DDevice8 *device;
2576 WNDCLASSA wc = {0};
2577 IDirect3D8 *d3d8;
2578 HANDLE thread;
2579 LONG_PTR proc;
2580 ULONG ref;
2581 DWORD res, tid;
2582 HWND tmp;
2583 UINT i, adapter_mode_count;
2584 HRESULT hr;
2585 D3DDISPLAYMODE d3ddm;
2586 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
2587 DEVMODEW devmode;
2588 LONG change_ret, device_style;
2589 BOOL ret;
2590 WINDOWPOS windowpos;
2592 static const struct message create_messages[] =
2594 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2595 /* Do not test wparam here. If device creation succeeds,
2596 * wparam is WA_ACTIVE. If device creation fails (testbot)
2597 * wparam is set to WA_INACTIVE on some Windows versions. */
2598 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
2599 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
2600 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2601 {WM_MOVE, DEVICE_WINDOW, FALSE, 0},
2602 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
2603 {0, 0, FALSE, 0},
2605 static const struct message focus_loss_messages[] =
2607 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
2608 * not reliable on X11 WMs. When the window focus follows the
2609 * mouse pointer the message is not sent.
2610 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
2611 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
2612 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2613 * not deterministic. */
2614 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
2615 /* Windows sends WM_ACTIVATE to the device window, indicating that
2616 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
2617 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
2618 * leaves the device window active, breaking re-activation in the
2619 * lost device test.
2620 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
2621 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
2622 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED,
2623 D3DERR_DEVICENOTRESET},
2624 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, D3DERR_DEVICELOST},
2625 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
2626 * not deterministic. It may be sent after the focus window handling
2627 * or before. */
2628 {0, 0, FALSE, 0, 0},
2630 static const struct message reactivate_messages[] =
2632 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2633 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2634 {WM_MOVE, DEVICE_WINDOW, FALSE, 0},
2635 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
2636 {0, 0, FALSE, 0},
2638 static const struct message focus_loss_messages_hidden[] =
2640 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2641 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2642 {0, 0, FALSE, 0},
2644 static const struct message focus_loss_messages_filtered[] =
2646 /* WM_ACTIVATE is delivered to the window proc because it is
2647 * generated by SetForegroundWindow before the d3d routine
2648 * starts it work. Don't check for it due to focus-follows-mouse
2649 * WMs though. */
2650 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
2651 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2652 {0, 0, FALSE, 0},
2654 static const struct message reactivate_messages_filtered[] =
2656 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
2657 {0, 0, FALSE, 0},
2659 static const struct message sc_restore_messages[] =
2661 /* WM_SYSCOMMAND is delivered only once, after d3d has already
2662 * processed it. Our wndproc has no way to prevent d3d from
2663 * handling the message. The second DefWindowProc call done by
2664 * our wndproc doesn't do any changes to the window because it
2665 * is already restored due to d3d's handling. */
2666 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2667 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2668 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
2669 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
2670 {0, 0, FALSE, 0},
2672 static const struct message sc_minimize_messages[] =
2674 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
2675 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2676 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2677 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2678 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
2679 {0, 0, FALSE, 0},
2681 static const struct message sc_maximize_messages[] =
2683 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
2684 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2685 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2686 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2687 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MAXIMIZED},
2688 {0, 0, FALSE, 0},
2690 struct message mode_change_messages[] =
2692 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2693 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2694 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
2695 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2696 * differs between Wine and Windows. */
2697 /* TODO 2: Windows sends a second WM_WINDOWPOSCHANGING(SWP_NOMOVE | SWP_NOSIZE
2698 * | SWP_NOACTIVATE) in this situation, suggesting a difference in their ShowWindow
2699 * implementation. This SetWindowPos call could in theory affect the Z order. Wine's
2700 * ShowWindow does not send such a message because the window is already visible. */
2701 {0, 0, FALSE, 0},
2703 struct message mode_change_messages_hidden[] =
2705 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2706 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2707 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
2708 {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0},
2709 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, ~0U, &windowpos},
2710 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2711 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2712 * differs between Wine and Windows. */
2713 {0, 0, FALSE, 0},
2716 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2717 ok(!!d3d8, "Failed to create a D3D object.\n");
2719 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
2720 for (i = 0; i < adapter_mode_count; ++i)
2722 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm);
2723 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2725 if (d3ddm.Format != D3DFMT_X8R8G8B8)
2726 continue;
2727 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
2728 continue;
2729 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
2730 * refuses to create a device at these sizes. */
2731 if (d3ddm.Width < 640 || d3ddm.Height < 480)
2732 continue;
2734 if (!user32_width)
2736 user32_width = d3ddm.Width;
2737 user32_height = d3ddm.Height;
2738 continue;
2741 /* Make sure the d3d mode is smaller in width or height and at most
2742 * equal in the other dimension than the mode passed to
2743 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
2744 * the ChangeDisplaySettings parameters + 12. */
2745 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
2746 continue;
2747 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
2749 d3d_width = d3ddm.Width;
2750 d3d_height = d3ddm.Height;
2751 break;
2753 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
2755 d3d_width = user32_width;
2756 d3d_height = user32_height;
2757 user32_width = d3ddm.Width;
2758 user32_height = d3ddm.Height;
2759 break;
2763 if (!d3d_width)
2765 skip("Could not find adequate modes, skipping mode tests.\n");
2766 IDirect3D8_Release(d3d8);
2767 return;
2770 wc.lpfnWndProc = test_proc;
2771 wc.lpszClassName = "d3d8_test_wndproc_wc";
2772 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2774 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
2775 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2776 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
2777 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2779 memset(&devmode, 0, sizeof(devmode));
2780 devmode.dmSize = sizeof(devmode);
2781 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2782 devmode.dmPelsWidth = user32_width;
2783 devmode.dmPelsHeight = user32_height;
2784 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2785 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2787 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2788 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2789 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2790 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2791 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2792 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2794 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2795 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2797 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2798 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2799 (LONG_PTR)test_proc, proc);
2800 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2801 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2802 (LONG_PTR)test_proc, proc);
2804 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2805 device_window, focus_window, thread_params.dummy_window);
2807 tmp = GetFocus();
2808 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2809 if (thread_params.running_in_foreground)
2811 tmp = GetForegroundWindow();
2812 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2813 thread_params.dummy_window, tmp);
2815 else
2816 skip("Not running in foreground, skip foreground window test\n");
2818 flush_events();
2820 expect_messages = create_messages;
2822 device_desc.device_window = device_window;
2823 device_desc.width = d3d_width;
2824 device_desc.height = d3d_height;
2825 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
2826 if (!(device = create_device(d3d8, focus_window, &device_desc)))
2828 skip("Failed to create a D3D device, skipping tests.\n");
2829 goto done;
2832 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2833 expect_messages->message, expect_messages->window);
2834 expect_messages = NULL;
2836 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2838 tmp = GetFocus();
2839 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2840 tmp = GetForegroundWindow();
2841 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2843 SetForegroundWindow(focus_window);
2844 flush_events();
2846 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2847 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2848 (LONG_PTR)test_proc, proc);
2850 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2851 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
2853 /* Change the mode while the device is in use and then drop focus. */
2854 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2855 devmode.dmPelsWidth = user32_width;
2856 devmode.dmPelsHeight = user32_height;
2857 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2858 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
2860 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
2861 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
2862 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
2863 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2864 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
2865 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
2867 expect_messages = focus_loss_messages;
2868 focus_test_device = device;
2869 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
2870 * manually changing the focus. It generates the same messages, but the task
2871 * bar still shows the previous foreground window as active, and the window has
2872 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
2873 * the device is difficult, see below. */
2874 SetForegroundWindow(GetDesktopWindow());
2875 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2876 expect_messages->message, expect_messages->window);
2877 expect_messages = NULL;
2878 tmp = GetFocus();
2879 ok(tmp != device_window, "The device window is active.\n");
2880 ok(tmp != focus_window, "The focus window is active.\n");
2881 focus_test_device = NULL;
2883 /* The Present call is necessary to make native realize the device is lost. */
2884 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2885 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
2886 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2887 /* Focus-follows-mouse WMs prematurely reactivate our window. */
2888 todo_wine_if (hr == D3DERR_DEVICENOTRESET)
2889 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
2891 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2892 ok(ret, "Failed to get display mode.\n");
2893 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2894 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2895 devmode.dmPelsWidth, devmode.dmPelsHeight);
2897 /* I have to minimize and restore the focus window, otherwise native d3d8 fails
2898 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
2899 * restore is triggered by the user. */
2900 expect_messages = reactivate_messages;
2901 ShowWindow(focus_window, SW_MINIMIZE);
2902 ShowWindow(focus_window, SW_RESTORE);
2903 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
2904 SetForegroundWindow(focus_window);
2905 flush_events();
2906 SetForegroundWindow(focus_window);
2907 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
2908 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2909 expect_messages->message, expect_messages->window, i);
2910 expect_messages = NULL;
2912 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2913 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
2915 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2916 ok(ret, "Failed to get display mode.\n");
2917 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2918 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2919 devmode.dmPelsWidth, devmode.dmPelsHeight);
2921 hr = reset_device(device, &device_desc);
2922 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2924 /* Remove the WS_VISIBLE flag to test hidden windows. This is enough to trigger d3d's hidden
2925 * window codepath, but does not actually hide the window without a SetWindowPos(SWP_FRAMECHANGED)
2926 * call. This way we avoid focus changes and random failures on focus follows mouse WMs. */
2927 device_style = GetWindowLongA(device_window, GWL_STYLE);
2928 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
2929 flush_events();
2931 expect_messages = focus_loss_messages_hidden;
2932 windowposchanged_received = 0;
2933 SetForegroundWindow(GetDesktopWindow());
2934 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2935 expect_messages->message, expect_messages->window);
2936 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
2937 expect_messages = NULL;
2938 flush_events();
2940 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2941 ok(ret, "Failed to get display mode.\n");
2942 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
2943 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
2945 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
2946 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
2947 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
2948 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
2949 flush_events();
2951 syscommand_received = 0;
2952 expect_messages = sc_restore_messages;
2953 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
2954 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2955 expect_messages->message, expect_messages->window);
2956 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
2957 expect_messages = NULL;
2958 flush_events();
2960 expect_messages = sc_minimize_messages;
2961 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2962 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2963 expect_messages->message, expect_messages->window);
2964 expect_messages = NULL;
2965 flush_events();
2967 expect_messages = sc_maximize_messages;
2968 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2969 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2970 expect_messages->message, expect_messages->window);
2971 expect_messages = NULL;
2972 flush_events();
2974 SetForegroundWindow(GetDesktopWindow());
2975 ShowWindow(device_window, SW_MINIMIZE);
2976 ShowWindow(focus_window, SW_MINIMIZE);
2977 ShowWindow(focus_window, SW_RESTORE);
2978 SetForegroundWindow(focus_window);
2979 flush_events();
2981 /* Releasing a device in lost state breaks follow-up tests on native. */
2982 hr = reset_device(device, &device_desc);
2983 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2985 filter_messages = focus_window;
2986 ref = IDirect3DDevice8_Release(device);
2987 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2989 /* Fix up the mode until Wine's device release behavior is fixed. */
2990 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2991 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2993 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2994 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2995 (LONG_PTR)test_proc, proc);
2997 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
2998 * on native in the test below. It isn't needed anyways. Creating the third
2999 * device will show it again. */
3000 filter_messages = NULL;
3001 ShowWindow(device_window, SW_HIDE);
3002 /* Remove the maximized state from the SYSCOMMAND test while we're not
3003 * interfering with a device. */
3004 ShowWindow(focus_window, SW_SHOWNORMAL);
3005 filter_messages = focus_window;
3007 device_desc.device_window = focus_window;
3008 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3010 skip("Failed to create a D3D device, skipping tests.\n");
3011 goto done;
3014 filter_messages = NULL;
3016 expect_messages = focus_loss_messages_filtered;
3017 windowposchanged_received = 0;
3018 SetForegroundWindow(GetDesktopWindow());
3019 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3020 expect_messages->message, expect_messages->window);
3021 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3022 expect_messages = NULL;
3024 /* The window is iconic even though no message was sent. */
3025 ok(IsIconic(focus_window), "The focus window is not iconic.\n");
3027 hr = IDirect3DDevice8_TestCooperativeLevel(device);
3028 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3030 syscommand_received = 0;
3031 expect_messages = sc_restore_messages;
3032 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3033 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3034 expect_messages->message, expect_messages->window);
3035 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3036 expect_messages = NULL;
3037 flush_events();
3039 /* For FVWM. */
3040 ShowWindow(focus_window, SW_RESTORE);
3041 flush_events();
3043 expect_messages = sc_minimize_messages;
3044 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3045 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3046 expect_messages->message, expect_messages->window);
3047 expect_messages = NULL;
3048 /* Needed to make the next test reliably send WM_SIZE(SIZE_MAXIMIZED). Without
3049 * this call it sends WM_SIZE(SIZE_RESTORED). */
3050 ShowWindow(focus_window, SW_RESTORE);
3051 flush_events();
3053 expect_messages = sc_maximize_messages;
3054 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3055 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3056 expect_messages->message, expect_messages->window);
3057 expect_messages = NULL;
3058 SetForegroundWindow(GetDesktopWindow());
3059 flush_events();
3061 /* ShowWindow(SW_RESTORE); SetForegroundWindow(desktop); SetForegroundWindow(focus);
3062 * results in the second SetForegroundWindow call failing and the device not being
3063 * restored on native. Directly using ShowWindow(SW_RESTORE) works, but it means
3064 * we cannot test for the absence of WM_WINDOWPOSCHANGED messages. */
3065 expect_messages = reactivate_messages_filtered;
3066 ShowWindow(focus_window, SW_RESTORE);
3067 SetForegroundWindow(focus_window);
3068 flush_events();
3069 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it\n",
3070 expect_messages->message, expect_messages->window);
3071 expect_messages = NULL;
3073 filter_messages = focus_window;
3074 hr = IDirect3DDevice8_TestCooperativeLevel(device);
3075 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3077 hr = reset_device(device, &device_desc);
3078 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3080 ref = IDirect3DDevice8_Release(device);
3081 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3082 filter_messages = NULL;
3084 ShowWindow(device_window, SW_RESTORE);
3085 SetForegroundWindow(focus_window);
3086 flush_events();
3088 filter_messages = focus_window;
3089 device_desc.device_window = device_window;
3090 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3092 skip("Failed to create a D3D device, skipping tests.\n");
3093 goto done;
3095 filter_messages = NULL;
3096 flush_events();
3098 device_desc.width = user32_width;
3099 device_desc.height = user32_height;
3101 expect_messages = mode_change_messages;
3102 filter_messages = focus_window;
3103 hr = reset_device(device, &device_desc);
3104 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3105 filter_messages = NULL;
3107 flush_events();
3108 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3109 expect_messages->message, expect_messages->window, i);
3111 /* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
3112 device_style = GetWindowLongA(device_window, GWL_STYLE);
3113 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3115 flush_events();
3116 device_desc.width = d3d_width;
3117 device_desc.height = d3d_height;
3118 memset(&windowpos, 0, sizeof(windowpos));
3120 expect_messages = mode_change_messages_hidden;
3121 filter_messages = focus_window;
3122 hr = reset_device(device, &device_desc);
3123 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3124 filter_messages = NULL;
3126 flush_events();
3127 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3128 expect_messages->message, expect_messages->window);
3130 ok(windowpos.hwnd == device_window && !windowpos.hwndInsertAfter
3131 && !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
3132 && windowpos.flags == (SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE),
3133 "Got unexpected WINDOWPOS hwnd=%p, insertAfter=%p, x=%d, y=%d, cx=%d, cy=%d, flags=%x\n",
3134 windowpos.hwnd, windowpos.hwndInsertAfter, windowpos.x, windowpos.y, windowpos.cx,
3135 windowpos.cy, windowpos.flags);
3137 device_style = GetWindowLongA(device_window, GWL_STYLE);
3138 ok(device_style & WS_VISIBLE, "Expected the device window to be visible.\n");
3140 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3141 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3143 ref = IDirect3DDevice8_Release(device);
3144 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3146 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3147 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3148 (LONG_PTR)DefWindowProcA, proc);
3150 done:
3151 filter_messages = NULL;
3152 IDirect3D8_Release(d3d8);
3154 SetEvent(thread_params.test_finished);
3155 WaitForSingleObject(thread, INFINITE);
3156 CloseHandle(thread_params.test_finished);
3157 CloseHandle(thread_params.window_created);
3158 CloseHandle(thread);
3160 DestroyWindow(device_window);
3161 DestroyWindow(focus_window);
3162 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3165 static void test_wndproc_windowed(void)
3167 struct wndproc_thread_param thread_params;
3168 struct device_desc device_desc;
3169 IDirect3DDevice8 *device;
3170 WNDCLASSA wc = {0};
3171 IDirect3D8 *d3d8;
3172 HANDLE thread;
3173 LONG_PTR proc;
3174 HRESULT hr;
3175 ULONG ref;
3176 DWORD res, tid;
3177 HWND tmp;
3179 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3180 ok(!!d3d8, "Failed to create a D3D object.\n");
3182 wc.lpfnWndProc = test_proc;
3183 wc.lpszClassName = "d3d8_test_wndproc_wc";
3184 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3186 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3187 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3188 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3189 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3191 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3192 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3193 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3194 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3195 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3196 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3197 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3198 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3200 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3201 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3203 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3204 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3205 (LONG_PTR)test_proc, proc);
3206 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3207 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3208 (LONG_PTR)test_proc, proc);
3210 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3211 device_window, focus_window, thread_params.dummy_window);
3213 tmp = GetFocus();
3214 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3215 if (thread_params.running_in_foreground)
3217 tmp = GetForegroundWindow();
3218 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3219 thread_params.dummy_window, tmp);
3221 else
3222 skip("Not running in foreground, skip foreground window test\n");
3224 filter_messages = focus_window;
3226 device_desc.device_window = device_window;
3227 device_desc.width = registry_mode.dmPelsWidth;
3228 device_desc.height = registry_mode.dmPelsHeight;
3229 device_desc.flags = 0;
3230 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3232 skip("Failed to create a D3D device, skipping tests.\n");
3233 goto done;
3236 tmp = GetFocus();
3237 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3238 tmp = GetForegroundWindow();
3239 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3240 thread_params.dummy_window, tmp);
3242 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3243 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3244 (LONG_PTR)test_proc, proc);
3246 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3247 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3248 (LONG_PTR)test_proc, proc);
3250 filter_messages = NULL;
3252 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3253 hr = reset_device(device, &device_desc);
3254 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3256 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3257 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3258 (LONG_PTR)test_proc, proc);
3260 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3261 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3263 device_desc.flags = 0;
3264 hr = reset_device(device, &device_desc);
3265 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3267 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3268 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3269 (LONG_PTR)test_proc, proc);
3271 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3272 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3273 (LONG_PTR)test_proc, proc);
3275 filter_messages = focus_window;
3277 ref = IDirect3DDevice8_Release(device);
3278 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3280 filter_messages = device_window;
3282 device_desc.device_window = focus_window;
3283 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3285 skip("Failed to create a D3D device, skipping tests.\n");
3286 goto done;
3289 filter_messages = NULL;
3291 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3292 hr = reset_device(device, &device_desc);
3293 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3295 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3296 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3297 (LONG_PTR)test_proc, proc);
3299 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3300 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3302 device_desc.flags = 0;
3303 hr = reset_device(device, &device_desc);
3304 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3306 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3307 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3308 (LONG_PTR)test_proc, proc);
3310 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3311 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3312 (LONG_PTR)test_proc, proc);
3314 filter_messages = device_window;
3316 ref = IDirect3DDevice8_Release(device);
3317 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3319 device_desc.device_window = device_window;
3320 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3322 skip("Failed to create a D3D device, skipping tests.\n");
3323 goto done;
3326 filter_messages = NULL;
3328 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3329 hr = reset_device(device, &device_desc);
3330 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3332 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3333 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3334 (LONG_PTR)test_proc, proc);
3336 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3337 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3339 device_desc.flags = 0;
3340 hr = reset_device(device, &device_desc);
3341 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3343 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3344 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3345 (LONG_PTR)test_proc, proc);
3347 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3348 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3349 (LONG_PTR)test_proc, proc);
3351 filter_messages = device_window;
3353 ref = IDirect3DDevice8_Release(device);
3354 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3356 done:
3357 filter_messages = NULL;
3358 IDirect3D8_Release(d3d8);
3360 SetEvent(thread_params.test_finished);
3361 WaitForSingleObject(thread, INFINITE);
3362 CloseHandle(thread_params.test_finished);
3363 CloseHandle(thread_params.window_created);
3364 CloseHandle(thread);
3366 DestroyWindow(device_window);
3367 DestroyWindow(focus_window);
3368 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3371 static inline void set_fpu_cw(WORD cw)
3373 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3374 #define D3D8_TEST_SET_FPU_CW 1
3375 __asm__ volatile ("fnclex");
3376 __asm__ volatile ("fldcw %0" : : "m" (cw));
3377 #elif defined(__i386__) && defined(_MSC_VER)
3378 #define D3D8_TEST_SET_FPU_CW 1
3379 __asm fnclex;
3380 __asm fldcw cw;
3381 #endif
3384 static inline WORD get_fpu_cw(void)
3386 WORD cw = 0;
3387 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3388 #define D3D8_TEST_GET_FPU_CW 1
3389 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3390 #elif defined(__i386__) && defined(_MSC_VER)
3391 #define D3D8_TEST_GET_FPU_CW 1
3392 __asm fnstcw cw;
3393 #endif
3394 return cw;
3397 static WORD callback_cw, callback_set_cw;
3398 static DWORD callback_tid;
3400 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
3402 *out = NULL;
3403 return E_NOINTERFACE;
3406 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
3408 callback_cw = get_fpu_cw();
3409 set_fpu_cw(callback_set_cw);
3410 callback_tid = GetCurrentThreadId();
3411 return 2;
3414 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
3416 callback_cw = get_fpu_cw();
3417 set_fpu_cw(callback_set_cw);
3418 callback_tid = GetCurrentThreadId();
3419 return 1;
3422 static const IUnknownVtbl dummy_object_vtbl =
3424 dummy_object_QueryInterface,
3425 dummy_object_AddRef,
3426 dummy_object_Release,
3429 static const GUID d3d8_private_data_test_guid =
3431 0xfdb37466,
3432 0x428f,
3433 0x4edf,
3434 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
3437 static void test_fpu_setup(void)
3439 #if defined(D3D8_TEST_SET_FPU_CW) && defined(D3D8_TEST_GET_FPU_CW)
3440 struct device_desc device_desc;
3441 IDirect3DDevice8 *device;
3442 D3DDISPLAYMODE d3ddm;
3443 IDirect3D8 *d3d8;
3444 HWND window;
3445 HRESULT hr;
3446 WORD cw;
3447 IDirect3DSurface8 *surface;
3448 IUnknown dummy_object = {&dummy_object_vtbl};
3450 window = create_window();
3451 ok(!!window, "Failed to create a window.\n");
3452 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3453 ok(!!d3d8, "Failed to create a D3D object.\n");
3455 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
3456 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
3458 device_desc.device_window = window;
3459 device_desc.width = 640;
3460 device_desc.height = 480;
3461 device_desc.flags = 0;
3463 set_fpu_cw(0xf60);
3464 cw = get_fpu_cw();
3465 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3467 if (!(device = create_device(d3d8, window, &device_desc)))
3469 skip("Failed to create a 3D device, skipping test.\n");
3470 set_fpu_cw(0x37f);
3471 goto done;
3474 cw = get_fpu_cw();
3475 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3477 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3478 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3480 callback_set_cw = 0xf60;
3481 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3482 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3483 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
3484 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
3485 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3486 cw = get_fpu_cw();
3487 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3489 callback_cw = 0;
3490 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3491 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3492 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
3493 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
3494 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3496 callback_set_cw = 0x7f;
3497 set_fpu_cw(0x7f);
3499 IDirect3DSurface8_Release(surface);
3501 callback_cw = 0;
3502 IDirect3DDevice8_Release(device);
3503 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
3504 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3506 cw = get_fpu_cw();
3507 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3508 set_fpu_cw(0xf60);
3509 cw = get_fpu_cw();
3510 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3512 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
3513 device = create_device(d3d8, window, &device_desc);
3514 ok(!!device, "CreateDevice failed.\n");
3516 cw = get_fpu_cw();
3517 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3519 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3520 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3522 callback_cw = 0;
3523 callback_set_cw = 0x37f;
3524 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3525 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3526 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
3527 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
3528 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3529 cw = get_fpu_cw();
3530 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
3532 IDirect3DSurface8_Release(surface);
3534 callback_cw = 0;
3535 IDirect3DDevice8_Release(device);
3536 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0x37f.\n", callback_cw);
3537 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3539 done:
3540 DestroyWindow(window);
3541 IDirect3D8_Release(d3d8);
3542 #endif
3545 static void test_ApplyStateBlock(void)
3547 IDirect3DDevice8 *device;
3548 IDirect3D8 *d3d8;
3549 HWND window;
3550 HRESULT hr;
3551 DWORD received, token;
3553 window = create_window();
3554 ok(!!window, "Failed to create a window.\n");
3555 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3556 ok(!!d3d8, "Failed to create a D3D object.\n");
3557 if (!(device = create_device(d3d8, window, NULL)))
3559 skip("Failed to create a 3D device, skipping test.\n");
3560 goto cleanup;
3563 IDirect3DDevice8_BeginStateBlock(device);
3564 IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
3565 IDirect3DDevice8_EndStateBlock(device, &token);
3566 ok(token, "Received zero stateblock handle.\n");
3567 IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
3569 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3570 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3571 ok(!received, "Expected = FALSE, received TRUE.\n");
3573 hr = IDirect3DDevice8_ApplyStateBlock(device, 0);
3574 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3575 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3576 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3577 ok(!received, "Expected FALSE, received TRUE.\n");
3579 hr = IDirect3DDevice8_ApplyStateBlock(device, token);
3580 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3581 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3582 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3583 ok(received, "Expected TRUE, received FALSE.\n");
3585 IDirect3DDevice8_DeleteStateBlock(device, token);
3586 IDirect3DDevice8_Release(device);
3587 cleanup:
3588 IDirect3D8_Release(d3d8);
3589 DestroyWindow(window);
3592 static void test_depth_stencil_size(void)
3594 IDirect3DDevice8 *device;
3595 IDirect3DSurface8 *ds, *rt, *ds_bigger, *ds_bigger2;
3596 IDirect3DSurface8 *surf;
3597 IDirect3D8 *d3d8;
3598 HRESULT hr;
3599 HWND hwnd;
3601 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3602 100, 100, 160, 160, NULL, NULL, NULL, NULL);
3603 ok(!!hwnd, "Failed to create a window.\n");
3604 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3605 ok(!!d3d8, "Failed to create a D3D object.\n");
3607 if (!(device = create_device(d3d8, hwnd, NULL)))
3609 skip("Failed to create a 3D device, skipping test.\n");
3610 goto cleanup;
3613 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
3614 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateRenderTarget failed, hr %#x.\n", hr);
3615 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds);
3616 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
3617 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger);
3618 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
3619 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger2);
3620 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
3622 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
3623 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
3624 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds_bigger);
3625 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
3627 /* try to set the small ds without changing the render target at the same time */
3628 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds);
3629 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
3630 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds_bigger2);
3631 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
3633 hr = IDirect3DDevice8_GetRenderTarget(device, &surf);
3634 ok(hr == D3D_OK, "IDirect3DDevice8_GetRenderTarget failed, hr %#x.\n", hr);
3635 ok(surf == rt, "The render target is %p, expected %p\n", surf, rt);
3636 IDirect3DSurface8_Release(surf);
3637 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
3638 ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr %#x.\n", hr);
3639 ok(surf == ds_bigger2, "The depth stencil is %p, expected %p\n", surf, ds_bigger2);
3640 IDirect3DSurface8_Release(surf);
3642 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
3643 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
3644 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
3645 ok(FAILED(hr), "IDirect3DDevice8_GetDepthStencilSurface should have failed, hr %#x.\n", hr);
3646 ok(surf == NULL, "The depth stencil is %p, expected NULL\n", surf);
3647 if (surf) IDirect3DSurface8_Release(surf);
3649 IDirect3DSurface8_Release(rt);
3650 IDirect3DSurface8_Release(ds);
3651 IDirect3DSurface8_Release(ds_bigger);
3652 IDirect3DSurface8_Release(ds_bigger2);
3654 cleanup:
3655 IDirect3D8_Release(d3d8);
3656 DestroyWindow(hwnd);
3659 static void test_window_style(void)
3661 RECT focus_rect, fullscreen_rect, r;
3662 LONG device_style, device_exstyle;
3663 LONG focus_style, focus_exstyle;
3664 struct device_desc device_desc;
3665 LONG style, expected_style;
3666 IDirect3DDevice8 *device;
3667 IDirect3D8 *d3d8;
3668 HRESULT hr;
3669 ULONG ref;
3670 BOOL ret;
3672 focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3673 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3674 device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3675 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3676 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3677 ok(!!d3d8, "Failed to create a D3D object.\n");
3679 device_style = GetWindowLongA(device_window, GWL_STYLE);
3680 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3681 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3682 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3684 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3685 GetWindowRect(focus_window, &focus_rect);
3687 device_desc.device_window = device_window;
3688 device_desc.width = registry_mode.dmPelsWidth;
3689 device_desc.height = registry_mode.dmPelsHeight;
3690 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3691 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3693 skip("Failed to create a D3D device, skipping tests.\n");
3694 goto done;
3697 style = GetWindowLongA(device_window, GWL_STYLE);
3698 expected_style = device_style | WS_VISIBLE;
3699 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3700 expected_style, style);
3701 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3702 expected_style = device_exstyle | WS_EX_TOPMOST;
3703 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3704 expected_style, style);
3706 style = GetWindowLongA(focus_window, GWL_STYLE);
3707 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3708 focus_style, style);
3709 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3710 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3711 focus_exstyle, style);
3713 GetWindowRect(device_window, &r);
3714 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
3715 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
3716 GetClientRect(device_window, &r);
3717 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3718 GetWindowRect(focus_window, &r);
3719 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&focus_rect),
3720 wine_dbgstr_rect(&r));
3722 device_desc.flags = 0;
3723 hr = reset_device(device, &device_desc);
3724 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3726 style = GetWindowLongA(device_window, GWL_STYLE);
3727 expected_style = device_style | WS_VISIBLE;
3728 ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3729 expected_style, style);
3730 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3731 expected_style = device_exstyle | WS_EX_TOPMOST;
3732 ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3733 expected_style, style);
3735 style = GetWindowLongA(focus_window, GWL_STYLE);
3736 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3737 focus_style, style);
3738 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3739 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3740 focus_exstyle, style);
3742 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3743 hr = reset_device(device, &device_desc);
3744 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3745 ret = SetForegroundWindow(GetDesktopWindow());
3746 ok(ret, "Failed to set foreground window.\n");
3748 style = GetWindowLongA(device_window, GWL_STYLE);
3749 expected_style = device_style | WS_MINIMIZE | WS_VISIBLE;
3750 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3751 expected_style, style);
3752 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3753 expected_style = device_exstyle | WS_EX_TOPMOST;
3754 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3755 expected_style, style);
3757 style = GetWindowLongA(focus_window, GWL_STYLE);
3758 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3759 focus_style, style);
3760 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3761 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3762 focus_exstyle, style);
3764 /* Follow-up tests fail on native if the device is destroyed while lost. */
3765 ShowWindow(focus_window, SW_MINIMIZE);
3766 ShowWindow(focus_window, SW_RESTORE);
3767 ret = SetForegroundWindow(focus_window);
3768 ok(ret, "Failed to set foreground window.\n");
3769 flush_events();
3770 hr = reset_device(device, &device_desc);
3771 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3773 ref = IDirect3DDevice8_Release(device);
3774 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3776 done:
3777 IDirect3D8_Release(d3d8);
3779 DestroyWindow(device_window);
3780 DestroyWindow(focus_window);
3783 static void test_unsupported_shaders(void)
3785 IDirect3DDevice8 *device;
3786 IDirect3D8 *d3d;
3787 ULONG refcount;
3788 DWORD vs, ps;
3789 HWND window;
3790 HRESULT hr;
3791 D3DCAPS8 caps;
3793 static const DWORD vs_2_0[] =
3795 0xfffe0200, /* vs_2_0 */
3796 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
3797 0x02000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
3798 0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002, /* add oD0, r1, c2 */
3799 0x02000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
3800 0x0000ffff /* end */
3802 static const DWORD ps_2_0[] =
3804 0xffff0200, /* ps_2_0 */
3805 0x02000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
3806 0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002, /* add r0, r1, c2 */
3807 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */
3808 0x0000ffff /* end */
3810 #if 0
3811 vs_1_1
3812 dcl_position v0
3813 def c255, 1.0, 1.0, 1.0, 1.0
3814 add r0, v0, c255
3815 mov oPos, r0
3816 #endif
3817 static const DWORD vs_1_255[] =
3819 0xfffe0101,
3820 0x0000001f, 0x80000000, 0x900f0000,
3821 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
3822 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
3823 0x00000001, 0xc00f0000, 0x80e40000,
3824 0x0000ffff
3826 #if 0
3827 vs_1_1
3828 dcl_position v0
3829 def c256, 1.0, 1.0, 1.0, 1.0
3830 add r0, v0, c256
3831 mov oPos, r0
3832 #endif
3833 static const DWORD vs_1_256[] =
3835 0xfffe0101,
3836 0x0000001f, 0x80000000, 0x900f0000,
3837 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
3838 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
3839 0x00000001, 0xc00f0000, 0x80e40000,
3840 0x0000ffff
3843 static const DWORD decl[] =
3845 D3DVSD_STREAM(0),
3846 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
3847 D3DVSD_END()
3850 window = create_window();
3851 ok(!!window, "Failed to create a window.\n");
3852 d3d = Direct3DCreate8(D3D_SDK_VERSION);
3853 ok(!!d3d, "Failed to create a D3D object.\n");
3854 if (!(device = create_device(d3d, window, NULL)))
3856 skip("Failed to create a D3D device, skipping tests.\n");
3857 IDirect3D8_Release(d3d);
3858 DestroyWindow(window);
3859 return;
3862 hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_ps, &vs, 0);
3863 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
3865 hr = IDirect3DDevice8_CreatePixelShader(device, simple_vs, &ps);
3866 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
3868 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_2_0, &vs, 0);
3869 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
3871 hr = IDirect3DDevice8_CreatePixelShader(device, ps_2_0, &ps);
3872 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
3874 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3875 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3876 if (caps.MaxVertexShaderConst < 256)
3878 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_255, &vs, 0);
3879 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3881 else
3883 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_255, &vs, 0);
3884 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3885 hr = IDirect3DDevice8_DeleteVertexShader(device, vs);
3886 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
3887 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_256, &vs, 0);
3888 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3891 refcount = IDirect3DDevice8_Release(device);
3892 ok(!refcount, "Device has %u references left.\n", refcount);
3893 IDirect3D8_Release(d3d);
3894 DestroyWindow(window);
3897 static void test_mode_change(void)
3899 RECT d3d_rect, focus_rect, r;
3900 struct device_desc device_desc;
3901 IDirect3DSurface8 *backbuffer;
3902 IDirect3DDevice8 *device;
3903 D3DSURFACE_DESC desc;
3904 IDirect3D8 *d3d8;
3905 DEVMODEW devmode;
3906 ULONG refcount;
3907 UINT adapter_mode_count, i;
3908 HRESULT hr;
3909 BOOL ret;
3910 LONG change_ret;
3911 D3DDISPLAYMODE d3ddm;
3912 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3914 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3915 ok(!!d3d8, "Failed to create a D3D object.\n");
3917 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
3918 for (i = 0; i < adapter_mode_count; ++i)
3920 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm);
3921 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3923 if (d3ddm.Format != D3DFMT_X8R8G8B8)
3924 continue;
3925 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3926 continue;
3927 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3928 * refuses to create a device at these sizes. */
3929 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3930 continue;
3932 if (!user32_width)
3934 user32_width = d3ddm.Width;
3935 user32_height = d3ddm.Height;
3936 continue;
3939 /* Make sure the d3d mode is smaller in width or height and at most
3940 * equal in the other dimension than the mode passed to
3941 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3942 * the ChangeDisplaySettings parameters + 12. */
3943 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3944 continue;
3945 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3947 d3d_width = d3ddm.Width;
3948 d3d_height = d3ddm.Height;
3949 break;
3951 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3953 d3d_width = user32_width;
3954 d3d_height = user32_height;
3955 user32_width = d3ddm.Width;
3956 user32_height = d3ddm.Height;
3957 break;
3961 if (!d3d_width)
3963 skip("Could not find adequate modes, skipping mode tests.\n");
3964 IDirect3D8_Release(d3d8);
3965 return;
3968 memset(&devmode, 0, sizeof(devmode));
3969 devmode.dmSize = sizeof(devmode);
3970 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3971 devmode.dmPelsWidth = user32_width;
3972 devmode.dmPelsHeight = user32_height;
3973 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3974 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3976 /* Make the windows visible, otherwise device::release does not restore the mode if
3977 * the application is not in foreground like on the testbot. */
3978 focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3979 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
3980 device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3981 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
3983 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
3984 GetWindowRect(focus_window, &focus_rect);
3986 device_desc.device_window = device_window;
3987 device_desc.width = d3d_width;
3988 device_desc.height = d3d_height;
3989 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3990 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3992 skip("Failed to create a D3D device, skipping tests.\n");
3993 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3994 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3995 goto done;
3998 devmode.dmPelsWidth = user32_width;
3999 devmode.dmPelsHeight = user32_height;
4000 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4001 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4003 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4004 ok(ret, "Failed to get display mode.\n");
4005 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4006 "Expected resolution %ux%u, got %ux%u.\n",
4007 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4009 GetWindowRect(device_window, &r);
4010 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&d3d_rect),
4011 wine_dbgstr_rect(&r));
4012 GetWindowRect(focus_window, &r);
4013 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&focus_rect),
4014 wine_dbgstr_rect(&r));
4016 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4017 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
4018 hr = IDirect3DSurface8_GetDesc(backbuffer, &desc);
4019 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
4020 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4021 desc.Width, d3d_width);
4022 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4023 desc.Height, d3d_height);
4024 IDirect3DSurface8_Release(backbuffer);
4026 refcount = IDirect3DDevice8_Release(device);
4027 ok(!refcount, "Device has %u references left.\n", refcount);
4029 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4030 ok(ret, "Failed to get display mode.\n");
4031 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4032 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4033 "Expected resolution %ux%u, got %ux%u.\n",
4034 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4036 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4037 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4039 /* The mode restore also happens when the device was created at the original screen size. */
4041 device_desc.device_window = device_window;
4042 device_desc.width = registry_mode.dmPelsWidth;
4043 device_desc.height = registry_mode.dmPelsHeight;
4044 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4045 ok(!!(device = create_device(d3d8, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4047 devmode.dmPelsWidth = user32_width;
4048 devmode.dmPelsHeight = user32_height;
4049 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4050 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4052 refcount = IDirect3DDevice8_Release(device);
4053 ok(!refcount, "Device has %u references left.\n", refcount);
4055 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4056 ok(ret, "Failed to get display mode.\n");
4057 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4058 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4059 "Expected resolution %ux%u, got %ux%u.\n",
4060 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4062 done:
4063 DestroyWindow(device_window);
4064 DestroyWindow(focus_window);
4065 IDirect3D8_Release(d3d8);
4068 static void test_device_window_reset(void)
4070 RECT fullscreen_rect, device_rect, r;
4071 struct device_desc device_desc;
4072 IDirect3DDevice8 *device;
4073 WNDCLASSA wc = {0};
4074 IDirect3D8 *d3d8;
4075 LONG_PTR proc;
4076 HRESULT hr;
4077 ULONG ref;
4079 wc.lpfnWndProc = test_proc;
4080 wc.lpszClassName = "d3d8_test_wndproc_wc";
4081 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4083 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4084 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4085 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4086 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4087 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4088 ok(!!d3d8, "Failed to create a D3D object.\n");
4090 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4091 GetWindowRect(device_window, &device_rect);
4093 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4094 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4095 (LONG_PTR)test_proc, proc);
4096 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4097 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4098 (LONG_PTR)test_proc, proc);
4100 device_desc.device_window = NULL;
4101 device_desc.width = registry_mode.dmPelsWidth;
4102 device_desc.height = registry_mode.dmPelsHeight;
4103 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4104 if (!(device = create_device(d3d8, focus_window, &device_desc)))
4106 skip("Failed to create a D3D device, skipping tests.\n");
4107 goto done;
4110 GetWindowRect(focus_window, &r);
4111 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4112 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4113 GetWindowRect(device_window, &r);
4114 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&device_rect),
4115 wine_dbgstr_rect(&r));
4117 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4118 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4119 (LONG_PTR)test_proc, proc);
4120 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4121 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4123 device_desc.device_window = device_window;
4124 hr = reset_device(device, &device_desc);
4125 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4127 GetWindowRect(focus_window, &r);
4128 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4129 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4130 GetWindowRect(device_window, &r);
4131 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4132 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4134 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4135 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4136 (LONG_PTR)test_proc, proc);
4137 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4138 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4140 ref = IDirect3DDevice8_Release(device);
4141 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4143 done:
4144 IDirect3D8_Release(d3d8);
4145 DestroyWindow(device_window);
4146 DestroyWindow(focus_window);
4147 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
4150 static void depth_blit_test(void)
4152 IDirect3DDevice8 *device = NULL;
4153 IDirect3DSurface8 *backbuffer, *ds1, *ds2, *ds3;
4154 RECT src_rect;
4155 const POINT dst_point = {0, 0};
4156 IDirect3D8 *d3d8;
4157 HRESULT hr;
4158 HWND hwnd;
4160 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4161 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4162 ok(!!hwnd, "Failed to create a window.\n");
4163 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4164 ok(!!d3d8, "Failed to create a D3D object.\n");
4166 if (!(device = create_device(d3d8, hwnd, NULL)))
4168 skip("Failed to create a D3D device, skipping tests.\n");
4169 goto done;
4172 hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
4173 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
4174 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds1);
4175 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
4176 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds2);
4177 ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
4178 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds3);
4179 ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
4181 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
4182 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
4184 /* Partial blit. */
4185 SetRect(&src_rect, 0, 0, 320, 240);
4186 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4187 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4188 /* Flipped. */
4189 SetRect(&src_rect, 0, 480, 640, 0);
4190 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4191 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4192 /* Full, explicit. */
4193 SetRect(&src_rect, 0, 0, 640, 480);
4194 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4195 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4196 /* Depth -> color blit.*/
4197 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, backbuffer, &dst_point);
4198 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4199 /* Full, NULL rects, current depth stencil -> unbound depth stencil */
4200 hr = IDirect3DDevice8_CopyRects(device, ds1, NULL, 0, ds2, NULL);
4201 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4202 /* Full, NULL rects, unbound depth stencil -> current depth stencil */
4203 hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds1, NULL);
4204 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4205 /* Full, NULL rects, unbound depth stencil -> unbound depth stencil */
4206 hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds3, NULL);
4207 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4209 IDirect3DSurface8_Release(backbuffer);
4210 IDirect3DSurface8_Release(ds3);
4211 IDirect3DSurface8_Release(ds2);
4212 IDirect3DSurface8_Release(ds1);
4214 done:
4215 if (device) IDirect3DDevice8_Release(device);
4216 IDirect3D8_Release(d3d8);
4217 DestroyWindow(hwnd);
4220 static void test_reset_resources(void)
4222 IDirect3DSurface8 *surface, *rt;
4223 IDirect3DTexture8 *texture;
4224 IDirect3DDevice8 *device;
4225 IDirect3D8 *d3d8;
4226 HWND window;
4227 HRESULT hr;
4228 ULONG ref;
4230 window = create_window();
4231 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4232 ok(!!d3d8, "Failed to create a D3D object.\n");
4234 if (!(device = create_device(d3d8, window, NULL)))
4236 skip("Failed to create a D3D device, skipping tests.\n");
4237 goto done;
4240 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24S8,
4241 D3DMULTISAMPLE_NONE, &surface);
4242 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
4244 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
4245 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
4246 ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr);
4247 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &rt);
4248 ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
4249 IDirect3DTexture8_Release(texture);
4251 hr = IDirect3DDevice8_SetRenderTarget(device, rt, surface);
4252 ok(SUCCEEDED(hr), "Failed to set render target surface, hr %#x.\n", hr);
4253 IDirect3DSurface8_Release(rt);
4254 IDirect3DSurface8_Release(surface);
4256 hr = reset_device(device, NULL);
4257 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4259 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
4260 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
4261 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
4262 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4263 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
4264 IDirect3DSurface8_Release(surface);
4265 IDirect3DSurface8_Release(rt);
4267 ref = IDirect3DDevice8_Release(device);
4268 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4270 done:
4271 IDirect3D8_Release(d3d8);
4272 DestroyWindow(window);
4275 static void test_set_rt_vp_scissor(void)
4277 IDirect3DDevice8 *device;
4278 IDirect3DSurface8 *rt;
4279 IDirect3D8 *d3d8;
4280 DWORD stateblock;
4281 D3DVIEWPORT8 vp;
4282 UINT refcount;
4283 HWND window;
4284 HRESULT hr;
4286 window = create_window();
4287 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4288 ok(!!d3d8, "Failed to create a D3D object.\n");
4289 if (!(device = create_device(d3d8, window, NULL)))
4291 skip("Failed to create a D3D device, skipping tests.\n");
4292 IDirect3D8_Release(d3d8);
4293 DestroyWindow(window);
4294 return;
4297 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
4298 D3DMULTISAMPLE_NONE, FALSE, &rt);
4299 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4301 hr = IDirect3DDevice8_GetViewport(device, &vp);
4302 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4303 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4304 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4305 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
4306 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
4307 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4308 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4310 hr = IDirect3DDevice8_BeginStateBlock(device);
4311 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
4313 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4314 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4316 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
4317 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
4318 hr = IDirect3DDevice8_DeleteStateBlock(device, stateblock);
4319 ok(SUCCEEDED(hr), "Failed to delete stateblock, hr %#x.\n", hr);
4321 hr = IDirect3DDevice8_GetViewport(device, &vp);
4322 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4323 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4324 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4325 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4326 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4327 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4328 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4330 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4331 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4333 vp.X = 10;
4334 vp.Y = 20;
4335 vp.Width = 30;
4336 vp.Height = 40;
4337 vp.MinZ = 0.25f;
4338 vp.MaxZ = 0.75f;
4339 hr = IDirect3DDevice8_SetViewport(device, &vp);
4340 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
4342 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4343 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4345 hr = IDirect3DDevice8_GetViewport(device, &vp);
4346 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4347 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4348 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4349 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4350 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4351 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4352 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4354 IDirect3DSurface8_Release(rt);
4355 refcount = IDirect3DDevice8_Release(device);
4356 ok(!refcount, "Device has %u references left.\n", refcount);
4357 IDirect3D8_Release(d3d8);
4358 DestroyWindow(window);
4361 static void test_validate_vs(void)
4363 static DWORD vs[] =
4365 0xfffe0101, /* vs_1_1 */
4366 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
4367 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
4368 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
4369 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
4370 0x0000ffff, /* end */
4372 HRESULT hr;
4374 hr = ValidateVertexShader(0, 0, 0, 0, 0);
4375 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4376 hr = ValidateVertexShader(0, 0, 0, 1, 0);
4377 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4378 hr = ValidateVertexShader(vs, 0, 0, 0, 0);
4379 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4381 hr = ValidateVertexShader(vs, 0, 0, 1, 0);
4382 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4383 /* Seems to do some version checking. */
4384 *vs = 0xfffe0100; /* vs_1_0 */
4385 hr = ValidateVertexShader(vs, 0, 0, 0, 0);
4386 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4388 *vs = 0xfffe0102; /* bogus version */
4389 hr = ValidateVertexShader(vs, 0, 0, 1, 0);
4390 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4391 /* I've seen that applications always pass the 2nd and 3rd parameter as 0.
4392 * Simple test with non-zero parameters. */
4393 *vs = 0xfffe0101; /* vs_1_1 */
4394 hr = ValidateVertexShader(vs, vs, 0, 1, 0);
4395 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4397 hr = ValidateVertexShader(vs, 0, vs, 1, 0);
4398 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4399 /* I've seen the 4th parameter always passed as either 0 or 1, but passing
4400 * other values doesn't seem to hurt. */
4401 hr = ValidateVertexShader(vs, 0, 0, 12345, 0);
4402 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4403 /* What is the 5th parameter? The following seems to work ok. */
4404 hr = ValidateVertexShader(vs, 0, 0, 1, vs);
4405 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4408 static void test_validate_ps(void)
4410 static DWORD ps[] =
4412 0xffff0101, /* ps_1_1 */
4413 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
4414 0x00000042, 0xb00f0000, /* tex t0 */
4415 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
4416 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
4417 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
4418 0x0000ffff, /* end */
4420 HRESULT hr;
4422 hr = ValidatePixelShader(0, 0, 0, 0);
4423 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4424 hr = ValidatePixelShader(0, 0, 1, 0);
4425 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4426 hr = ValidatePixelShader(ps, 0, 0, 0);
4427 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4429 hr = ValidatePixelShader(ps, 0, 1, 0);
4430 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4431 /* Seems to do some version checking. */
4432 *ps = 0xffff0105; /* bogus version */
4433 hr = ValidatePixelShader(ps, 0, 1, 0);
4434 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4435 /* I've seen that applications always pass the 2nd parameter as 0.
4436 * Simple test with a non-zero parameter. */
4437 *ps = 0xffff0101; /* ps_1_1 */
4438 hr = ValidatePixelShader(ps, ps, 1, 0);
4439 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4440 /* I've seen the 3rd parameter always passed as either 0 or 1, but passing
4441 * other values doesn't seem to hurt. */
4442 hr = ValidatePixelShader(ps, 0, 12345, 0);
4443 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4444 /* What is the 4th parameter? The following seems to work ok. */
4445 hr = ValidatePixelShader(ps, 0, 1, ps);
4446 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4449 static void test_volume_get_container(void)
4451 IDirect3DVolumeTexture8 *texture = NULL;
4452 IDirect3DVolume8 *volume = NULL;
4453 IDirect3DDevice8 *device;
4454 IUnknown *container;
4455 IDirect3D8 *d3d8;
4456 ULONG refcount;
4457 D3DCAPS8 caps;
4458 HWND window;
4459 HRESULT hr;
4461 window = create_window();
4462 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4463 ok(!!d3d8, "Failed to create a D3D object.\n");
4464 if (!(device = create_device(d3d8, window, NULL)))
4466 skip("Failed to create a D3D device, skipping tests.\n");
4467 IDirect3D8_Release(d3d8);
4468 DestroyWindow(window);
4469 return;
4472 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4473 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4474 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
4476 skip("No volume texture support, skipping tests.\n");
4477 IDirect3DDevice8_Release(device);
4478 IDirect3D8_Release(d3d8);
4479 DestroyWindow(window);
4480 return;
4483 hr = IDirect3DDevice8_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
4484 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
4485 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
4486 ok(!!texture, "Got unexpected texture %p.\n", texture);
4488 hr = IDirect3DVolumeTexture8_GetVolumeLevel(texture, 0, &volume);
4489 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
4490 ok(!!volume, "Got unexpected volume %p.\n", volume);
4492 /* These should work... */
4493 container = NULL;
4494 hr = IDirect3DVolume8_GetContainer(volume, &IID_IUnknown, (void **)&container);
4495 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4496 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4497 IUnknown_Release(container);
4499 container = NULL;
4500 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DResource8, (void **)&container);
4501 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4502 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4503 IUnknown_Release(container);
4505 container = NULL;
4506 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DBaseTexture8, (void **)&container);
4507 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4508 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4509 IUnknown_Release(container);
4511 container = NULL;
4512 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolumeTexture8, (void **)&container);
4513 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4514 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4515 IUnknown_Release(container);
4517 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
4518 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolume8, (void **)&container);
4519 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
4520 ok(!container, "Got unexpected container %p.\n", container);
4522 IDirect3DVolume8_Release(volume);
4523 IDirect3DVolumeTexture8_Release(texture);
4524 refcount = IDirect3DDevice8_Release(device);
4525 ok(!refcount, "Device has %u references left.\n", refcount);
4526 IDirect3D8_Release(d3d8);
4527 DestroyWindow(window);
4530 static void test_vb_lock_flags(void)
4532 static const struct
4534 DWORD flags;
4535 const char *debug_string;
4536 HRESULT result;
4538 test_data[] =
4540 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
4541 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
4542 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
4543 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
4544 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
4545 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3D_OK },
4546 /* Completely bogus flags aren't an error. */
4547 {0xdeadbeef, "0xdeadbeef", D3D_OK },
4549 IDirect3DVertexBuffer8 *buffer;
4550 IDirect3DDevice8 *device;
4551 IDirect3D8 *d3d8;
4552 unsigned int i;
4553 ULONG refcount;
4554 HWND window;
4555 HRESULT hr;
4556 BYTE *data;
4558 window = create_window();
4559 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4560 ok(!!d3d8, "Failed to create a D3D object.\n");
4561 if (!(device = create_device(d3d8, window, NULL)))
4563 skip("Failed to create a D3D device, skipping tests.\n");
4564 IDirect3D8_Release(d3d8);
4565 DestroyWindow(window);
4566 return;
4569 hr = IDirect3DDevice8_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer);
4570 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
4572 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
4574 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &data, test_data[i].flags);
4575 ok(hr == test_data[i].result, "Got unexpected hr %#x for %s.\n",
4576 hr, test_data[i].debug_string);
4577 if (SUCCEEDED(hr))
4579 ok(!!data, "Got unexpected data %p.\n", data);
4580 hr = IDirect3DVertexBuffer8_Unlock(buffer);
4581 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4585 IDirect3DVertexBuffer8_Release(buffer);
4586 refcount = IDirect3DDevice8_Release(device);
4587 ok(!refcount, "Device has %u references left.\n", refcount);
4588 IDirect3D8_Release(d3d8);
4589 DestroyWindow(window);
4592 /* Test the default texture stage state values */
4593 static void test_texture_stage_states(void)
4595 IDirect3DDevice8 *device;
4596 IDirect3D8 *d3d8;
4597 unsigned int i;
4598 ULONG refcount;
4599 D3DCAPS8 caps;
4600 DWORD value;
4601 HWND window;
4602 HRESULT hr;
4604 window = create_window();
4605 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4606 ok(!!d3d8, "Failed to create a D3D object.\n");
4607 if (!(device = create_device(d3d8, window, NULL)))
4609 skip("Failed to create a D3D device, skipping tests.\n");
4610 IDirect3D8_Release(d3d8);
4611 DestroyWindow(window);
4612 return;
4615 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4616 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4618 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
4620 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
4621 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4622 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
4623 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
4624 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
4625 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4626 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
4627 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
4628 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4629 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
4630 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
4631 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4632 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
4633 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
4634 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
4635 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4636 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
4637 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
4638 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4639 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
4640 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
4641 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4642 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
4643 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
4644 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4645 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
4646 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
4647 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4648 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
4649 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
4650 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4651 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
4652 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
4653 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4654 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
4655 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
4656 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4657 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
4658 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
4659 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4660 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
4661 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
4662 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4663 ok(value == D3DTTFF_DISABLE,
4664 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
4665 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
4666 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4667 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
4668 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
4669 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4670 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
4671 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
4672 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4673 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
4676 refcount = IDirect3DDevice8_Release(device);
4677 ok(!refcount, "Device has %u references left.\n", refcount);
4678 IDirect3D8_Release(d3d8);
4679 DestroyWindow(window);
4682 static void test_cube_textures(void)
4684 IDirect3DCubeTexture8 *texture;
4685 IDirect3DDevice8 *device;
4686 IDirect3D8 *d3d8;
4687 ULONG refcount;
4688 D3DCAPS8 caps;
4689 HWND window;
4690 HRESULT hr;
4692 window = create_window();
4693 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4694 ok(!!d3d8, "Failed to create a D3D object.\n");
4695 if (!(device = create_device(d3d8, window, NULL)))
4697 skip("Failed to create a D3D device, skipping tests.\n");
4698 IDirect3D8_Release(d3d8);
4699 DestroyWindow(window);
4700 return;
4703 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4704 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4706 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
4708 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
4709 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
4710 IDirect3DCubeTexture8_Release(texture);
4711 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
4712 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
4713 IDirect3DCubeTexture8_Release(texture);
4714 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
4715 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
4716 IDirect3DCubeTexture8_Release(texture);
4718 else
4720 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
4721 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
4722 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
4723 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
4724 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
4725 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
4727 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture);
4728 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
4729 IDirect3DCubeTexture8_Release(texture);
4731 refcount = IDirect3DDevice8_Release(device);
4732 ok(!refcount, "Device has %u references left.\n", refcount);
4733 IDirect3D8_Release(d3d8);
4734 DestroyWindow(window);
4737 static void test_get_set_texture(void)
4739 const IDirect3DBaseTexture8Vtbl *texture_vtbl;
4740 IDirect3DBaseTexture8 *texture;
4741 IDirect3DDevice8 *device;
4742 IDirect3D8 *d3d;
4743 ULONG refcount;
4744 HWND window;
4745 HRESULT hr;
4747 window = create_window();
4748 d3d = Direct3DCreate8(D3D_SDK_VERSION);
4749 ok(!!d3d, "Failed to create a D3D object.\n");
4750 if (!(device = create_device(d3d, window, NULL)))
4752 skip("Failed to create a D3D device, skipping tests.\n");
4753 IDirect3D8_Release(d3d);
4754 DestroyWindow(window);
4755 return;
4758 texture = (IDirect3DBaseTexture8 *)0xdeadbeef;
4759 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
4760 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4761 hr = IDirect3DDevice8_GetTexture(device, 0, &texture);
4762 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4763 ok(!texture, "Got unexpected texture %p.\n", texture);
4765 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
4766 D3DPOOL_MANAGED, (IDirect3DTexture8 **)&texture);
4767 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4768 texture_vtbl = texture->lpVtbl;
4769 texture->lpVtbl = (IDirect3DBaseTexture8Vtbl *)0xdeadbeef;
4770 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
4771 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4772 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
4773 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4774 texture->lpVtbl = NULL;
4775 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
4776 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4777 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
4778 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4779 texture->lpVtbl = texture_vtbl;
4780 IDirect3DBaseTexture8_Release(texture);
4782 refcount = IDirect3DDevice8_Release(device);
4783 ok(!refcount, "Device has %u references left.\n", refcount);
4784 IDirect3D8_Release(d3d);
4785 DestroyWindow(window);
4788 /* Test the behaviour of the IDirect3DDevice8::CreateImageSurface() method.
4790 * The expected behaviour (as documented in the original DX8 docs) is that the
4791 * call returns a surface in the SYSTEMMEM pool. Games like Max Payne 1 and 2
4792 * depend on this behaviour.
4794 * A short remark in the DX9 docs however states that the pool of the returned
4795 * surface object is D3DPOOL_SCRATCH. This is misinformation and would result
4796 * in screenshots not appearing in the savegame loading menu of both games
4797 * mentioned above (engine tries to display a texture from the scratch pool).
4799 * This test verifies that the behaviour described in the original d3d8 docs
4800 * is the correct one. For more information about this issue, see the MSDN:
4801 * d3d9 docs: "Converting to Direct3D 9"
4802 * d3d9 reference: "IDirect3DDevice9::CreateOffscreenPlainSurface"
4803 * d3d8 reference: "IDirect3DDevice8::CreateImageSurface" */
4804 static void test_image_surface_pool(void)
4806 IDirect3DSurface8 *surface;
4807 IDirect3DDevice8 *device;
4808 D3DSURFACE_DESC desc;
4809 IDirect3D8 *d3d8;
4810 ULONG refcount;
4811 HWND window;
4812 HRESULT hr;
4814 window = create_window();
4815 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4816 ok(!!d3d8, "Failed to create a D3D object.\n");
4817 if (!(device = create_device(d3d8, window, NULL)))
4819 skip("Failed to create a D3D device, skipping tests.\n");
4820 IDirect3D8_Release(d3d8);
4821 DestroyWindow(window);
4822 return;
4825 hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
4826 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4827 hr = IDirect3DSurface8_GetDesc(surface, &desc);
4828 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4829 ok(desc.Pool == D3DPOOL_SYSTEMMEM, "Got unexpected pool %#x.\n", desc.Pool);
4830 IDirect3DSurface8_Release(surface);
4832 refcount = IDirect3DDevice8_Release(device);
4833 ok(!refcount, "Device has %u references left.\n", refcount);
4834 IDirect3D8_Release(d3d8);
4835 DestroyWindow(window);
4838 static void test_surface_get_container(void)
4840 IDirect3DTexture8 *texture = NULL;
4841 IDirect3DSurface8 *surface = NULL;
4842 IDirect3DDevice8 *device;
4843 IUnknown *container;
4844 IDirect3D8 *d3d8;
4845 ULONG refcount;
4846 HWND window;
4847 HRESULT hr;
4849 window = create_window();
4850 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4851 ok(!!d3d8, "Failed to create a D3D object.\n");
4852 if (!(device = create_device(d3d8, window, NULL)))
4854 skip("Failed to create a D3D device, skipping tests.\n");
4855 IDirect3D8_Release(d3d8);
4856 DestroyWindow(window);
4857 return;
4860 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0,
4861 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
4862 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4863 ok(!!texture, "Got unexpected texture %p.\n", texture);
4865 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
4866 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
4867 ok(!!surface, "Got unexpected surface %p.\n", surface);
4869 /* These should work... */
4870 container = NULL;
4871 hr = IDirect3DSurface8_GetContainer(surface, &IID_IUnknown, (void **)&container);
4872 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4873 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4874 IUnknown_Release(container);
4876 container = NULL;
4877 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DResource8, (void **)&container);
4878 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4879 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4880 IUnknown_Release(container);
4882 container = NULL;
4883 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DBaseTexture8, (void **)&container);
4884 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4885 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4886 IUnknown_Release(container);
4888 container = NULL;
4889 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DTexture8, (void **)&container);
4890 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4891 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4892 IUnknown_Release(container);
4894 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
4895 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DSurface8, (void **)&container);
4896 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
4897 ok(!container, "Got unexpected container %p.\n", container);
4899 IDirect3DSurface8_Release(surface);
4900 IDirect3DTexture8_Release(texture);
4901 refcount = IDirect3DDevice8_Release(device);
4902 ok(!refcount, "Device has %u references left.\n", refcount);
4903 IDirect3D8_Release(d3d8);
4904 DestroyWindow(window);
4907 static void test_lockrect_invalid(void)
4909 static const RECT valid[] =
4911 {60, 60, 68, 68},
4912 {120, 60, 128, 68},
4913 {60, 120, 68, 128},
4915 static const RECT invalid[] =
4917 {60, 60, 60, 68}, /* 0 height */
4918 {60, 60, 68, 60}, /* 0 width */
4919 {68, 60, 60, 68}, /* left > right */
4920 {60, 68, 68, 60}, /* top > bottom */
4921 {-8, 60, 0, 68}, /* left < surface */
4922 {60, -8, 68, 0}, /* top < surface */
4923 {-16, 60, -8, 68}, /* right < surface */
4924 {60, -16, 68, -8}, /* bottom < surface */
4925 {60, 60, 136, 68}, /* right > surface */
4926 {60, 60, 68, 136}, /* bottom > surface */
4927 {136, 60, 144, 68}, /* left > surface */
4928 {60, 136, 68, 144}, /* top > surface */
4930 IDirect3DSurface8 *surface;
4931 IDirect3DTexture8 *texture;
4932 IDirect3DCubeTexture8 *cube_texture;
4933 D3DLOCKED_RECT locked_rect;
4934 IDirect3DDevice8 *device;
4935 HRESULT hr, expected_hr;
4936 IDirect3D8 *d3d8;
4937 unsigned int i, r;
4938 ULONG refcount;
4939 HWND window;
4940 BYTE *base;
4941 unsigned int offset, expected_offset;
4942 static const struct
4944 D3DRESOURCETYPE type;
4945 D3DPOOL pool;
4946 const char *name;
4947 BOOL validate, clear;
4949 resources[] =
4951 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface", TRUE, TRUE},
4952 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture", FALSE, FALSE},
4953 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture", FALSE, FALSE},
4954 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture", FALSE, FALSE},
4955 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture", TRUE, TRUE},
4956 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture", TRUE, TRUE},
4957 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture", TRUE, TRUE},
4960 window = create_window();
4961 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4962 ok(!!d3d8, "Failed to create a D3D object.\n");
4963 if (!(device = create_device(d3d8, window, NULL)))
4965 skip("Failed to create a D3D device, skipping tests.\n");
4966 IDirect3D8_Release(d3d8);
4967 DestroyWindow(window);
4968 return;
4971 for (r = 0; r < ARRAY_SIZE(resources); ++r)
4973 texture = NULL;
4974 cube_texture = NULL;
4975 switch (resources[r].type)
4977 case D3DRTYPE_SURFACE:
4978 hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
4979 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
4980 break;
4982 case D3DRTYPE_TEXTURE:
4983 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
4984 resources[r].pool, &texture);
4985 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n", hr, resources[r].name);
4986 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
4987 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n", hr, resources[r].name);
4988 break;
4990 case D3DRTYPE_CUBETEXTURE:
4991 hr = IDirect3DDevice8_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
4992 resources[r].pool, &cube_texture);
4993 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n", hr, resources[r].name);
4994 hr = IDirect3DCubeTexture8_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
4995 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n", hr, resources[r].name);
4996 break;
4998 default:
4999 break;
5002 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5003 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
5004 base = locked_rect.pBits;
5005 hr = IDirect3DSurface8_UnlockRect(surface);
5006 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5007 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
5008 hr = IDirect3DSurface8_UnlockRect(surface);
5009 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
5011 for (i = 0; i < ARRAY_SIZE(valid); ++i)
5013 const RECT *rect = &valid[i];
5015 locked_rect.pBits = (BYTE *)0xdeadbeef;
5016 locked_rect.Pitch = 0xdeadbeef;
5018 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
5019 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
5020 wine_dbgstr_rect(rect), hr, resources[r].name);
5022 offset = (BYTE *)locked_rect.pBits - base;
5023 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5024 ok(offset == expected_offset,
5025 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5026 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
5028 hr = IDirect3DSurface8_UnlockRect(surface);
5029 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s\n", hr, resources[r].name);
5031 if (texture)
5033 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, rect, 0);
5034 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
5035 wine_dbgstr_rect(rect), hr, resources[r].name);
5037 offset = (BYTE *)locked_rect.pBits - base;
5038 ok(offset == expected_offset,
5039 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5040 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
5042 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5043 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5045 if (cube_texture)
5047 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0, &locked_rect, rect, 0);
5048 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
5049 wine_dbgstr_rect(rect), hr, resources[r].name);
5051 offset = (BYTE *)locked_rect.pBits - base;
5052 ok(offset == expected_offset,
5053 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5054 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
5056 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5057 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5061 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
5063 const RECT *rect = &invalid[i];
5065 locked_rect.pBits = (void *)0xdeadbeef;
5066 locked_rect.Pitch = 1;
5067 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
5068 if (resources[r].validate)
5069 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5070 hr, wine_dbgstr_rect(rect), resources[r].name);
5071 else
5072 ok(SUCCEEDED(hr), "Got unexpected hr %#x for rect %s, type %s.\n",
5073 hr, wine_dbgstr_rect(rect), resources[r].name);
5075 if (SUCCEEDED(hr))
5077 offset = (BYTE *)locked_rect.pBits - base;
5078 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5079 ok(offset == expected_offset,
5080 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5081 offset, expected_offset,wine_dbgstr_rect(rect), resources[r].name);
5083 hr = IDirect3DSurface8_UnlockRect(surface);
5084 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5086 else
5088 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5089 locked_rect.pBits, resources[r].name);
5090 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5091 locked_rect.Pitch, resources[r].name);
5095 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5096 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n",
5097 hr, resources[r].name);
5098 locked_rect.pBits = (void *)0xdeadbeef;
5099 locked_rect.Pitch = 1;
5100 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5101 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5102 if (resources[r].clear)
5104 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5105 locked_rect.pBits, resources[r].name);
5106 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5107 locked_rect.Pitch, resources[r].name);
5109 else
5111 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
5112 locked_rect.pBits, resources[r].name);
5113 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
5114 locked_rect.Pitch, resources[r].name);
5116 hr = IDirect3DSurface8_UnlockRect(surface);
5117 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5119 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
5120 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
5121 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5122 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
5123 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5124 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5125 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[1], 0);
5126 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5127 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5128 hr = IDirect3DSurface8_UnlockRect(surface);
5129 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5131 IDirect3DSurface8_Release(surface);
5132 if (texture)
5134 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5135 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
5136 hr, resources[r].name);
5137 locked_rect.pBits = (void *)0xdeadbeef;
5138 locked_rect.Pitch = 1;
5139 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5140 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5141 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
5142 locked_rect.pBits, resources[r].name);
5143 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
5144 locked_rect.Pitch, resources[r].name);
5145 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5146 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5147 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5148 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5149 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5150 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5152 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5153 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
5154 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5155 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5156 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5157 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5158 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[1], 0);
5159 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5160 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5161 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5162 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5164 IDirect3DTexture8_Release(texture);
5167 if (cube_texture)
5169 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5170 &locked_rect, NULL, 0);
5171 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
5172 hr, resources[r].name);
5173 locked_rect.pBits = (void *)0xdeadbeef;
5174 locked_rect.Pitch = 1;
5175 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5176 &locked_rect, NULL, 0);
5177 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5178 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5179 locked_rect.pBits, resources[r].name);
5180 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5181 locked_rect.Pitch, resources[r].name);
5182 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5183 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5184 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5185 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5186 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5187 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5189 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5190 &locked_rect, &valid[0], 0);
5191 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
5192 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5193 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5194 &locked_rect, &valid[0], 0);
5195 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5196 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5197 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5198 &locked_rect, &valid[1], 0);
5199 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5200 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5201 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5202 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5204 IDirect3DTexture8_Release(cube_texture);
5208 refcount = IDirect3DDevice8_Release(device);
5209 ok(!refcount, "Device has %u references left.\n", refcount);
5210 IDirect3D8_Release(d3d8);
5211 DestroyWindow(window);
5214 static void test_private_data(void)
5216 ULONG refcount, expected_refcount;
5217 IDirect3DTexture8 *texture;
5218 IDirect3DSurface8 *surface, *surface2;
5219 IDirect3DDevice8 *device;
5220 IDirect3D8 *d3d8;
5221 IUnknown *ptr;
5222 HWND window;
5223 HRESULT hr;
5224 DWORD size;
5225 DWORD data[4] = {1, 2, 3, 4};
5226 static const GUID d3d8_private_data_test_guid2 =
5228 0x2e5afac2,
5229 0x87b5,
5230 0x4c10,
5231 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
5234 window = create_window();
5235 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5236 ok(!!d3d8, "Failed to create a D3D object.\n");
5237 if (!(device = create_device(d3d8, window, NULL)))
5239 skip("Failed to create a D3D device, skipping tests.\n");
5240 IDirect3D8_Release(d3d8);
5241 DestroyWindow(window);
5242 return;
5245 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_A8R8G8B8, &surface);
5246 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5248 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5249 device, 0, D3DSPD_IUNKNOWN);
5250 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5251 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5252 device, 5, D3DSPD_IUNKNOWN);
5253 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5254 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5255 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
5256 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5258 /* A failing SetPrivateData call does not clear the old data with the same tag. */
5259 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
5260 sizeof(device), D3DSPD_IUNKNOWN);
5261 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5262 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
5263 sizeof(device) * 2, D3DSPD_IUNKNOWN);
5264 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5265 size = sizeof(ptr);
5266 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5267 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
5268 IUnknown_Release(ptr);
5269 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5270 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5272 refcount = get_refcount((IUnknown *)device);
5273 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5274 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5275 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5276 expected_refcount = refcount + 1;
5277 refcount = get_refcount((IUnknown *)device);
5278 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5279 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5280 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5281 expected_refcount = refcount - 1;
5282 refcount = get_refcount((IUnknown *)device);
5283 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5285 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5286 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5287 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5288 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5289 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5290 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5291 refcount = get_refcount((IUnknown *)device);
5292 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5294 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5295 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5296 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5297 size = 2 * sizeof(ptr);
5298 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5299 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5300 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5301 expected_refcount = refcount + 2;
5302 refcount = get_refcount((IUnknown *)device);
5303 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5304 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
5305 IUnknown_Release(ptr);
5306 expected_refcount--;
5308 ptr = (IUnknown *)0xdeadbeef;
5309 size = 1;
5310 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
5311 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5312 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5313 size = 2 * sizeof(ptr);
5314 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
5315 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5316 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5317 refcount = get_refcount((IUnknown *)device);
5318 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5319 size = 1;
5320 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5321 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
5322 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5323 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
5324 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, NULL, NULL);
5325 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5326 size = 0xdeadbabe;
5327 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, &ptr, &size);
5328 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5329 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
5330 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
5331 /* GetPrivateData with size = NULL causes an access violation on Windows if the
5332 * requested data exists. */
5334 /* Destroying the surface frees the held reference. */
5335 IDirect3DSurface8_Release(surface);
5336 expected_refcount = refcount - 2;
5337 refcount = get_refcount((IUnknown *)device);
5338 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5340 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
5341 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5342 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5343 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
5344 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
5345 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
5347 hr = IDirect3DTexture8_SetPrivateData(texture, &d3d8_private_data_test_guid, data, sizeof(data), 0);
5348 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5350 memset(data, 0, sizeof(data));
5351 size = sizeof(data);
5352 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, data, &size);
5353 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5354 hr = IDirect3DTexture8_GetPrivateData(texture, &d3d8_private_data_test_guid, data, &size);
5355 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
5356 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
5357 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
5359 hr = IDirect3DTexture8_FreePrivateData(texture, &d3d8_private_data_test_guid);
5360 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5362 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, data, sizeof(data), 0);
5363 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5364 hr = IDirect3DSurface8_GetPrivateData(surface2, &d3d8_private_data_test_guid, data, &size);
5365 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5366 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5367 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5369 IDirect3DSurface8_Release(surface2);
5370 IDirect3DSurface8_Release(surface);
5371 IDirect3DTexture8_Release(texture);
5373 refcount = IDirect3DDevice8_Release(device);
5374 ok(!refcount, "Device has %u references left.\n", refcount);
5375 IDirect3D8_Release(d3d8);
5376 DestroyWindow(window);
5379 static void test_surface_dimensions(void)
5381 IDirect3DSurface8 *surface;
5382 IDirect3DDevice8 *device;
5383 IDirect3D8 *d3d8;
5384 ULONG refcount;
5385 HWND window;
5386 HRESULT hr;
5388 window = create_window();
5389 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5390 ok(!!d3d8, "Failed to create a D3D object.\n");
5391 if (!(device = create_device(d3d8, window, NULL)))
5393 skip("Failed to create a D3D device, skipping tests.\n");
5394 IDirect3D8_Release(d3d8);
5395 DestroyWindow(window);
5396 return;
5399 hr = IDirect3DDevice8_CreateImageSurface(device, 0, 1, D3DFMT_A8R8G8B8, &surface);
5400 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5401 hr = IDirect3DDevice8_CreateImageSurface(device, 1, 0, D3DFMT_A8R8G8B8, &surface);
5402 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5404 refcount = IDirect3DDevice8_Release(device);
5405 ok(!refcount, "Device has %u references left.\n", refcount);
5406 IDirect3D8_Release(d3d8);
5407 DestroyWindow(window);
5410 static void test_surface_format_null(void)
5412 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
5413 IDirect3DTexture8 *texture;
5414 IDirect3DSurface8 *surface;
5415 IDirect3DSurface8 *rt, *ds;
5416 D3DLOCKED_RECT locked_rect;
5417 IDirect3DDevice8 *device;
5418 D3DSURFACE_DESC desc;
5419 IDirect3D8 *d3d;
5420 ULONG refcount;
5421 HWND window;
5422 HRESULT hr;
5424 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5425 ok(!!d3d, "Failed to create a D3D object.\n");
5427 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5428 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
5429 if (hr != D3D_OK)
5431 skip("No D3DFMT_NULL support, skipping test.\n");
5432 IDirect3D8_Release(d3d);
5433 return;
5436 window = create_window();
5437 if (!(device = create_device(d3d, window, NULL)))
5439 skip("Failed to create a D3D device, skipping tests.\n");
5440 IDirect3D8_Release(d3d);
5441 DestroyWindow(window);
5442 return;
5445 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5446 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
5447 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
5449 hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5450 D3DFMT_NULL, D3DFMT_D24S8);
5451 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
5453 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
5454 D3DMULTISAMPLE_NONE, TRUE, &surface);
5455 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5457 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
5458 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
5460 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds);
5461 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
5463 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
5464 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5466 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
5467 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
5469 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
5470 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5472 IDirect3DSurface8_Release(rt);
5473 IDirect3DSurface8_Release(ds);
5475 hr = IDirect3DSurface8_GetDesc(surface, &desc);
5476 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5477 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
5478 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
5480 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5481 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5482 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
5483 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
5485 hr = IDirect3DSurface8_UnlockRect(surface);
5486 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5488 IDirect3DSurface8_Release(surface);
5490 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
5491 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture);
5492 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5493 IDirect3DTexture8_Release(texture);
5495 refcount = IDirect3DDevice8_Release(device);
5496 ok(!refcount, "Device has %u references left.\n", refcount);
5497 IDirect3D8_Release(d3d);
5498 DestroyWindow(window);
5501 static void test_surface_double_unlock(void)
5503 static const D3DPOOL pools[] =
5505 D3DPOOL_DEFAULT,
5506 D3DPOOL_SYSTEMMEM,
5508 IDirect3DSurface8 *surface;
5509 IDirect3DDevice8 *device;
5510 D3DLOCKED_RECT lr;
5511 IDirect3D8 *d3d;
5512 unsigned int i;
5513 ULONG refcount;
5514 HWND window;
5515 HRESULT hr;
5517 window = create_window();
5518 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5519 ok(!!d3d, "Failed to create a D3D object.\n");
5520 if (!(device = create_device(d3d, window, NULL)))
5522 skip("Failed to create a D3D device, skipping tests.\n");
5523 IDirect3D8_Release(d3d);
5524 DestroyWindow(window);
5525 return;
5528 for (i = 0; i < ARRAY_SIZE(pools); ++i)
5530 switch (pools[i])
5532 case D3DPOOL_DEFAULT:
5533 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5534 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
5535 if (FAILED(hr))
5537 skip("D3DFMT_X8R8G8B8 render targets not supported, skipping double unlock DEFAULT pool test.\n");
5538 continue;
5541 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_X8R8G8B8,
5542 D3DMULTISAMPLE_NONE, TRUE, &surface);
5543 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5544 break;
5546 case D3DPOOL_SYSTEMMEM:
5547 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64, D3DFMT_X8R8G8B8, &surface);
5548 ok(SUCCEEDED(hr), "Failed to create image surface, hr %#x.\n", hr);
5549 break;
5551 default:
5552 break;
5555 hr = IDirect3DSurface8_UnlockRect(surface);
5556 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5557 hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
5558 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
5559 hr = IDirect3DSurface8_UnlockRect(surface);
5560 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
5561 hr = IDirect3DSurface8_UnlockRect(surface);
5562 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5564 IDirect3DSurface8_Release(surface);
5567 refcount = IDirect3DDevice8_Release(device);
5568 ok(!refcount, "Device has %u references left.\n", refcount);
5569 IDirect3D8_Release(d3d);
5570 DestroyWindow(window);
5573 static void test_surface_blocks(void)
5575 static const struct
5577 D3DFORMAT fmt;
5578 const char *name;
5579 unsigned int block_width;
5580 unsigned int block_height;
5581 BOOL broken;
5582 BOOL create_size_checked, core_fmt;
5584 formats[] =
5586 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
5587 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
5588 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
5589 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
5590 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
5591 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
5592 * which doesn't match the format spec. On newer Nvidia cards
5593 * they have the correct 4x4 block size */
5594 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
5595 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
5596 /* Windows drivers generally enforce block-aligned locks for
5597 * YUY2 and UYVY. The notable exception is the AMD r500 driver
5598 * in d3d8. The same driver checks the sizes in d3d9. */
5599 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, TRUE, FALSE, TRUE },
5600 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, TRUE, FALSE, TRUE },
5602 static const struct
5604 D3DPOOL pool;
5605 const char *name;
5606 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
5607 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
5608 BOOL success;
5610 pools[] =
5612 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
5613 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
5614 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
5615 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
5617 static struct
5619 D3DRESOURCETYPE rtype;
5620 const char *type_name;
5621 D3DPOOL pool;
5622 const char *pool_name;
5623 BOOL need_driver_support, need_runtime_support;
5625 create_tests[] =
5627 /* D3d8 only supports sysmem surfaces, which are created via CreateImageSurface. Other tests confirm
5628 * that they are D3DPOOL_SYSTEMMEM surfaces, but their creation restriction behaves like the scratch
5629 * pool in d3d9. */
5630 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE, TRUE },
5632 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
5633 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
5634 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
5635 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5637 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
5638 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
5639 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
5640 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5642 IDirect3DTexture8 *texture;
5643 IDirect3DCubeTexture8 *cube_texture;
5644 IDirect3DSurface8 *surface;
5645 D3DLOCKED_RECT locked_rect;
5646 IDirect3DDevice8 *device;
5647 unsigned int i, j, k, w, h;
5648 IDirect3D8 *d3d;
5649 ULONG refcount;
5650 HWND window;
5651 HRESULT hr;
5652 RECT rect;
5653 BOOL tex_pow2, cube_pow2;
5654 D3DCAPS8 caps;
5655 static const RECT invalid[] =
5657 {60, 60, 60, 68}, /* 0 height */
5658 {60, 60, 68, 60}, /* 0 width */
5659 {68, 60, 60, 68}, /* left > right */
5660 {60, 68, 68, 60}, /* top > bottom */
5661 {-8, 60, 0, 68}, /* left < surface */
5662 {60, -8, 68, 0}, /* top < surface */
5663 {-16, 60, -8, 68}, /* right < surface */
5664 {60, -16, 68, -8}, /* bottom < surface */
5665 {60, 60, 136, 68}, /* right > surface */
5666 {60, 60, 68, 136}, /* bottom > surface */
5667 {136, 60, 144, 68}, /* left > surface */
5668 {60, 136, 68, 144}, /* top > surface */
5671 window = create_window();
5672 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5673 ok(!!d3d, "Failed to create a D3D object.\n");
5674 if (!(device = create_device(d3d, window, NULL)))
5676 skip("Failed to create a D3D device, skipping tests.\n");
5677 IDirect3D8_Release(d3d);
5678 DestroyWindow(window);
5679 return;
5682 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5683 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5684 tex_pow2 = caps.TextureCaps & D3DPTEXTURECAPS_POW2;
5685 if (tex_pow2)
5686 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
5687 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
5689 for (i = 0; i < ARRAY_SIZE(formats); ++i)
5691 BOOL tex_support, cube_support, surface_support, format_known;
5693 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5694 0, D3DRTYPE_TEXTURE, formats[i].fmt);
5695 tex_support = SUCCEEDED(hr);
5696 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5697 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
5698 cube_support = SUCCEEDED(hr);
5699 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5700 0, D3DRTYPE_SURFACE, formats[i].fmt);
5701 surface_support = SUCCEEDED(hr);
5703 /* Scratch pool in general allows texture creation even if the driver does
5704 * not support the format. If the format is an extension format that is not
5705 * known to the runtime, like ATI2N, some driver support is required for
5706 * this to work.
5708 * It is also possible that Windows Vista and Windows 7 d3d8 runtimes know
5709 * about ATI2N. I cannot check this because all my Vista+ machines support
5710 * ATI2N in hardware, but none of my WinXP machines do. */
5711 format_known = tex_support || cube_support || surface_support;
5713 for (w = 1; w <= 8; w++)
5715 for (h = 1; h <= 8; h++)
5717 BOOL block_aligned = TRUE;
5718 BOOL size_is_pow2;
5720 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5721 block_aligned = FALSE;
5723 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
5725 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
5727 BOOL support, pow2;
5728 HRESULT expect_hr;
5729 BOOL may_succeed = FALSE;
5730 IUnknown **check_null;
5732 if (!formats[i].core_fmt)
5734 /* AMD warns against creating ATI2N textures smaller than
5735 * the block size because the runtime cannot calculate the
5736 * correct texture size. Generalize this for all extension
5737 * formats. */
5738 if (w < formats[i].block_width || h < formats[i].block_height)
5739 continue;
5742 texture = (IDirect3DTexture8 *)0xdeadbeef;
5743 cube_texture = (IDirect3DCubeTexture8 *)0xdeadbeef;
5744 surface = (IDirect3DSurface8 *)0xdeadbeef;
5746 switch (create_tests[j].rtype)
5748 case D3DRTYPE_TEXTURE:
5749 check_null = (IUnknown **)&texture;
5750 hr = IDirect3DDevice8_CreateTexture(device, w, h, 1, 0,
5751 formats[i].fmt, create_tests[j].pool, &texture);
5752 support = tex_support;
5753 pow2 = tex_pow2;
5754 break;
5756 case D3DRTYPE_CUBETEXTURE:
5757 if (w != h)
5758 continue;
5759 check_null = (IUnknown **)&cube_texture;
5760 hr = IDirect3DDevice8_CreateCubeTexture(device, w, 1, 0,
5761 formats[i].fmt, create_tests[j].pool, &cube_texture);
5762 support = cube_support;
5763 pow2 = cube_pow2;
5764 break;
5766 case D3DRTYPE_SURFACE:
5767 check_null = (IUnknown **)&surface;
5768 hr = IDirect3DDevice8_CreateImageSurface(device, w, h,
5769 formats[i].fmt, &surface);
5770 support = surface_support;
5771 pow2 = FALSE;
5772 break;
5774 default:
5775 pow2 = FALSE;
5776 support = FALSE;
5777 check_null = NULL;
5778 break;
5781 if (create_tests[j].need_driver_support && !support)
5782 expect_hr = D3DERR_INVALIDCALL;
5783 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
5784 expect_hr = D3DERR_INVALIDCALL;
5785 else if (formats[i].create_size_checked && !block_aligned)
5786 expect_hr = D3DERR_INVALIDCALL;
5787 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
5788 expect_hr = D3DERR_INVALIDCALL;
5789 else
5790 expect_hr = D3D_OK;
5792 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
5793 may_succeed = TRUE;
5795 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
5796 * does not support it. Accept scratch creation of extension formats on
5797 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
5798 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
5799 * support it. */
5800 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
5801 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
5802 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
5804 if (FAILED(hr))
5805 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
5806 else
5807 IUnknown_Release(*check_null);
5812 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5813 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
5814 if (FAILED(hr))
5816 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
5817 continue;
5820 for (j = 0; j < ARRAY_SIZE(pools); ++j)
5822 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1,
5823 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
5824 formats[i].fmt, pools[j].pool, &texture);
5825 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5826 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5827 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5828 IDirect3DTexture8_Release(texture);
5830 if (formats[i].block_width > 1)
5832 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
5833 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5834 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5835 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5836 SUCCEEDED(hr) ? "succeeded" : "failed",
5837 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5838 if (SUCCEEDED(hr))
5840 hr = IDirect3DSurface8_UnlockRect(surface);
5841 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5844 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
5845 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5846 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5847 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5848 SUCCEEDED(hr) ? "succeeded" : "failed",
5849 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5850 if (SUCCEEDED(hr))
5852 hr = IDirect3DSurface8_UnlockRect(surface);
5853 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5857 if (formats[i].block_height > 1)
5859 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
5860 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5861 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5862 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5863 SUCCEEDED(hr) ? "succeeded" : "failed",
5864 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5865 if (SUCCEEDED(hr))
5867 hr = IDirect3DSurface8_UnlockRect(surface);
5868 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5871 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
5872 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5873 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5874 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5875 SUCCEEDED(hr) ? "succeeded" : "failed",
5876 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5877 if (SUCCEEDED(hr))
5879 hr = IDirect3DSurface8_UnlockRect(surface);
5880 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5884 for (k = 0; k < ARRAY_SIZE(invalid); ++k)
5886 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &invalid[k], 0);
5887 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
5888 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
5889 formats[i].name, pools[j].name, k);
5890 if (SUCCEEDED(hr))
5892 hr = IDirect3DSurface8_UnlockRect(surface);
5893 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5897 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
5898 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5899 ok(hr == D3D_OK, "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
5900 hr = IDirect3DSurface8_UnlockRect(surface);
5901 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5903 IDirect3DSurface8_Release(surface);
5906 if (formats[i].block_width == 1 && formats[i].block_height == 1)
5907 continue;
5908 if (!formats[i].core_fmt)
5909 continue;
5911 hr = IDirect3DDevice8_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
5912 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture);
5913 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
5915 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, NULL, 0);
5916 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5917 hr = IDirect3DTexture8_UnlockRect(texture, 1);
5918 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5920 rect.left = 0;
5921 rect.top = 0;
5922 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
5923 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
5924 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
5925 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5926 hr = IDirect3DTexture8_UnlockRect(texture, 1);
5927 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5929 rect.right = formats[i].block_width;
5930 rect.bottom = formats[i].block_height;
5931 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
5932 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5933 if (SUCCEEDED(hr))
5934 IDirect3DTexture8_UnlockRect(texture, 1);
5936 IDirect3DTexture8_Release(texture);
5939 refcount = IDirect3DDevice8_Release(device);
5940 ok(!refcount, "Device has %u references left.\n", refcount);
5941 IDirect3D8_Release(d3d);
5942 DestroyWindow(window);
5945 static void test_set_palette(void)
5947 IDirect3DDevice8 *device;
5948 IDirect3D8 *d3d8;
5949 UINT refcount;
5950 HWND window;
5951 HRESULT hr;
5952 PALETTEENTRY pal[256];
5953 unsigned int i;
5954 D3DCAPS8 caps;
5956 window = create_window();
5957 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5958 ok(!!d3d8, "Failed to create a D3D object.\n");
5959 if (!(device = create_device(d3d8, window, NULL)))
5961 skip("Failed to create a D3D device, skipping tests.\n");
5962 IDirect3D8_Release(d3d8);
5963 DestroyWindow(window);
5964 return;
5967 for (i = 0; i < ARRAY_SIZE(pal); i++)
5969 pal[i].peRed = i;
5970 pal[i].peGreen = i;
5971 pal[i].peBlue = i;
5972 pal[i].peFlags = 0xff;
5974 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5975 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
5977 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5978 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5979 for (i = 0; i < ARRAY_SIZE(pal); i++)
5981 pal[i].peRed = i;
5982 pal[i].peGreen = i;
5983 pal[i].peBlue = i;
5984 pal[i].peFlags = i;
5986 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
5988 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5989 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
5991 else
5993 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5994 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
5997 refcount = IDirect3DDevice8_Release(device);
5998 ok(!refcount, "Device has %u references left.\n", refcount);
5999 IDirect3D8_Release(d3d8);
6000 DestroyWindow(window);
6003 static void test_swvp_buffer(void)
6005 IDirect3DDevice8 *device;
6006 IDirect3D8 *d3d8;
6007 UINT refcount;
6008 HWND window;
6009 HRESULT hr;
6010 unsigned int i;
6011 IDirect3DVertexBuffer8 *buffer;
6012 static const unsigned int bufsize = 1024;
6013 D3DVERTEXBUFFER_DESC desc;
6014 struct device_desc device_desc;
6015 struct
6017 float x, y, z;
6018 } *ptr, *ptr2;
6020 window = create_window();
6021 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6022 ok(!!d3d8, "Failed to create a D3D object.\n");
6024 device_desc.device_window = window;
6025 device_desc.width = 640;
6026 device_desc.height = 480;
6027 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
6028 if (!(device = create_device(d3d8, window, &device_desc)))
6030 skip("Failed to create a D3D device, skipping tests.\n");
6031 IDirect3D8_Release(d3d8);
6032 DestroyWindow(window);
6033 return;
6036 hr = IDirect3DDevice8_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
6037 D3DPOOL_DEFAULT, &buffer);
6038 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6039 hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
6040 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6041 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
6042 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
6043 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
6045 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
6046 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6047 for (i = 0; i < bufsize; i++)
6049 ptr[i].x = i * 1.0f;
6050 ptr[i].y = i * 2.0f;
6051 ptr[i].z = i * 3.0f;
6053 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6054 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6056 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
6057 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6058 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
6059 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6060 hr = IDirect3DDevice8_BeginScene(device);
6061 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6062 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6063 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6064 hr = IDirect3DDevice8_EndScene(device);
6065 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6067 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
6068 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6069 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
6070 for (i = 0; i < bufsize; i++)
6072 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6074 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
6075 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6076 break;
6079 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6080 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6082 IDirect3DVertexBuffer8_Release(buffer);
6083 refcount = IDirect3DDevice8_Release(device);
6084 ok(!refcount, "Device has %u references left.\n", refcount);
6085 IDirect3D8_Release(d3d8);
6086 DestroyWindow(window);
6089 static void test_managed_buffer(void)
6091 static const unsigned int vertex_count = 1024;
6092 IDirect3DVertexBuffer8 *buffer;
6093 D3DVERTEXBUFFER_DESC desc;
6094 IDirect3DDevice8 *device;
6095 struct vec3 *ptr, *ptr2;
6096 IDirect3D8 *d3d8;
6097 unsigned int i;
6098 UINT refcount;
6099 HWND window;
6100 HRESULT hr;
6102 window = create_window();
6103 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6104 ok(!!d3d8, "Failed to create a D3D object.\n");
6105 if (!(device = create_device(d3d8, window, NULL)))
6107 skip("Failed to create a D3D device, skipping tests.\n");
6108 IDirect3D8_Release(d3d8);
6109 DestroyWindow(window);
6110 return;
6113 hr = IDirect3DDevice8_CreateVertexBuffer(device, vertex_count * sizeof(*ptr), 0, 0, D3DPOOL_MANAGED, &buffer);
6114 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6115 hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
6116 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6117 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
6118 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
6120 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
6121 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6122 for (i = 0; i < vertex_count; ++i)
6124 ptr[i].x = i * 1.0f;
6125 ptr[i].y = i * 2.0f;
6126 ptr[i].z = i * 3.0f;
6128 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6129 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6131 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
6132 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6133 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
6134 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6135 hr = IDirect3DDevice8_BeginScene(device);
6136 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6137 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6138 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6139 hr = IDirect3DDevice8_EndScene(device);
6140 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6142 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
6143 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6144 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
6145 for (i = 0; i < vertex_count; ++i)
6147 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6149 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
6150 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6151 break;
6154 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6155 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6157 IDirect3DVertexBuffer8_Release(buffer);
6158 refcount = IDirect3DDevice8_Release(device);
6159 ok(!refcount, "Device has %u references left.\n", refcount);
6160 IDirect3D8_Release(d3d8);
6161 DestroyWindow(window);
6164 static void test_npot_textures(void)
6166 IDirect3DDevice8 *device = NULL;
6167 IDirect3D8 *d3d8;
6168 ULONG refcount;
6169 HWND window = NULL;
6170 HRESULT hr;
6171 D3DCAPS8 caps;
6172 IDirect3DTexture8 *texture;
6173 IDirect3DCubeTexture8 *cube_texture;
6174 IDirect3DVolumeTexture8 *volume_texture;
6175 struct
6177 D3DPOOL pool;
6178 const char *pool_name;
6179 HRESULT hr;
6181 pools[] =
6183 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
6184 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
6185 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
6186 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
6188 unsigned int i, levels;
6189 BOOL tex_pow2, cube_pow2, vol_pow2;
6191 window = create_window();
6192 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6193 ok(!!d3d8, "Failed to create a D3D object.\n");
6194 if (!(device = create_device(d3d8, window, NULL)))
6196 skip("Failed to create a D3D device, skipping tests.\n");
6197 goto done;
6200 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6201 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6202 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
6203 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6204 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6205 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
6206 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
6208 for (i = 0; i < ARRAY_SIZE(pools); i++)
6210 for (levels = 0; levels <= 2; levels++)
6212 HRESULT expected;
6214 hr = IDirect3DDevice8_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
6215 pools[i].pool, &texture);
6216 if (!tex_pow2)
6218 expected = D3D_OK;
6220 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
6222 if (levels == 1)
6223 expected = D3D_OK;
6224 else
6225 expected = pools[i].hr;
6227 else
6229 expected = pools[i].hr;
6231 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
6232 pools[i].pool_name, levels, hr, expected);
6234 if (SUCCEEDED(hr))
6235 IDirect3DTexture8_Release(texture);
6238 hr = IDirect3DDevice8_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8,
6239 pools[i].pool, &cube_texture);
6240 if (tex_pow2)
6242 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6243 pools[i].pool_name, hr, pools[i].hr);
6245 else
6247 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6248 pools[i].pool_name, hr, D3D_OK);
6251 if (SUCCEEDED(hr))
6252 IDirect3DCubeTexture8_Release(cube_texture);
6254 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8,
6255 pools[i].pool, &volume_texture);
6256 if (tex_pow2)
6258 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6259 pools[i].pool_name, hr, pools[i].hr);
6261 else
6263 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6264 pools[i].pool_name, hr, D3D_OK);
6267 if (SUCCEEDED(hr))
6268 IDirect3DVolumeTexture8_Release(volume_texture);
6271 done:
6272 if (device)
6274 refcount = IDirect3DDevice8_Release(device);
6275 ok(!refcount, "Device has %u references left.\n", refcount);
6277 IDirect3D8_Release(d3d8);
6278 DestroyWindow(window);
6282 static void test_volume_locking(void)
6284 IDirect3DDevice8 *device;
6285 IDirect3D8 *d3d8;
6286 HWND window;
6287 HRESULT hr;
6288 IDirect3DVolumeTexture8 *texture;
6289 unsigned int i;
6290 D3DLOCKED_BOX locked_box;
6291 ULONG refcount;
6292 D3DCAPS8 caps;
6293 static const struct
6295 D3DPOOL pool;
6296 DWORD usage;
6297 HRESULT create_hr, lock_hr;
6299 tests[] =
6301 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
6302 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6303 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
6304 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6305 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
6306 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6307 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
6308 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6311 window = create_window();
6312 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6313 ok(!!d3d8, "Failed to create a D3D object.\n");
6314 if (!(device = create_device(d3d8, window, NULL)))
6316 skip("Failed to create a D3D device, skipping tests.\n");
6317 IDirect3D8_Release(d3d8);
6318 DestroyWindow(window);
6319 return;
6322 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6323 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6324 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6326 skip("Volume textures not supported, skipping test.\n");
6327 goto out;
6330 for (i = 0; i < ARRAY_SIZE(tests); i++)
6332 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
6333 D3DFMT_A8R8G8B8, tests[i].pool, &texture);
6334 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
6335 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
6336 if (FAILED(hr))
6337 continue;
6339 locked_box.pBits = (void *)0xdeadbeef;
6340 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6341 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
6342 if (SUCCEEDED(hr))
6344 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6345 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6347 else
6349 ok (locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
6351 IDirect3DVolumeTexture8_Release(texture);
6354 out:
6355 refcount = IDirect3DDevice8_Release(device);
6356 ok(!refcount, "Device has %u references left.\n", refcount);
6357 IDirect3D8_Release(d3d8);
6358 DestroyWindow(window);
6361 static void test_update_volumetexture(void)
6363 IDirect3DDevice8 *device;
6364 IDirect3D8 *d3d8;
6365 HWND window;
6366 HRESULT hr;
6367 IDirect3DVolumeTexture8 *src, *dst;
6368 unsigned int i;
6369 D3DLOCKED_BOX locked_box;
6370 ULONG refcount;
6371 D3DCAPS8 caps;
6372 static const struct
6374 D3DPOOL src_pool, dst_pool;
6375 HRESULT hr;
6377 tests[] =
6379 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6380 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6381 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
6382 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6384 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6385 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6386 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6387 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6389 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6390 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6391 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6392 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6394 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6395 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6396 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6397 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6399 static const struct
6401 UINT src_size, dst_size;
6402 UINT src_lvl, dst_lvl;
6403 D3DFORMAT src_fmt, dst_fmt;
6405 tests2[] =
6407 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6408 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6409 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6410 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6411 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6412 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
6413 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
6414 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
6417 window = create_window();
6418 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6419 ok(!!d3d8, "Failed to create a D3D object.\n");
6420 if (!(device = create_device(d3d8, window, NULL)))
6422 skip("Failed to create a D3D device, skipping tests.\n");
6423 IDirect3D8_Release(d3d8);
6424 DestroyWindow(window);
6425 return;
6428 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6429 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6430 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6432 skip("Volume textures not supported, skipping test.\n");
6433 goto out;
6436 for (i = 0; i < ARRAY_SIZE(tests); i++)
6438 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6439 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6441 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
6442 D3DFMT_A8R8G8B8, tests[i].src_pool, &src);
6443 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6444 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
6445 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst);
6446 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6448 hr = IDirect3DVolumeTexture8_LockBox(src, 0, &locked_box, NULL, 0);
6449 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6450 *((DWORD *)locked_box.pBits) = 0x11223344;
6451 hr = IDirect3DVolumeTexture8_UnlockBox(src, 0);
6452 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6454 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src, (IDirect3DBaseTexture8 *)dst);
6455 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
6456 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
6458 if (SUCCEEDED(hr))
6460 DWORD content = *((DWORD *)locked_box.pBits);
6461 hr = IDirect3DVolumeTexture8_LockBox(dst, 0, &locked_box, NULL, 0);
6462 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6463 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
6464 hr = IDirect3DVolumeTexture8_UnlockBox(dst, 0);
6465 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6467 IDirect3DVolumeTexture8_Release(src);
6468 IDirect3DVolumeTexture8_Release(dst);
6471 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
6473 skip("Mipmapped volume maps not supported.\n");
6474 goto out;
6477 for (i = 0; i < ARRAY_SIZE(tests2); i++)
6479 hr = IDirect3DDevice8_CreateVolumeTexture(device,
6480 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
6481 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src);
6482 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6483 hr = IDirect3DDevice8_CreateVolumeTexture(device,
6484 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
6485 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst);
6486 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6488 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src, (IDirect3DBaseTexture8 *)dst);
6489 todo_wine_if (FAILED(hr))
6490 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
6492 IDirect3DVolumeTexture8_Release(src);
6493 IDirect3DVolumeTexture8_Release(dst);
6496 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
6497 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
6498 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
6499 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
6500 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
6502 * I'm not adding tests for this behavior until an application needs it. */
6504 out:
6505 refcount = IDirect3DDevice8_Release(device);
6506 ok(!refcount, "Device has %u references left.\n", refcount);
6507 IDirect3D8_Release(d3d8);
6508 DestroyWindow(window);
6511 static void test_create_rt_ds_fail(void)
6513 IDirect3DDevice8 *device;
6514 HWND window;
6515 HRESULT hr;
6516 ULONG refcount;
6517 IDirect3D8 *d3d8;
6518 IDirect3DSurface8 *surface;
6520 window = create_window();
6521 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6522 ok(!!d3d8, "Failed to create a D3D object.\n");
6523 if (!(device = create_device(d3d8, window, NULL)))
6525 skip("Failed to create a D3D device, skipping tests.\n");
6526 IDirect3D8_Release(d3d8);
6527 DestroyWindow(window);
6528 return;
6531 /* Output pointer == NULL segfaults on Windows. */
6533 surface = (IDirect3DSurface8 *)0xdeadbeef;
6534 hr = IDirect3DDevice8_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
6535 D3DMULTISAMPLE_NONE, FALSE, &surface);
6536 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
6537 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6538 if (SUCCEEDED(hr))
6539 IDirect3DSurface8_Release(surface);
6541 surface = (IDirect3DSurface8 *)0xdeadbeef;
6542 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
6543 D3DMULTISAMPLE_NONE, &surface);
6544 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
6545 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6546 if (SUCCEEDED(hr))
6547 IDirect3DSurface8_Release(surface);
6549 refcount = IDirect3DDevice8_Release(device);
6550 ok(!refcount, "Device has %u references left.\n", refcount);
6551 IDirect3D8_Release(d3d8);
6552 DestroyWindow(window);
6555 static void test_volume_blocks(void)
6557 IDirect3DDevice8 *device;
6558 IDirect3D8 *d3d8;
6559 UINT refcount;
6560 HWND window;
6561 HRESULT hr;
6562 D3DCAPS8 caps;
6563 IDirect3DVolumeTexture8 *texture;
6564 unsigned int w, h, d, i, j;
6565 static const struct
6567 D3DFORMAT fmt;
6568 const char *name;
6569 unsigned int block_width;
6570 unsigned int block_height;
6571 unsigned int block_depth;
6572 unsigned int block_size;
6573 unsigned int broken;
6574 BOOL create_size_checked, core_fmt;
6576 formats[] =
6578 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
6579 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
6580 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
6581 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
6582 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
6583 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
6584 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
6585 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
6586 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
6587 * which doesn't match the format spec. On newer Nvidia cards
6588 * it has the correct 4x4 block size.
6589 * ATI1N volume textures are only supported by AMD GPUs right
6590 * now and locking offsets seem just wrong. */
6591 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
6592 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
6593 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
6594 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
6596 static const struct
6598 D3DPOOL pool;
6599 const char *name;
6600 BOOL need_driver_support, need_runtime_support;
6602 create_tests[] =
6604 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6605 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6606 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
6607 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
6609 static const struct
6611 unsigned int x, y, z, x2, y2, z2;
6613 offset_tests[] =
6615 {0, 0, 0, 8, 8, 8},
6616 {0, 0, 3, 8, 8, 8},
6617 {0, 4, 0, 8, 8, 8},
6618 {0, 4, 3, 8, 8, 8},
6619 {4, 0, 0, 8, 8, 8},
6620 {4, 0, 3, 8, 8, 8},
6621 {4, 4, 0, 8, 8, 8},
6622 {4, 4, 3, 8, 8, 8},
6624 D3DBOX box;
6625 D3DLOCKED_BOX locked_box;
6626 BYTE *base;
6627 INT expected_row_pitch, expected_slice_pitch;
6628 BOOL support;
6629 BOOL pow2;
6630 unsigned int offset, expected_offset;
6632 window = create_window();
6633 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6634 ok(!!d3d8, "Failed to create a D3D object.\n");
6635 if (!(device = create_device(d3d8, window, NULL)))
6637 skip("Failed to create a D3D device, skipping tests.\n");
6638 IDirect3D8_Release(d3d8);
6639 DestroyWindow(window);
6640 return;
6642 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6643 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6644 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6646 for (i = 0; i < ARRAY_SIZE(formats); i++)
6648 hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6649 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
6650 support = SUCCEEDED(hr);
6652 /* Test creation restrictions */
6653 for (w = 1; w <= 8; w++)
6655 for (h = 1; h <= 8; h++)
6657 for (d = 1; d <= 8; d++)
6659 HRESULT expect_hr;
6660 BOOL size_is_pow2;
6661 BOOL block_aligned = TRUE;
6663 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6664 block_aligned = FALSE;
6666 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
6668 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
6670 BOOL may_succeed = FALSE;
6672 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
6673 expect_hr = D3DERR_INVALIDCALL;
6674 else if (formats[i].create_size_checked && !block_aligned)
6675 expect_hr = D3DERR_INVALIDCALL;
6676 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6677 expect_hr = D3DERR_INVALIDCALL;
6678 else if (create_tests[j].need_driver_support && !support)
6679 expect_hr = D3DERR_INVALIDCALL;
6680 else
6681 expect_hr = D3D_OK;
6683 texture = (IDirect3DVolumeTexture8 *)0xdeadbeef;
6684 hr = IDirect3DDevice8_CreateVolumeTexture(device, w, h, d, 1, 0,
6685 formats[i].fmt, create_tests[j].pool, &texture);
6687 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6688 * does not support it. Accept scratch creation of extension formats on
6689 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6690 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6691 * support it. */
6692 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
6693 may_succeed = TRUE;
6695 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6696 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
6697 hr, formats[i].name, create_tests[j].name, w, h, d);
6699 if (FAILED(hr))
6700 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
6701 else
6702 IDirect3DVolumeTexture8_Release(texture);
6708 if (!support && !formats[i].core_fmt)
6709 continue;
6711 hr = IDirect3DDevice8_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
6712 formats[i].fmt, D3DPOOL_SCRATCH, &texture);
6713 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6715 /* Test lockrect offset */
6716 for (j = 0; j < ARRAY_SIZE(offset_tests); j++)
6718 unsigned int bytes_per_pixel;
6719 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
6721 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6722 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6724 base = locked_box.pBits;
6725 if (formats[i].broken == 1)
6727 expected_row_pitch = bytes_per_pixel * 24;
6729 else if (formats[i].broken == 2)
6731 expected_row_pitch = 24;
6733 else
6735 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
6736 * formats[i].block_size;
6738 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
6739 locked_box.RowPitch, formats[i].name, expected_row_pitch);
6741 if (formats[i].broken)
6743 expected_slice_pitch = expected_row_pitch * 8;
6745 else
6747 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
6748 * expected_row_pitch;
6750 ok(locked_box.SlicePitch == expected_slice_pitch,
6751 "Got unexpected slice pitch %d for format %s, expected %d.\n",
6752 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
6754 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6755 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
6757 box.Left = offset_tests[j].x;
6758 box.Top = offset_tests[j].y;
6759 box.Front = offset_tests[j].z;
6760 box.Right = offset_tests[j].x2;
6761 box.Bottom = offset_tests[j].y2;
6762 box.Back = offset_tests[j].z2;
6763 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6764 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
6766 offset = (BYTE *)locked_box.pBits - base;
6767 if (formats[i].broken == 1)
6769 expected_offset = box.Front * expected_slice_pitch
6770 + box.Top * expected_row_pitch
6771 + box.Left * bytes_per_pixel;
6773 else if (formats[i].broken == 2)
6775 expected_offset = box.Front * expected_slice_pitch
6776 + box.Top * expected_row_pitch
6777 + box.Left;
6779 else
6781 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
6782 + (box.Top / formats[i].block_height) * expected_row_pitch
6783 + (box.Left / formats[i].block_width) * formats[i].block_size;
6785 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
6786 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
6788 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6789 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6792 /* Test partial block locks */
6793 box.Front = 0;
6794 box.Back = 1;
6795 if (formats[i].block_width > 1)
6797 box.Left = formats[i].block_width >> 1;
6798 box.Top = 0;
6799 box.Right = formats[i].block_width;
6800 box.Bottom = formats[i].block_height;
6801 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6802 ok(FAILED(hr) || broken(formats[i].broken),
6803 "Partial block lock succeeded, expected failure, format %s.\n",
6804 formats[i].name);
6805 if (SUCCEEDED(hr))
6807 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6808 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6811 box.Left = 0;
6812 box.Top = 0;
6813 box.Right = formats[i].block_width >> 1;
6814 box.Bottom = formats[i].block_height;
6815 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6816 ok(FAILED(hr) || broken(formats[i].broken),
6817 "Partial block lock succeeded, expected failure, format %s.\n",
6818 formats[i].name);
6819 if (SUCCEEDED(hr))
6821 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6822 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6826 if (formats[i].block_height > 1)
6828 box.Left = 0;
6829 box.Top = formats[i].block_height >> 1;
6830 box.Right = formats[i].block_width;
6831 box.Bottom = formats[i].block_height;
6832 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6833 ok(FAILED(hr) || broken(formats[i].broken),
6834 "Partial block lock succeeded, expected failure, format %s.\n",
6835 formats[i].name);
6836 if (SUCCEEDED(hr))
6838 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6839 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6842 box.Left = 0;
6843 box.Top = 0;
6844 box.Right = formats[i].block_width;
6845 box.Bottom = formats[i].block_height >> 1;
6846 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6847 ok(FAILED(hr) || broken(formats[i].broken),
6848 "Partial block lock succeeded, expected failure, format %s.\n",
6849 formats[i].name);
6850 if (SUCCEEDED(hr))
6852 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6853 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6857 /* Test full block lock */
6858 box.Left = 0;
6859 box.Top = 0;
6860 box.Right = formats[i].block_width;
6861 box.Bottom = formats[i].block_height;
6862 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6863 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6864 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6865 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6867 IDirect3DVolumeTexture8_Release(texture);
6869 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
6870 * does not allocate surfaces smaller than the blocksize properly. */
6871 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
6873 hr = IDirect3DDevice8_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
6874 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture);
6876 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
6877 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, NULL, 0);
6878 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
6879 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6880 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6882 box.Left = box.Top = box.Front = 0;
6883 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
6884 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
6885 box.Back = 1;
6886 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
6887 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
6888 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6889 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6891 box.Right = formats[i].block_width;
6892 box.Bottom = formats[i].block_height;
6893 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
6894 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6895 if (SUCCEEDED(hr))
6896 IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6898 IDirect3DVolumeTexture8_Release(texture);
6902 refcount = IDirect3DDevice8_Release(device);
6903 ok(!refcount, "Device has %u references left.\n", refcount);
6904 IDirect3D8_Release(d3d8);
6905 DestroyWindow(window);
6908 static void test_lockbox_invalid(void)
6910 static const struct
6912 D3DBOX box;
6913 HRESULT result;
6915 test_data[] =
6917 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
6918 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
6919 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
6920 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
6921 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
6922 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
6923 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
6924 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
6925 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
6926 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
6927 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
6928 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
6929 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
6930 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
6932 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
6933 IDirect3DVolumeTexture8 *texture = NULL;
6934 D3DLOCKED_BOX locked_box;
6935 IDirect3DDevice8 *device;
6936 IDirect3D8 *d3d;
6937 unsigned int i;
6938 ULONG refcount;
6939 HWND window;
6940 BYTE *base;
6941 HRESULT hr;
6943 window = create_window();
6944 d3d = Direct3DCreate8(D3D_SDK_VERSION);
6945 ok(!!d3d, "Failed to create a D3D object.\n");
6946 if (!(device = create_device(d3d, window, NULL)))
6948 skip("Failed to create a D3D device, skipping tests.\n");
6949 IDirect3D8_Release(d3d);
6950 DestroyWindow(window);
6951 return;
6954 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
6955 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
6956 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6957 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6958 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6959 base = locked_box.pBits;
6960 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6961 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6963 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
6965 unsigned int offset, expected_offset;
6966 const D3DBOX *box = &test_data[i].box;
6968 locked_box.pBits = (BYTE *)0xdeadbeef;
6969 locked_box.RowPitch = 0xdeadbeef;
6970 locked_box.SlicePitch = 0xdeadbeef;
6972 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, box, 0);
6973 /* Unlike surfaces, volumes properly check the box even in Windows XP */
6974 ok(hr == test_data[i].result,
6975 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
6976 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
6977 test_data[i].result);
6978 if (FAILED(hr))
6979 continue;
6981 offset = (BYTE *)locked_box.pBits - base;
6982 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
6983 ok(offset == expected_offset,
6984 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
6985 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
6987 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6988 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6991 /* locked_box = NULL throws an exception on Windows */
6992 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6993 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6994 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6995 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6996 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6997 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6998 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6999 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7001 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7002 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7003 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7004 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7005 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7006 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7007 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7008 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7009 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
7010 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
7011 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
7012 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
7013 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7014 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
7016 IDirect3DVolumeTexture8_Release(texture);
7017 refcount = IDirect3DDevice8_Release(device);
7018 ok(!refcount, "Device has %u references left.\n", refcount);
7019 IDirect3D8_Release(d3d);
7020 DestroyWindow(window);
7023 static void test_pixel_format(void)
7025 int format, test_format;
7026 PIXELFORMATDESCRIPTOR pfd;
7027 IDirect3D8 *d3d8 = NULL;
7028 IDirect3DDevice8 *device = NULL;
7029 HWND hwnd, hwnd2;
7030 HDC hdc, hdc2;
7031 HMODULE gl;
7032 HRESULT hr;
7034 static const float point[] = {0.0f, 0.0f, 0.0f};
7036 hwnd = create_window();
7037 ok(!!hwnd, "Failed to create window.\n");
7038 hwnd2 = create_window();
7039 ok(!!hwnd2, "Failed to create window.\n");
7041 hdc = GetDC(hwnd);
7042 ok(!!hdc, "Failed to get DC.\n");
7043 hdc2 = GetDC(hwnd2);
7044 ok(!!hdc2, "Failed to get DC.\n");
7046 gl = LoadLibraryA("opengl32.dll");
7047 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7049 format = GetPixelFormat(hdc);
7050 ok(format == 0, "new window has pixel format %d\n", format);
7052 ZeroMemory(&pfd, sizeof(pfd));
7053 pfd.nSize = sizeof(pfd);
7054 pfd.nVersion = 1;
7055 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7056 pfd.iPixelType = PFD_TYPE_RGBA;
7057 pfd.iLayerType = PFD_MAIN_PLANE;
7058 format = ChoosePixelFormat(hdc, &pfd);
7059 if (format <= 0)
7061 skip("no pixel format available\n");
7062 goto cleanup;
7065 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7067 skip("failed to set pixel format\n");
7068 goto cleanup;
7071 if (!SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7073 skip("failed to set pixel format on second window\n");
7074 goto cleanup;
7077 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7078 ok(!!d3d8, "Failed to create a D3D object.\n");
7080 test_format = GetPixelFormat(hdc);
7081 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7083 if (!(device = create_device(d3d8, hwnd, NULL)))
7085 skip("Failed to create device\n");
7086 goto cleanup;
7089 test_format = GetPixelFormat(hdc);
7090 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7092 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
7093 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
7095 test_format = GetPixelFormat(hdc);
7096 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7098 hr = IDirect3DDevice8_BeginScene(device);
7099 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
7101 test_format = GetPixelFormat(hdc);
7102 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7104 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
7105 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7107 test_format = GetPixelFormat(hdc);
7108 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7110 hr = IDirect3DDevice8_EndScene(device);
7111 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
7113 test_format = GetPixelFormat(hdc);
7114 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7116 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7117 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
7119 test_format = GetPixelFormat(hdc);
7120 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7122 hr = IDirect3DDevice8_Present(device, NULL, NULL, hwnd2, NULL);
7123 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
7125 test_format = GetPixelFormat(hdc);
7126 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7128 test_format = GetPixelFormat(hdc2);
7129 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7131 cleanup:
7132 if (device)
7134 UINT refcount = IDirect3DDevice8_Release(device);
7135 ok(!refcount, "Device has %u references left.\n", refcount);
7137 if (d3d8)
7138 IDirect3D8_Release(d3d8);
7139 FreeLibrary(gl);
7140 ReleaseDC(hwnd2, hdc2);
7141 ReleaseDC(hwnd, hdc);
7142 DestroyWindow(hwnd2);
7143 DestroyWindow(hwnd);
7146 static void test_begin_end_state_block(void)
7148 IDirect3DDevice8 *device;
7149 DWORD stateblock;
7150 IDirect3D8 *d3d;
7151 ULONG refcount;
7152 HWND window;
7153 HRESULT hr;
7155 window = create_window();
7156 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7157 ok(!!d3d, "Failed to create a D3D object.\n");
7158 if (!(device = create_device(d3d, window, NULL)))
7160 skip("Failed to create a D3D device, skipping tests.\n");
7161 IDirect3D8_Release(d3d);
7162 DestroyWindow(window);
7163 return;
7166 /* Should succeed. */
7167 hr = IDirect3DDevice8_BeginStateBlock(device);
7168 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
7170 /* Calling BeginStateBlock() while recording should return
7171 * D3DERR_INVALIDCALL. */
7172 hr = IDirect3DDevice8_BeginStateBlock(device);
7173 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7175 /* Should succeed. */
7176 stateblock = 0xdeadbeef;
7177 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7178 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
7179 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
7180 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
7182 /* Calling EndStateBlock() while not recording should return
7183 * D3DERR_INVALIDCALL. stateblock should not be touched. */
7184 stateblock = 0xdeadbeef;
7185 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7186 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7187 ok(stateblock == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
7189 refcount = IDirect3DDevice8_Release(device);
7190 ok(!refcount, "Device has %u references left.\n", refcount);
7191 IDirect3D8_Release(d3d);
7192 DestroyWindow(window);
7195 static void test_shader_constant_apply(void)
7197 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
7198 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
7199 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
7200 DWORD vs_version, ps_version;
7201 IDirect3DDevice8 *device;
7202 DWORD stateblock;
7203 IDirect3D8 *d3d;
7204 ULONG refcount;
7205 D3DCAPS8 caps;
7206 float ret[4];
7207 HWND window;
7208 HRESULT hr;
7210 window = create_window();
7211 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7212 ok(!!d3d, "Failed to create a D3D object.\n");
7213 if (!(device = create_device(d3d, window, NULL)))
7215 skip("Failed to create a D3D device, skipping tests.\n");
7216 IDirect3D8_Release(d3d);
7217 DestroyWindow(window);
7218 return;
7221 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7222 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7223 vs_version = caps.VertexShaderVersion & 0xffff;
7224 ps_version = caps.PixelShaderVersion & 0xffff;
7226 if (vs_version)
7228 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, initial, 1);
7229 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7230 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, initial, 1);
7231 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7233 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7234 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7235 ok(!memcmp(ret, initial, sizeof(initial)),
7236 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7237 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7238 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7239 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7240 ok(!memcmp(ret, initial, sizeof(initial)),
7241 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7242 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7244 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, vs_const, 1);
7245 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7247 if (ps_version)
7249 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, initial, 1);
7250 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7251 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, initial, 1);
7252 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7254 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7255 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7256 ok(!memcmp(ret, initial, sizeof(initial)),
7257 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7258 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7259 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7260 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7261 ok(!memcmp(ret, initial, sizeof(initial)),
7262 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7263 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7265 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, ps_const, 1);
7266 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7269 hr = IDirect3DDevice8_BeginStateBlock(device);
7270 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
7272 if (vs_version)
7274 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, vs_const, 1);
7275 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7277 if (ps_version)
7279 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, ps_const, 1);
7280 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7283 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7284 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
7286 if (vs_version)
7288 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7289 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7290 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7291 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7292 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7293 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7294 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7295 ok(!memcmp(ret, initial, sizeof(initial)),
7296 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7297 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7299 if (ps_version)
7301 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7302 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7303 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7304 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7305 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7306 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7307 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7308 ok(!memcmp(ret, initial, sizeof(initial)),
7309 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7310 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7313 /* Apply doesn't overwrite constants that aren't explicitly set on the
7314 * source stateblock. */
7315 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
7316 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
7318 if (vs_version)
7320 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7321 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7322 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7323 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7324 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7325 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7326 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7327 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7328 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7329 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7331 if (ps_version)
7333 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7334 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7335 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7336 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7337 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7338 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7339 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7340 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7341 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7342 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7345 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
7346 refcount = IDirect3DDevice8_Release(device);
7347 ok(!refcount, "Device has %u references left.\n", refcount);
7348 IDirect3D8_Release(d3d);
7349 DestroyWindow(window);
7352 static void test_resource_type(void)
7354 IDirect3DDevice8 *device;
7355 IDirect3DSurface8 *surface;
7356 IDirect3DTexture8 *texture;
7357 IDirect3DCubeTexture8 *cube_texture;
7358 IDirect3DVolume8 *volume;
7359 IDirect3DVolumeTexture8 *volume_texture;
7360 D3DSURFACE_DESC surface_desc;
7361 D3DVOLUME_DESC volume_desc;
7362 D3DRESOURCETYPE type;
7363 IDirect3D8 *d3d;
7364 ULONG refcount;
7365 HWND window;
7366 HRESULT hr;
7367 D3DCAPS8 caps;
7369 window = create_window();
7370 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7371 ok(!!d3d, "Failed to create a D3D object.\n");
7372 if (!(device = create_device(d3d, window, NULL)))
7374 skip("Failed to create a D3D device, skipping tests.\n");
7375 IDirect3D8_Release(d3d);
7376 DestroyWindow(window);
7377 return;
7380 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7381 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7383 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_X8R8G8B8, &surface);
7384 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7385 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7386 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7387 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7388 surface_desc.Type);
7389 IDirect3DSurface8_Release(surface);
7391 hr = IDirect3DDevice8_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
7392 D3DPOOL_SYSTEMMEM, &texture);
7393 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7394 type = IDirect3DTexture8_GetType(texture);
7395 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
7397 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
7398 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7399 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7400 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7401 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7402 surface_desc.Type);
7403 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
7404 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
7405 hr = IDirect3DTexture8_GetLevelDesc(texture, 0, &surface_desc);
7406 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7407 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7408 surface_desc.Type);
7409 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
7410 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
7411 IDirect3DSurface8_Release(surface);
7413 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 2, &surface);
7414 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7415 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7416 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7417 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7418 surface_desc.Type);
7419 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
7420 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
7421 hr = IDirect3DTexture8_GetLevelDesc(texture, 2, &surface_desc);
7422 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7423 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7424 surface_desc.Type);
7425 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
7426 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
7427 IDirect3DSurface8_Release(surface);
7428 IDirect3DTexture8_Release(texture);
7430 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7432 hr = IDirect3DDevice8_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
7433 D3DPOOL_SYSTEMMEM, &cube_texture);
7434 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
7435 type = IDirect3DCubeTexture8_GetType(cube_texture);
7436 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
7438 hr = IDirect3DCubeTexture8_GetCubeMapSurface(cube_texture,
7439 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7440 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
7441 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7442 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7443 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7444 surface_desc.Type);
7445 hr = IDirect3DCubeTexture8_GetLevelDesc(cube_texture, 0, &surface_desc);
7446 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7447 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7448 surface_desc.Type);
7449 IDirect3DSurface8_Release(surface);
7450 IDirect3DCubeTexture8_Release(cube_texture);
7452 else
7453 skip("Cube maps not supported.\n");
7455 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
7457 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
7458 D3DPOOL_SYSTEMMEM, &volume_texture);
7459 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
7460 type = IDirect3DVolumeTexture8_GetType(volume_texture);
7461 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
7463 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 0, &volume);
7464 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
7465 /* IDirect3DVolume8 is not an IDirect3DResource8 and has no GetType method. */
7466 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
7467 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
7468 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7469 volume_desc.Type);
7470 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
7471 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
7472 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
7473 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 0, &volume_desc);
7474 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7475 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7476 volume_desc.Type);
7477 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
7478 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
7479 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
7480 IDirect3DVolume8_Release(volume);
7482 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 2, &volume);
7483 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
7484 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
7485 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
7486 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7487 volume_desc.Type);
7488 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
7489 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
7490 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
7491 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 2, &volume_desc);
7492 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7493 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7494 volume_desc.Type);
7495 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
7496 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
7497 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
7498 IDirect3DVolume8_Release(volume);
7499 IDirect3DVolumeTexture8_Release(volume_texture);
7501 else
7502 skip("Mipmapped volume maps not supported.\n");
7504 refcount = IDirect3DDevice8_Release(device);
7505 ok(!refcount, "Device has %u references left.\n", refcount);
7506 IDirect3D8_Release(d3d);
7507 DestroyWindow(window);
7510 static void test_mipmap_lock(void)
7512 IDirect3DDevice8 *device;
7513 IDirect3DSurface8 *surface, *surface2, *surface_dst, *surface_dst2;
7514 IDirect3DTexture8 *texture, *texture_dst;
7515 IDirect3D8 *d3d;
7516 ULONG refcount;
7517 HWND window;
7518 HRESULT hr;
7519 D3DLOCKED_RECT locked_rect;
7521 window = create_window();
7522 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7523 ok(!!d3d, "Failed to create a D3D object.\n");
7524 if (!(device = create_device(d3d, window, NULL)))
7526 skip("Failed to create a D3D device, skipping tests.\n");
7527 IDirect3D8_Release(d3d);
7528 DestroyWindow(window);
7529 return;
7532 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
7533 D3DPOOL_DEFAULT, &texture_dst);
7534 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7535 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 0, &surface_dst);
7536 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7537 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
7538 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7540 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
7541 D3DPOOL_SYSTEMMEM, &texture);
7542 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7543 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
7544 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7545 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
7546 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7548 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
7549 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7550 hr = IDirect3DSurface8_LockRect(surface2, &locked_rect, NULL, 0);
7551 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7552 hr = IDirect3DSurface8_UnlockRect(surface);
7553 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7555 hr = IDirect3DDevice8_CopyRects(device, surface, NULL, 0, surface_dst, NULL);
7556 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
7557 hr = IDirect3DDevice8_CopyRects(device, surface2, NULL, 0, surface_dst2, NULL);
7558 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7560 /* Apparently there's no validation on the container. */
7561 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)texture,
7562 (IDirect3DBaseTexture8 *)texture_dst);
7563 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
7565 hr = IDirect3DSurface8_UnlockRect(surface2);
7566 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7568 IDirect3DSurface8_Release(surface_dst2);
7569 IDirect3DSurface8_Release(surface_dst);
7570 IDirect3DSurface8_Release(surface2);
7571 IDirect3DSurface8_Release(surface);
7572 IDirect3DTexture8_Release(texture_dst);
7573 IDirect3DTexture8_Release(texture);
7575 refcount = IDirect3DDevice8_Release(device);
7576 ok(!refcount, "Device has %u references left.\n", refcount);
7577 IDirect3D8_Release(d3d);
7578 DestroyWindow(window);
7581 static void test_writeonly_resource(void)
7583 IDirect3D8 *d3d;
7584 IDirect3DDevice8 *device;
7585 IDirect3DVertexBuffer8 *buffer;
7586 ULONG refcount;
7587 HWND window;
7588 HRESULT hr;
7589 BYTE *ptr;
7590 static const struct
7592 struct vec3 pos;
7594 quad[] =
7596 {{-1.0f, -1.0f, 0.0f}},
7597 {{-1.0f, 1.0f, 0.0f}},
7598 {{ 1.0f, -1.0f, 0.0f}},
7599 {{ 1.0f, 1.0f, 0.0f}}
7602 window = create_window();
7603 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7604 ok(!!d3d, "Failed to create a D3D object.\n");
7605 if (!(device = create_device(d3d, window, NULL)))
7607 skip("Failed to create a D3D device, skipping tests.\n");
7608 IDirect3D8_Release(d3d);
7609 DestroyWindow(window);
7610 return;
7613 hr = IDirect3DDevice8_CreateVertexBuffer(device, sizeof(quad),
7614 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer);
7615 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
7617 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
7618 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7619 memcpy(ptr, quad, sizeof(quad));
7620 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7621 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7622 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*quad));
7623 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
7624 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
7625 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
7627 hr = IDirect3DDevice8_BeginScene(device);
7628 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
7629 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7630 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7631 hr = IDirect3DDevice8_EndScene(device);
7632 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
7634 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, 0);
7635 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7636 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7637 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7638 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7640 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
7641 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7642 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7643 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7644 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7646 refcount = IDirect3DVertexBuffer8_Release(buffer);
7647 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
7648 refcount = IDirect3DDevice8_Release(device);
7649 ok(!refcount, "Device has %u references left.\n", refcount);
7650 IDirect3D8_Release(d3d);
7651 DestroyWindow(window);
7654 static void test_lost_device(void)
7656 struct device_desc device_desc;
7657 IDirect3DDevice8 *device;
7658 IDirect3D8 *d3d;
7659 ULONG refcount;
7660 HWND window;
7661 HRESULT hr;
7662 BOOL ret;
7664 window = create_window();
7665 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7666 ok(!!d3d, "Failed to create a D3D object.\n");
7667 device_desc.device_window = window;
7668 device_desc.width = registry_mode.dmPelsWidth;
7669 device_desc.height = registry_mode.dmPelsHeight;
7670 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
7671 if (!(device = create_device(d3d, window, &device_desc)))
7673 skip("Failed to create a D3D device, skipping tests.\n");
7674 goto done;
7677 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7678 if (hr == D3DERR_DEVICELOST)
7680 win_skip("Broken TestCooperativeLevel(), skipping test.\n");
7681 IDirect3DDevice8_Release(device);
7682 goto done;
7684 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7685 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7686 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7688 ret = SetForegroundWindow(GetDesktopWindow());
7689 ok(ret, "Failed to set foreground window.\n");
7690 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7691 /* The device is not lost on Windows 10. */
7692 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7693 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7694 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7696 ret = ShowWindow(window, SW_RESTORE);
7697 ok(ret, "Failed to restore window.\n");
7698 ret = SetForegroundWindow(window);
7699 ok(ret, "Failed to set foreground window.\n");
7700 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7701 ok(hr == D3DERR_DEVICENOTRESET || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7702 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7703 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7705 hr = reset_device(device, &device_desc);
7706 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7707 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7708 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7709 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7710 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7712 device_desc.flags = 0;
7713 hr = reset_device(device, &device_desc);
7714 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7715 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7716 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7717 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7718 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7720 ret = SetForegroundWindow(GetDesktopWindow());
7721 ok(ret, "Failed to set foreground window.\n");
7722 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7723 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7724 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7725 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7727 ret = ShowWindow(window, SW_RESTORE);
7728 ok(ret, "Failed to restore window.\n");
7729 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7730 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7731 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7732 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7734 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
7735 hr = reset_device(device, &device_desc);
7736 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7737 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7738 /* The device is not lost on Windows 10. */
7739 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7740 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7741 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7743 ret = SetForegroundWindow(GetDesktopWindow());
7744 ok(ret, "Failed to set foreground window.\n");
7745 hr = reset_device(device, &device_desc);
7746 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7747 ret = ShowWindow(window, SW_RESTORE);
7748 ok(ret, "Failed to restore window.\n");
7749 ret = SetForegroundWindow(window);
7750 ok(ret, "Failed to set foreground window.\n");
7751 hr = reset_device(device, &device_desc);
7752 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7754 refcount = IDirect3DDevice8_Release(device);
7755 ok(!refcount, "Device has %u references left.\n", refcount);
7756 done:
7757 IDirect3D8_Release(d3d);
7758 DestroyWindow(window);
7761 static void test_resource_priority(void)
7763 IDirect3DDevice8 *device;
7764 IDirect3DTexture8 *texture;
7765 IDirect3DVertexBuffer8 *buffer;
7766 IDirect3D8 *d3d;
7767 ULONG refcount;
7768 HWND window;
7769 HRESULT hr;
7770 static const struct
7772 D3DPOOL pool;
7773 const char *name;
7774 BOOL can_set_priority;
7776 test_data[] =
7778 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
7779 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
7780 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
7781 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
7783 unsigned int i;
7784 DWORD priority;
7786 window = create_window();
7787 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7788 ok(!!d3d, "Failed to create a D3D object.\n");
7789 if (!(device = create_device(d3d, window, NULL)))
7791 skip("Failed to create a D3D device, skipping tests.\n");
7792 IDirect3D8_Release(d3d);
7793 DestroyWindow(window);
7794 return;
7797 for (i = 0; i < ARRAY_SIZE(test_data); i++)
7799 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
7800 test_data[i].pool, &texture);
7801 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
7803 priority = IDirect3DTexture8_GetPriority(texture);
7804 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7805 priority = IDirect3DTexture8_SetPriority(texture, 1);
7806 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7807 priority = IDirect3DTexture8_GetPriority(texture);
7808 if (test_data[i].can_set_priority)
7810 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7811 priority = IDirect3DTexture8_SetPriority(texture, 0);
7812 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7814 else
7815 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7817 IDirect3DTexture8_Release(texture);
7819 if (test_data[i].pool != D3DPOOL_SCRATCH)
7821 hr = IDirect3DDevice8_CreateVertexBuffer(device, 256, 0, 0,
7822 test_data[i].pool, &buffer);
7823 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
7825 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
7826 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7827 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 1);
7828 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7829 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
7830 if (test_data[i].can_set_priority)
7832 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7833 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 0);
7834 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7836 else
7837 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7839 IDirect3DVertexBuffer8_Release(buffer);
7843 refcount = IDirect3DDevice8_Release(device);
7844 ok(!refcount, "Device has %u references left.\n", refcount);
7845 IDirect3D8_Release(d3d);
7846 DestroyWindow(window);
7849 static void test_swapchain_parameters(void)
7851 IDirect3DSurface8 *backbuffer;
7852 IDirect3DDevice8 *device;
7853 HRESULT hr, expected_hr;
7854 IDirect3D8 *d3d;
7855 D3DCAPS8 caps;
7856 HWND window;
7857 unsigned int i, j;
7858 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0};
7859 static const struct
7861 BOOL windowed;
7862 UINT backbuffer_count;
7863 D3DSWAPEFFECT swap_effect;
7864 HRESULT hr;
7866 tests[] =
7868 /* Swap effect 0 is not allowed. */
7869 {TRUE, 1, 0, D3DERR_INVALIDCALL},
7870 {FALSE, 1, 0, D3DERR_INVALIDCALL},
7872 /* All (non-ex) swap effects are allowed in
7873 * windowed and fullscreen mode. */
7874 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
7875 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
7876 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
7877 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
7878 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
7880 /* Only one backbuffer in copy mode. Reset allows it for
7881 * some reason. */
7882 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
7883 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
7884 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
7885 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
7886 {TRUE, 0, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
7887 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
7888 {TRUE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
7889 {FALSE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
7891 /* Ok with the others, in fullscreen and windowed mode. */
7892 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
7893 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
7894 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
7895 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
7897 /* Invalid swapeffects. */
7898 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
7899 {FALSE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
7901 /* 3 is the highest allowed backbuffer count. */
7902 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
7903 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
7904 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
7905 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
7906 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
7909 window = create_window();
7910 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7911 ok(!!d3d, "Failed to create a D3D object.\n");
7912 if (!(device = create_device(d3d, window, NULL)))
7914 skip("Failed to create a D3D device, skipping tests.\n");
7915 IDirect3D8_Release(d3d);
7916 DestroyWindow(window);
7917 return;
7919 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7920 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7921 IDirect3DDevice8_Release(device);
7923 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
7924 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
7925 present_parameters_windowed.hDeviceWindow = window;
7926 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
7927 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
7928 present_parameters_windowed.Windowed = TRUE;
7929 present_parameters_windowed.BackBufferCount = 1;
7931 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7933 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
7935 memset(&present_parameters, 0, sizeof(present_parameters));
7936 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
7937 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
7938 present_parameters.hDeviceWindow = window;
7939 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
7941 present_parameters.SwapEffect = tests[i].swap_effect;
7942 present_parameters.Windowed = tests[i].windowed;
7943 present_parameters.BackBufferCount = tests[i].backbuffer_count;
7945 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
7946 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
7947 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
7948 if (SUCCEEDED(hr))
7950 for (j = 0; j < bb_count; ++j)
7952 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7953 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#x, test %u.\n", j, hr, i);
7954 IDirect3DSurface8_Release(backbuffer);
7956 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7957 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %x, test %u.\n", hr, i);
7959 IDirect3DDevice8_Release(device);
7962 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
7963 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
7964 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
7966 memset(&present_parameters, 0, sizeof(present_parameters));
7967 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
7968 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
7969 present_parameters.hDeviceWindow = window;
7970 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
7972 present_parameters.SwapEffect = tests[i].swap_effect;
7973 present_parameters.Windowed = tests[i].windowed;
7974 present_parameters.BackBufferCount = tests[i].backbuffer_count;
7976 hr = IDirect3DDevice8_Reset(device, &present_parameters);
7977 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
7979 if (FAILED(hr))
7981 hr = IDirect3DDevice8_Reset(device, &present_parameters_windowed);
7982 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
7984 else
7986 for (j = 0; j < bb_count; ++j)
7988 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7989 todo_wine_if (j)
7990 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#x, test %u.\n", j, hr, i);
7991 if (SUCCEEDED(hr))
7992 IDirect3DSurface8_Release(backbuffer);
7994 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7995 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %x, test %u.\n", hr, i);
7997 IDirect3DDevice8_Release(device);
8000 for (i = 0; i < 10; ++i)
8002 memset(&present_parameters, 0, sizeof(present_parameters));
8003 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
8004 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
8005 present_parameters.hDeviceWindow = window;
8006 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
8007 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
8008 present_parameters.Windowed = FALSE;
8009 present_parameters.BackBufferCount = 2;
8011 present_parameters.FullScreen_PresentationInterval = i;
8012 switch (present_parameters.FullScreen_PresentationInterval)
8014 case D3DPRESENT_INTERVAL_ONE:
8015 case D3DPRESENT_INTERVAL_TWO:
8016 case D3DPRESENT_INTERVAL_THREE:
8017 case D3DPRESENT_INTERVAL_FOUR:
8018 if (!(caps.PresentationIntervals & present_parameters.FullScreen_PresentationInterval))
8019 continue;
8020 /* Fall through */
8021 case D3DPRESENT_INTERVAL_DEFAULT:
8022 expected_hr = D3D_OK;
8023 break;
8024 default:
8025 expected_hr = D3DERR_INVALIDCALL;
8026 break;
8029 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
8030 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
8031 ok(hr == expected_hr, "Got unexpected hr %#x, test %u.\n", hr, i);
8032 if (SUCCEEDED(hr))
8033 IDirect3DDevice8_Release(device);
8036 IDirect3D8_Release(d3d);
8037 DestroyWindow(window);
8040 static void test_check_device_format(void)
8042 D3DDEVTYPE device_type;
8043 IDirect3D8 *d3d;
8044 HRESULT hr;
8046 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8047 ok(!!d3d, "Failed to create a D3D object.\n");
8049 for (device_type = D3DDEVTYPE_HAL; device_type <= D3DDEVTYPE_SW; ++device_type)
8051 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8052 0, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
8053 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
8054 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8055 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
8056 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
8057 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8058 0, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
8059 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
8060 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8061 0, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
8062 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
8065 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8066 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
8067 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8068 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8069 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
8070 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8071 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8072 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
8073 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8075 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8076 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
8077 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8078 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8079 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
8080 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8081 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8082 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
8083 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8085 IDirect3D8_Release(d3d);
8088 static void test_miptree_layout(void)
8090 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
8091 IDirect3DCubeTexture8 *texture_cube;
8092 IDirect3DTexture8 *texture_2d;
8093 IDirect3DDevice8 *device;
8094 D3DLOCKED_RECT map_desc;
8095 BYTE *base = NULL;
8096 IDirect3D8 *d3d;
8097 D3DCAPS8 caps;
8098 UINT refcount;
8099 HWND window;
8100 HRESULT hr;
8102 static const struct
8104 D3DFORMAT format;
8105 const char *name;
8107 formats[] =
8109 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
8110 {D3DFMT_A8, "D3DFMT_A8"},
8111 {D3DFMT_L8, "D3DFMT_L8"},
8112 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
8113 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
8115 static const struct
8117 D3DPOOL pool;
8118 const char *name;
8120 pools[] =
8122 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
8123 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
8124 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
8127 window = create_window();
8128 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8129 ok(!!d3d, "Failed to create a D3D object.\n");
8130 if (!(device = create_device(d3d, window, NULL)))
8132 skip("Failed to create a D3D device, skipping tests.\n");
8133 goto done;
8136 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
8137 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8139 base_dimension = 257;
8140 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
8142 skip("Using power of two base dimension.\n");
8143 base_dimension = 256;
8146 for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx)
8148 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8149 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
8151 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
8152 continue;
8155 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
8157 hr = IDirect3DDevice8_CreateTexture(device, base_dimension, base_dimension, 0, 0,
8158 formats[format_idx].format, pools[pool_idx].pool, &texture_2d);
8159 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
8160 pools[pool_idx].name, formats[format_idx].name, hr);
8162 level_count = IDirect3DTexture8_GetLevelCount(texture_2d);
8163 for (i = 0, offset = 0; i < level_count; ++i)
8165 hr = IDirect3DTexture8_LockRect(texture_2d, i, &map_desc, NULL, 0);
8166 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
8167 pools[pool_idx].name, formats[format_idx].name, i, hr);
8169 if (!i)
8170 base = map_desc.pBits;
8171 else
8172 ok(map_desc.pBits == base + offset,
8173 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
8174 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
8175 offset += (base_dimension >> i) * map_desc.Pitch;
8177 hr = IDirect3DTexture8_UnlockRect(texture_2d, i);
8178 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
8179 pools[pool_idx].name, formats[format_idx].name, i, hr);
8182 IDirect3DTexture8_Release(texture_2d);
8185 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8186 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
8188 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
8189 continue;
8192 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
8194 hr = IDirect3DDevice8_CreateCubeTexture(device, base_dimension, 0, 0,
8195 formats[format_idx].format, pools[pool_idx].pool, &texture_cube);
8196 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
8197 pools[pool_idx].name, formats[format_idx].name, hr);
8199 level_count = IDirect3DCubeTexture8_GetLevelCount(texture_cube);
8200 for (i = 0, offset = 0; i < 6; ++i)
8202 for (j = 0; j < level_count; ++j)
8204 hr = IDirect3DCubeTexture8_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
8205 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
8206 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
8208 if (!i && !j)
8209 base = map_desc.pBits;
8210 else
8211 ok(map_desc.pBits == base + offset,
8212 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
8213 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
8214 offset += (base_dimension >> j) * map_desc.Pitch;
8216 hr = IDirect3DCubeTexture8_UnlockRect(texture_cube, i, j);
8217 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
8218 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
8220 offset = (offset + 15) & ~15;
8223 IDirect3DCubeTexture8_Release(texture_cube);
8227 refcount = IDirect3DDevice8_Release(device);
8228 ok(!refcount, "Device has %u references left.\n", refcount);
8229 done:
8230 IDirect3D8_Release(d3d);
8231 DestroyWindow(window);
8234 static void test_render_target_device_mismatch(void)
8236 IDirect3DDevice8 *device, *device2;
8237 IDirect3DSurface8 *surface, *rt;
8238 IDirect3D8 *d3d;
8239 UINT refcount;
8240 HWND window;
8241 HRESULT hr;
8243 window = create_window();
8244 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8245 ok(!!d3d, "Failed to create a D3D object.\n");
8246 if (!(device = create_device(d3d, window, NULL)))
8248 skip("Failed to create a D3D device.\n");
8249 IDirect3D8_Release(d3d);
8250 DestroyWindow(window);
8251 return;
8254 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
8255 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8257 device2 = create_device(d3d, window, NULL);
8258 ok(!!device2, "Failed to create a D3D device.\n");
8260 hr = IDirect3DDevice8_CreateRenderTarget(device2, 640, 480,
8261 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &surface);
8262 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8264 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
8265 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8267 IDirect3DSurface8_Release(surface);
8269 hr = IDirect3DDevice8_GetRenderTarget(device2, &surface);
8270 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8272 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
8273 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8275 IDirect3DSurface8_Release(surface);
8277 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
8278 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8279 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
8280 IDirect3DSurface8_Release(surface);
8281 IDirect3DSurface8_Release(rt);
8283 refcount = IDirect3DDevice8_Release(device);
8284 ok(!refcount, "Device has %u references left.\n", refcount);
8285 refcount = IDirect3DDevice8_Release(device2);
8286 ok(!refcount, "Device has %u references left.\n", refcount);
8287 IDirect3D8_Release(d3d);
8288 DestroyWindow(window);
8291 static void test_format_unknown(void)
8293 IDirect3DDevice8 *device;
8294 IDirect3D8 *d3d;
8295 UINT refcount;
8296 HWND window;
8297 void *iface;
8298 HRESULT hr;
8300 window = create_window();
8301 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8302 ok(!!d3d, "Failed to create a D3D object.\n");
8303 if (!(device = create_device(d3d, window, NULL)))
8305 skip("Failed to create a D3D device.\n");
8306 IDirect3D8_Release(d3d);
8307 DestroyWindow(window);
8308 return;
8311 if (SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8312 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_P8)))
8314 skip("P8 textures are supported, skipping some tests.\n");
8316 else
8318 iface = (void *)0xdeadbeef;
8319 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64,
8320 D3DFMT_P8, D3DMULTISAMPLE_NONE, FALSE, (IDirect3DSurface8 **)&iface);
8321 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8322 ok(!iface, "Got unexpected iface %p.\n", iface);
8324 iface = (void *)0xdeadbeef;
8325 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 64, 64,
8326 D3DFMT_P8, D3DMULTISAMPLE_NONE, (IDirect3DSurface8 **)&iface);
8327 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8328 ok(!iface, "Got unexpected iface %p.\n", iface);
8330 iface = (void *)0xdeadbeef;
8331 hr = IDirect3DDevice8_CreateTexture(device, 64, 64, 1, 0,
8332 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DTexture8 **)&iface);
8333 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8334 ok(!iface, "Got unexpected iface %p.\n", iface);
8336 iface = (void *)0xdeadbeef;
8337 hr = IDirect3DDevice8_CreateCubeTexture(device, 64, 1, 0,
8338 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DCubeTexture8 **)&iface);
8339 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8340 ok(!iface, "Got unexpected iface %p.\n", iface);
8342 iface = (void *)0xdeadbeef;
8343 hr = IDirect3DDevice8_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
8344 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture8 **)&iface);
8345 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8346 ok(!iface, "Got unexpected iface %p.\n", iface);
8349 iface = (void *)0xdeadbeef;
8350 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64,
8351 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, FALSE, (IDirect3DSurface8 **)&iface);
8352 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8353 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8355 iface = (void *)0xdeadbeef;
8356 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 64, 64,
8357 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, (IDirect3DSurface8 **)&iface);
8358 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8359 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8361 iface = (void *)0xdeadbeef;
8362 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64,
8363 D3DFMT_UNKNOWN, (IDirect3DSurface8 **)&iface);
8364 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8365 ok(!iface, "Got unexpected iface %p.\n", iface);
8367 iface = (void *)0xdeadbeef;
8368 hr = IDirect3DDevice8_CreateTexture(device, 64, 64, 1, 0,
8369 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture8 **)&iface);
8370 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8371 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8373 iface = (void *)0xdeadbeef;
8374 hr = IDirect3DDevice8_CreateCubeTexture(device, 64, 1, 0,
8375 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture8 **)&iface);
8376 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8377 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8379 iface = (void *)0xdeadbeef;
8380 hr = IDirect3DDevice8_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
8381 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture8 **)&iface);
8382 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8383 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8385 refcount = IDirect3DDevice8_Release(device);
8386 ok(!refcount, "Device has %u references left.\n", refcount);
8387 IDirect3D8_Release(d3d);
8388 DestroyWindow(window);
8391 static void test_destroyed_window(void)
8393 IDirect3DDevice8 *device;
8394 IDirect3D8 *d3d8;
8395 ULONG refcount;
8396 HWND window;
8397 HRESULT hr;
8399 /* No WS_VISIBLE. */
8400 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
8401 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8402 ok(!!window, "Failed to create a window.\n");
8404 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
8405 ok(!!d3d8, "Failed to create a D3D object.\n");
8406 device = create_device(d3d8, window, NULL);
8407 IDirect3D8_Release(d3d8);
8408 DestroyWindow(window);
8409 if (!device)
8411 skip("Failed to create a 3D device, skipping test.\n");
8412 return;
8415 hr = IDirect3DDevice8_BeginScene(device);
8416 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8417 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8418 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
8419 hr = IDirect3DDevice8_EndScene(device);
8420 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8421 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8422 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8424 refcount = IDirect3DDevice8_Release(device);
8425 ok(!refcount, "Device has %u references left.\n", refcount);
8428 static void test_lockable_backbuffer(void)
8430 D3DPRESENT_PARAMETERS present_parameters = {0};
8431 struct device_desc device_desc;
8432 IDirect3DSurface8 *surface;
8433 IDirect3DDevice8 *device;
8434 D3DLOCKED_RECT lockrect;
8435 IDirect3D8 *d3d;
8436 ULONG refcount;
8437 HWND window;
8438 HRESULT hr;
8440 window = create_window();
8441 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8442 ok(!!d3d, "Failed to create a D3D object.\n");
8444 if (!(device = create_device(d3d, window, NULL)))
8446 skip("Failed to create a D3D device, skipping tests.\n");
8447 IDirect3D8_Release(d3d);
8448 DestroyWindow(window);
8449 return;
8452 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8453 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
8455 hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY);
8456 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8458 IDirect3DSurface8_Release(surface);
8460 /* Reset with D3DPRESENTFLAG_LOCKABLE_BACKBUFFER. */
8461 present_parameters.BackBufferWidth = 640;
8462 present_parameters.BackBufferHeight = 480;
8463 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
8464 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
8465 present_parameters.hDeviceWindow = window;
8466 present_parameters.Windowed = TRUE;
8467 present_parameters.EnableAutoDepthStencil = TRUE;
8468 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
8469 present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
8471 hr = IDirect3DDevice8_Reset(device, &present_parameters);
8472 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
8474 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8475 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
8477 hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY);
8478 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
8479 hr = IDirect3DSurface8_UnlockRect(surface);
8480 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
8482 IDirect3DSurface8_Release(surface);
8483 refcount = IDirect3DDevice8_Release(device);
8484 ok(!refcount, "Device has %u references left.\n", refcount);
8486 device_desc.width = 640;
8487 device_desc.height = 480;
8488 device_desc.device_window = window;
8489 device_desc.flags = CREATE_DEVICE_LOCKABLE_BACKBUFFER;
8491 device = create_device(d3d, window, &device_desc);
8492 ok(!!device, "Failed to create device.\n");
8494 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8495 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
8497 hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY);
8498 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
8499 hr = IDirect3DSurface8_UnlockRect(surface);
8500 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
8502 IDirect3DSurface8_Release(surface);
8503 refcount = IDirect3DDevice8_Release(device);
8504 ok(!refcount, "Device has %u references left.\n", refcount);
8505 IDirect3D8_Release(d3d);
8506 DestroyWindow(window);
8509 static void test_clip_planes_limits(void)
8511 static const DWORD device_flags[] = {0, CREATE_DEVICE_SWVP_ONLY};
8512 IDirect3DDevice8 *device;
8513 struct device_desc desc;
8514 unsigned int i, j;
8515 IDirect3D8 *d3d;
8516 ULONG refcount;
8517 float plane[4];
8518 D3DCAPS8 caps;
8519 DWORD state;
8520 HWND window;
8521 HRESULT hr;
8523 window = create_window();
8524 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8525 ok(!!d3d, "Failed to create a D3D object.\n");
8527 for (i = 0; i < ARRAY_SIZE(device_flags); ++i)
8529 desc.device_window = window;
8530 desc.width = 640;
8531 desc.height = 480;
8532 desc.flags = device_flags[i];
8533 if (!(device = create_device(d3d, window, &desc)))
8535 skip("Failed to create D3D device, flags %#x.\n", desc.flags);
8536 continue;
8539 memset(&caps, 0, sizeof(caps));
8540 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
8541 ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr);
8543 trace("Max user clip planes: %u.\n", caps.MaxUserClipPlanes);
8545 for (j = 0; j < caps.MaxUserClipPlanes; ++j)
8547 memset(plane, 0xff, sizeof(plane));
8548 hr = IDirect3DDevice8_GetClipPlane(device, j, plane);
8549 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
8550 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
8551 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
8552 j, plane[0], plane[1], plane[2], plane[3]);
8555 plane[0] = 2.0f;
8556 plane[1] = 8.0f;
8557 plane[2] = 5.0f;
8558 for (j = 0; j < caps.MaxUserClipPlanes; ++j)
8560 plane[3] = j;
8561 hr = IDirect3DDevice8_SetClipPlane(device, j, plane);
8562 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", j, hr);
8564 for (j = 0; j < caps.MaxUserClipPlanes; ++j)
8566 memset(plane, 0xff, sizeof(plane));
8567 hr = IDirect3DDevice8_GetClipPlane(device, j, plane);
8568 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
8569 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == j,
8570 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
8571 j, plane[0], plane[1], plane[2], plane[3]);
8574 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0xffffffff);
8575 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8576 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
8577 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
8578 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
8579 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x80000000);
8580 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
8581 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
8582 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
8583 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
8585 refcount = IDirect3DDevice8_Release(device);
8586 ok(!refcount, "Device has %u references left.\n", refcount);
8589 IDirect3D8_Release(d3d);
8590 DestroyWindow(window);
8593 static void test_swapchain_multisample_reset(void)
8595 D3DPRESENT_PARAMETERS present_parameters;
8596 IDirect3DDevice8 *device;
8597 IDirect3D8 *d3d;
8598 ULONG refcount;
8599 HWND window;
8600 HRESULT hr;
8602 window = create_window();
8603 ok(!!window, "Failed to create a window.\n");
8604 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8605 ok(!!d3d, "Failed to create D3D object.\n");
8607 if (IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8608 D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES) == D3DERR_NOTAVAILABLE)
8610 skip("Multisampling not supported for D3DFMT_A8R8G8B8.\n");
8611 IDirect3D8_Release(d3d);
8612 DestroyWindow(window);
8613 return;
8616 if (!(device = create_device(d3d, window, NULL)))
8618 skip("Failed to create 3D device.\n");
8619 IDirect3D8_Release(d3d);
8620 DestroyWindow(window);
8621 return;
8624 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
8625 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
8627 memset(&present_parameters, 0, sizeof(present_parameters));
8628 present_parameters.BackBufferWidth = 640;
8629 present_parameters.BackBufferHeight = 480;
8630 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
8631 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
8632 present_parameters.hDeviceWindow = NULL;
8633 present_parameters.Windowed = TRUE;
8634 present_parameters.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
8635 hr = IDirect3DDevice8_Reset(device, &present_parameters);
8636 ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
8638 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
8639 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
8641 refcount = IDirect3DDevice8_Release(device);
8642 ok(!refcount, "Device has %u references left.\n", refcount);
8643 IDirect3D8_Release(d3d);
8644 DestroyWindow(window);
8647 static void test_device_caps(void)
8649 IDirect3DDevice8 *device;
8650 IDirect3D8 *d3d;
8651 ULONG refcount;
8652 D3DCAPS8 caps;
8653 HWND window;
8654 HRESULT hr;
8656 window = create_window();
8657 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8658 ok(!!d3d, "Failed to create a D3D object.\n");
8659 if (!(device = create_device(d3d, window, NULL)))
8661 skip("Failed to create a D3D device.\n");
8662 IDirect3D8_Release(d3d);
8663 DestroyWindow(window);
8664 return;
8667 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
8668 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8670 ok(!(caps.Caps & ~D3DCAPS_READ_SCANLINE), "Caps field has unexpected flags %#x.\n", caps.Caps);
8671 ok(!(caps.Caps2 & ~(D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_CANRENDERWINDOWED
8672 | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_FULLSCREENGAMMA
8673 | D3DCAPS2_NO2DDURING3DSCENE | D3DCAPS2_RESERVED)),
8674 "Caps2 field has unexpected flags %#x.\n", caps.Caps2);
8675 /* Nvidia returns that 0x400 flag, which is probably Vista+
8676 * D3DCAPS3_DXVAHD from d3d9caps.h */
8677 /* AMD doesn't filter all the ddraw / d3d9 caps. Consider that behavior
8678 * broken. */
8679 ok(!(caps.Caps3 & ~(D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | D3DCAPS3_RESERVED | 0x400))
8680 || broken(!(caps.Caps3 & ~(D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | 0x80))),
8681 "Caps3 field has unexpected flags %#x.\n", caps.Caps3);
8682 ok(!(caps.PrimitiveMiscCaps & ~(D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP
8683 | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW
8684 | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
8685 | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP
8686 | D3DPMISCCAPS_NULLREFERENCE))
8687 || broken(!(caps.PrimitiveMiscCaps & ~0x003fdff6)),
8688 "PrimitiveMiscCaps field has unexpected flags %#x.\n", caps.PrimitiveMiscCaps);
8689 /* AMD includes an unknown 0x2 flag. */
8690 ok(!(caps.RasterCaps & ~(D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST
8691 | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_ANTIALIASEDGES
8692 | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR
8693 | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER
8694 | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE
8695 | D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE))
8696 || broken(!(caps.RasterCaps & ~0x0ff7f19b)),
8697 "RasterCaps field has unexpected flags %#x.\n", caps.RasterCaps);
8698 ok(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
8699 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
8700 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
8701 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
8702 | D3DPBLENDCAPS_BOTHINVSRCALPHA)),
8703 "SrcBlendCaps field has unexpected flags %#x.\n", caps.SrcBlendCaps);
8704 ok(!(caps.DestBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
8705 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
8706 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
8707 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
8708 | D3DPBLENDCAPS_BOTHINVSRCALPHA)),
8709 "DestBlendCaps field has unexpected flags %#x.\n", caps.DestBlendCaps);
8710 ok(!(caps.TextureCaps & ~(D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2
8711 | D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_SQUAREONLY
8712 | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE
8713 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED
8714 | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP | D3DPTEXTURECAPS_MIPMAP
8715 | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP
8716 | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2)),
8717 "TextureCaps field has unexpected flags %#x.\n", caps.TextureCaps);
8718 ok(!(caps.TextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
8719 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
8720 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
8721 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
8722 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC))
8723 || broken(!(caps.TextureFilterCaps & ~0x0703073f)),
8724 "TextureFilterCaps field has unexpected flags %#x.\n", caps.TextureFilterCaps);
8725 ok(!(caps.CubeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
8726 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
8727 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
8728 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
8729 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC)),
8730 "CubeTextureFilterCaps field has unexpected flags %#x.\n", caps.CubeTextureFilterCaps);
8731 ok(!(caps.VolumeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
8732 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
8733 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
8734 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
8735 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC)),
8736 "VolumeTextureFilterCaps field has unexpected flags %#x.\n", caps.VolumeTextureFilterCaps);
8737 ok(!(caps.LineCaps & ~(D3DLINECAPS_TEXTURE | D3DLINECAPS_ZTEST | D3DLINECAPS_BLEND
8738 | D3DLINECAPS_ALPHACMP | D3DLINECAPS_FOG)),
8739 "LineCaps field has unexpected flags %#x.\n", caps.LineCaps);
8740 ok(!(caps.StencilCaps & ~(D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE
8741 | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT
8742 | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR)),
8743 "StencilCaps field has unexpected flags %#x.\n", caps.StencilCaps);
8744 ok(!(caps.VertexProcessingCaps & ~(D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7
8745 | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER
8746 | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_NO_VSDT_UBYTE4)),
8747 "VertexProcessingCaps field has unexpected flags %#x.\n", caps.VertexProcessingCaps);
8748 /* Both Nvidia and AMD give 10 here. */
8749 ok(caps.MaxActiveLights <= 10,
8750 "MaxActiveLights field has unexpected value %u.\n", caps.MaxActiveLights);
8751 /* AMD gives 6, Nvidia returns 8. */
8752 ok(caps.MaxUserClipPlanes <= 8,
8753 "MaxUserClipPlanes field has unexpected value %u.\n", caps.MaxUserClipPlanes);
8755 refcount = IDirect3DDevice8_Release(device);
8756 ok(!refcount, "Device has %u references left.\n", refcount);
8757 IDirect3D8_Release(d3d);
8758 DestroyWindow(window);
8761 static void test_get_info(void)
8763 IDirect3DDevice8 *device;
8764 IDirect3D8 *d3d;
8765 BYTE info[1024];
8766 ULONG refcount;
8767 unsigned int i;
8768 HWND window;
8769 HRESULT hr;
8771 window = create_window();
8772 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8773 ok(!!d3d, "Failed to create a D3D object.\n");
8774 if (!(device = create_device(d3d, window, NULL)))
8776 skip("Failed to create a D3D device.\n");
8777 IDirect3D8_Release(d3d);
8778 DestroyWindow(window);
8779 return;
8782 /* As called by Chessmaster 9000 (bug 42118). */
8783 hr = IDirect3DDevice8_GetInfo(device, 4, info, 16);
8784 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
8786 for (i = 0; i < 256; ++i)
8788 hr = IDirect3DDevice8_GetInfo(device, i, info, sizeof(info));
8789 if (i <= 4)
8790 ok(hr == (i < 4 ? E_FAIL : S_FALSE), "info_id %u, unexpected hr %#x.\n", i, hr);
8791 else
8792 ok(hr == E_FAIL || hr == S_FALSE, "info_id %u, unexpected hr %#x.\n", i, hr);
8795 refcount = IDirect3DDevice8_Release(device);
8796 ok(!refcount, "Device has %u references left.\n", refcount);
8797 IDirect3D8_Release(d3d);
8798 DestroyWindow(window);
8801 static void test_resource_access(void)
8803 IDirect3DSurface8 *backbuffer, *depth_stencil;
8804 D3DFORMAT colour_format, depth_format, format;
8805 BOOL depth_2d, depth_cube, depth_plain;
8806 struct device_desc device_desc;
8807 D3DSURFACE_DESC surface_desc;
8808 IDirect3DDevice8 *device;
8809 unsigned int i, j;
8810 IDirect3D8 *d3d;
8811 ULONG refcount;
8812 HWND window;
8813 HRESULT hr;
8815 enum surface_type
8817 SURFACE_2D,
8818 SURFACE_CUBE,
8819 SURFACE_RT,
8820 SURFACE_DS,
8821 SURFACE_IMAGE,
8824 enum resource_format
8826 FORMAT_COLOUR,
8827 FORMAT_ATI2,
8828 FORMAT_DEPTH,
8831 static const struct
8833 D3DPOOL pool;
8834 enum resource_format format;
8835 DWORD usage;
8836 BOOL valid;
8838 tests[] =
8840 /* 0 */
8841 {D3DPOOL_DEFAULT, FORMAT_COLOUR, 0, TRUE},
8842 {D3DPOOL_DEFAULT, FORMAT_ATI2, 0, TRUE},
8843 {D3DPOOL_DEFAULT, FORMAT_DEPTH, 0, TRUE},
8844 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, TRUE},
8845 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
8846 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
8847 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, TRUE},
8848 /* 7 */
8849 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC, TRUE},
8850 {D3DPOOL_DEFAULT, FORMAT_ATI2, D3DUSAGE_DYNAMIC, TRUE},
8851 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC, TRUE},
8852 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
8853 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
8854 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
8855 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
8856 /* 14 */
8857 {D3DPOOL_MANAGED, FORMAT_COLOUR, 0, TRUE},
8858 {D3DPOOL_MANAGED, FORMAT_ATI2, 0, TRUE},
8859 {D3DPOOL_MANAGED, FORMAT_DEPTH, 0, FALSE},
8860 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
8861 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
8862 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
8863 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
8864 /* 21 */
8865 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, 0, TRUE},
8866 {D3DPOOL_SYSTEMMEM, FORMAT_ATI2, 0, TRUE},
8867 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, 0, FALSE},
8868 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
8869 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
8870 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
8871 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
8872 /* 28 */
8873 {D3DPOOL_SCRATCH, FORMAT_COLOUR, 0, TRUE},
8874 {D3DPOOL_SCRATCH, FORMAT_ATI2, 0, TRUE},
8875 {D3DPOOL_SCRATCH, FORMAT_DEPTH, 0, FALSE},
8876 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
8877 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
8878 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
8879 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
8881 static const struct
8883 const char *name;
8884 enum surface_type type;
8886 surface_types[] =
8888 {"2D", SURFACE_2D},
8889 {"CUBE", SURFACE_CUBE},
8890 {"RT", SURFACE_RT},
8891 {"DS", SURFACE_DS},
8892 {"IMAGE", SURFACE_IMAGE},
8895 window = create_window();
8896 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8897 ok(!!d3d, "Failed to create a D3D object.\n");
8899 device_desc.device_window = window;
8900 device_desc.width = 16;
8901 device_desc.height = 16;
8902 device_desc.flags = 0;
8903 if (!(device = create_device(d3d, window, &device_desc)))
8905 skip("Failed to create a D3D device.\n");
8906 IDirect3D8_Release(d3d);
8907 DestroyWindow(window);
8908 return;
8911 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8912 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8913 hr = IDirect3DSurface8_GetDesc(backbuffer, &surface_desc);
8914 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8915 colour_format = surface_desc.Format;
8917 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depth_stencil);
8918 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8919 hr = IDirect3DSurface8_GetDesc(depth_stencil, &surface_desc);
8920 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8921 depth_format = surface_desc.Format;
8923 depth_2d = SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8924 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, depth_format));
8925 depth_cube = SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8926 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, depth_format));
8927 depth_plain = SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8928 D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, depth_format));
8930 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW);
8931 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8933 for (i = 0; i < ARRAY_SIZE(surface_types); ++i)
8935 for (j = 0; j < ARRAY_SIZE(tests); ++j)
8937 IDirect3DCubeTexture8 *texture_cube;
8938 IDirect3DBaseTexture8 *texture;
8939 IDirect3DTexture8 *texture_2d;
8940 IDirect3DSurface8 *surface;
8941 HRESULT expected_hr;
8942 D3DLOCKED_RECT lr;
8944 if (tests[j].format == FORMAT_ATI2)
8945 format = MAKEFOURCC('A','T','I','2');
8946 else if (tests[j].format == FORMAT_DEPTH)
8947 format = depth_format;
8948 else
8949 format = colour_format;
8951 if (tests[j].format == FORMAT_ATI2 && FAILED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
8952 D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, format)))
8954 skip("ATI2N texture not supported.\n");
8955 continue;
8958 switch (surface_types[i].type)
8960 case SURFACE_2D:
8961 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1,
8962 tests[j].usage, format, tests[j].pool, &texture_2d);
8963 todo_wine_if(!tests[j].valid && tests[j].format == FORMAT_DEPTH && !tests[j].usage)
8964 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_2d)
8965 ? D3D_OK : D3DERR_INVALIDCALL),
8966 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
8967 if (FAILED(hr))
8968 continue;
8970 hr = IDirect3DTexture8_GetSurfaceLevel(texture_2d, 0, &surface);
8971 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
8972 IDirect3DTexture8_Release(texture_2d);
8973 break;
8975 case SURFACE_CUBE:
8976 hr = IDirect3DDevice8_CreateCubeTexture(device, 16, 1,
8977 tests[j].usage, format, tests[j].pool, &texture_cube);
8978 todo_wine_if(!tests[j].valid && tests[j].format == FORMAT_DEPTH && !tests[j].usage)
8979 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_cube)
8980 ? D3D_OK : D3DERR_INVALIDCALL),
8981 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
8982 if (FAILED(hr))
8983 continue;
8985 hr = IDirect3DCubeTexture8_GetCubeMapSurface(texture_cube,
8986 D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
8987 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
8988 IDirect3DCubeTexture8_Release(texture_cube);
8989 break;
8991 case SURFACE_RT:
8992 hr = IDirect3DDevice8_CreateRenderTarget(device, 16, 16, format,
8993 D3DMULTISAMPLE_NONE, tests[j].usage & D3DUSAGE_DYNAMIC, &surface);
8994 ok(hr == (tests[j].format == FORMAT_COLOUR ? D3D_OK : D3DERR_INVALIDCALL),
8995 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
8996 if (FAILED(hr))
8997 continue;
8998 break;
9000 case SURFACE_DS:
9001 hr = IDirect3DDevice8_CreateDepthStencilSurface(device,
9002 16, 16, format, D3DMULTISAMPLE_NONE, &surface);
9003 todo_wine_if(tests[j].format == FORMAT_ATI2)
9004 ok(hr == (tests[j].format != FORMAT_COLOUR ? D3D_OK : D3DERR_INVALIDCALL),
9005 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9006 if (FAILED(hr))
9007 continue;
9008 break;
9010 case SURFACE_IMAGE:
9011 hr = IDirect3DDevice8_CreateImageSurface(device, 16, 16, format, &surface);
9012 ok(hr == ((tests[j].format != FORMAT_DEPTH || depth_plain) ? D3D_OK : D3DERR_INVALIDCALL),
9013 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9014 if (FAILED(hr))
9015 continue;
9016 break;
9018 default:
9019 ok(0, "Invalid surface type %#x.\n", surface_types[i].type);
9020 continue;
9023 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
9024 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9025 if (surface_types[i].type == SURFACE_RT)
9027 ok(surface_desc.Usage == D3DUSAGE_RENDERTARGET, "Test %s %u: Got unexpected usage %#x.\n",
9028 surface_types[i].name, j, surface_desc.Usage);
9029 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
9030 surface_types[i].name, j, surface_desc.Pool);
9032 else if (surface_types[i].type == SURFACE_DS)
9034 ok(surface_desc.Usage == D3DUSAGE_DEPTHSTENCIL, "Test %s %u: Got unexpected usage %#x.\n",
9035 surface_types[i].name, j, surface_desc.Usage);
9036 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
9037 surface_types[i].name, j, surface_desc.Pool);
9039 else if (surface_types[i].type == SURFACE_IMAGE)
9041 ok(!surface_desc.Usage, "Test %s %u: Got unexpected usage %#x.\n",
9042 surface_types[i].name, j, surface_desc.Usage);
9043 ok(surface_desc.Pool == D3DPOOL_SYSTEMMEM, "Test %s %u: Got unexpected pool %#x.\n",
9044 surface_types[i].name, j, surface_desc.Pool);
9046 else
9048 ok(surface_desc.Usage == tests[j].usage, "Test %s %u: Got unexpected usage %#x.\n",
9049 surface_types[i].name, j, surface_desc.Usage);
9050 ok(surface_desc.Pool == tests[j].pool, "Test %s %u: Got unexpected pool %#x.\n",
9051 surface_types[i].name, j, surface_desc.Pool);
9054 hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
9055 if (surface_desc.Pool != D3DPOOL_DEFAULT || surface_desc.Usage & D3DUSAGE_DYNAMIC
9056 || (surface_types[i].type == SURFACE_RT && tests[j].usage & D3DUSAGE_DYNAMIC)
9057 || surface_types[i].type == SURFACE_IMAGE
9058 || tests[j].format == FORMAT_ATI2)
9059 expected_hr = D3D_OK;
9060 else
9061 expected_hr = D3DERR_INVALIDCALL;
9062 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9063 hr = IDirect3DSurface8_UnlockRect(surface);
9064 todo_wine_if(expected_hr != D3D_OK && surface_types[i].type == SURFACE_2D)
9065 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9067 if (SUCCEEDED(IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DBaseTexture8, (void **)&texture)))
9069 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
9070 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9071 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
9072 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9073 IDirect3DBaseTexture8_Release(texture);
9076 hr = IDirect3DDevice8_SetRenderTarget(device, surface, depth_stencil);
9077 ok(hr == (surface_desc.Usage & D3DUSAGE_RENDERTARGET ? D3D_OK : D3DERR_INVALIDCALL),
9078 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9079 hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
9080 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9082 hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, surface);
9083 ok(hr == (surface_desc.Usage & D3DUSAGE_DEPTHSTENCIL ? D3D_OK : D3DERR_INVALIDCALL),
9084 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9085 hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
9086 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
9088 IDirect3DSurface8_Release(surface);
9092 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9094 IDirect3DVolumeTexture8 *texture;
9095 D3DVOLUME_DESC volume_desc;
9096 IDirect3DVolume8 *volume;
9097 HRESULT expected_hr;
9098 D3DLOCKED_BOX lb;
9100 if (tests[j].format == FORMAT_DEPTH)
9101 continue;
9103 if (tests[j].format == FORMAT_ATI2)
9104 format = MAKEFOURCC('A','T','I','2');
9105 else
9106 format = colour_format;
9108 hr = IDirect3DDevice8_CreateVolumeTexture(device, 16, 16, 1, 1,
9109 tests[i].usage, format, tests[i].pool, &texture);
9110 ok(hr == (!(tests[i].usage & ~D3DUSAGE_DYNAMIC) ? D3D_OK : D3DERR_INVALIDCALL),
9111 "Test %u: Got unexpected hr %#x.\n", i, hr);
9112 if (FAILED(hr))
9113 continue;
9115 hr = IDirect3DVolumeTexture8_GetVolumeLevel(texture, 0, &volume);
9116 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9118 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
9119 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9120 ok(volume_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#x.\n", i, volume_desc.Usage);
9121 ok(volume_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, volume_desc.Pool);
9123 hr = IDirect3DVolume8_LockBox(volume, &lb, NULL, 0);
9124 if (volume_desc.Pool != D3DPOOL_DEFAULT || volume_desc.Usage & D3DUSAGE_DYNAMIC)
9125 expected_hr = D3D_OK;
9126 else
9127 expected_hr = D3DERR_INVALIDCALL;
9128 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
9129 hr = IDirect3DVolume8_UnlockBox(volume);
9130 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
9132 hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
9133 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9134 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
9135 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9137 IDirect3DVolume8_Release(volume);
9138 IDirect3DVolumeTexture8_Release(texture);
9141 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9143 D3DINDEXBUFFER_DESC ib_desc;
9144 IDirect3DIndexBuffer8 *ib;
9145 BYTE *data;
9147 hr = IDirect3DDevice8_CreateIndexBuffer(device, 16, tests[i].usage,
9148 tests[i].format == FORMAT_COLOUR ? D3DFMT_INDEX32 : D3DFMT_INDEX16, tests[i].pool, &ib);
9149 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || (tests[i].usage & ~D3DUSAGE_DYNAMIC)
9150 ? D3DERR_INVALIDCALL : D3D_OK), "Test %u: Got unexpected hr %#x.\n", i, hr);
9151 if (FAILED(hr))
9152 continue;
9154 hr = IDirect3DIndexBuffer8_GetDesc(ib, &ib_desc);
9155 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9156 ok(ib_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#x.\n", i, ib_desc.Usage);
9157 ok(ib_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, ib_desc.Pool);
9159 hr = IDirect3DIndexBuffer8_Lock(ib, 0, 0, &data, 0);
9160 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9161 hr = IDirect3DIndexBuffer8_Unlock(ib);
9162 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9164 hr = IDirect3DDevice8_SetIndices(device, ib, 0);
9165 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9166 hr = IDirect3DDevice8_SetIndices(device, NULL, 0);
9167 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9169 IDirect3DIndexBuffer8_Release(ib);
9172 for (i = 0; i < ARRAY_SIZE(tests); ++i)
9174 D3DVERTEXBUFFER_DESC vb_desc;
9175 IDirect3DVertexBuffer8 *vb;
9176 BYTE *data;
9178 hr = IDirect3DDevice8_CreateVertexBuffer(device, 16, tests[i].usage,
9179 tests[i].format == FORMAT_COLOUR ? 0 : D3DFVF_XYZRHW, tests[i].pool, &vb);
9180 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || (tests[i].usage & ~D3DUSAGE_DYNAMIC)
9181 ? D3DERR_INVALIDCALL : D3D_OK), "Test %u: Got unexpected hr %#x.\n", i, hr);
9182 if (FAILED(hr))
9183 continue;
9185 hr = IDirect3DVertexBuffer8_GetDesc(vb, &vb_desc);
9186 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9187 ok(vb_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#x.\n", i, vb_desc.Usage);
9188 ok(vb_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, vb_desc.Pool);
9190 hr = IDirect3DVertexBuffer8_Lock(vb, 0, 0, &data, 0);
9191 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9192 hr = IDirect3DVertexBuffer8_Unlock(vb);
9193 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9195 hr = IDirect3DDevice8_SetStreamSource(device, 0, vb, 16);
9196 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9197 hr = IDirect3DDevice8_SetStreamSource(device, 0, NULL, 0);
9198 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
9200 IDirect3DVertexBuffer8_Release(vb);
9203 IDirect3DSurface8_Release(depth_stencil);
9204 IDirect3DSurface8_Release(backbuffer);
9205 refcount = IDirect3DDevice8_Release(device);
9206 ok(!refcount, "Device has %u references left.\n", refcount);
9207 IDirect3D8_Release(d3d);
9208 DestroyWindow(window);
9211 START_TEST(device)
9213 HMODULE d3d8_handle = GetModuleHandleA("d3d8.dll");
9214 WNDCLASSA wc = {0};
9215 IDirect3D8 *d3d8;
9216 DEVMODEW current_mode;
9218 if (!d3d8_handle)
9220 skip("Could not load d3d8.dll\n");
9221 return;
9224 memset(&current_mode, 0, sizeof(current_mode));
9225 current_mode.dmSize = sizeof(current_mode);
9226 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
9227 registry_mode.dmSize = sizeof(registry_mode);
9228 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
9229 if (current_mode.dmPelsWidth != registry_mode.dmPelsWidth
9230 || current_mode.dmPelsHeight != registry_mode.dmPelsHeight)
9232 skip("Current mode does not match registry mode, skipping test.\n");
9233 return;
9236 wc.lpfnWndProc = DefWindowProcA;
9237 wc.lpszClassName = "d3d8_test_wc";
9238 RegisterClassA(&wc);
9240 ValidateVertexShader = (void *)GetProcAddress(d3d8_handle, "ValidateVertexShader");
9241 ValidatePixelShader = (void *)GetProcAddress(d3d8_handle, "ValidatePixelShader");
9243 if (!(d3d8 = Direct3DCreate8(D3D_SDK_VERSION)))
9245 skip("could not create D3D8\n");
9246 return;
9248 IDirect3D8_Release(d3d8);
9250 test_fpu_setup();
9251 test_display_formats();
9252 test_display_modes();
9253 test_shader_versions();
9254 test_swapchain();
9255 test_refcount();
9256 test_mipmap_levels();
9257 test_checkdevicemultisampletype();
9258 test_invalid_multisample();
9259 test_cursor();
9260 test_cursor_pos();
9261 test_states();
9262 test_reset();
9263 test_scene();
9264 test_shader();
9265 test_limits();
9266 test_lights();
9267 test_ApplyStateBlock();
9268 test_render_zero_triangles();
9269 test_depth_stencil_reset();
9270 test_wndproc();
9271 test_wndproc_windowed();
9272 test_depth_stencil_size();
9273 test_window_style();
9274 test_unsupported_shaders();
9275 test_mode_change();
9276 test_device_window_reset();
9277 test_reset_resources();
9278 depth_blit_test();
9279 test_set_rt_vp_scissor();
9280 test_validate_vs();
9281 test_validate_ps();
9282 test_volume_get_container();
9283 test_vb_lock_flags();
9284 test_texture_stage_states();
9285 test_cube_textures();
9286 test_get_set_texture();
9287 test_image_surface_pool();
9288 test_surface_get_container();
9289 test_lockrect_invalid();
9290 test_private_data();
9291 test_surface_dimensions();
9292 test_surface_format_null();
9293 test_surface_double_unlock();
9294 test_surface_blocks();
9295 test_set_palette();
9296 test_swvp_buffer();
9297 test_managed_buffer();
9298 test_npot_textures();
9299 test_volume_locking();
9300 test_update_volumetexture();
9301 test_create_rt_ds_fail();
9302 test_volume_blocks();
9303 test_lockbox_invalid();
9304 test_pixel_format();
9305 test_begin_end_state_block();
9306 test_shader_constant_apply();
9307 test_resource_type();
9308 test_mipmap_lock();
9309 test_writeonly_resource();
9310 test_lost_device();
9311 test_resource_priority();
9312 test_swapchain_parameters();
9313 test_check_device_format();
9314 test_miptree_layout();
9315 test_render_target_device_mismatch();
9316 test_format_unknown();
9317 test_destroyed_window();
9318 test_lockable_backbuffer();
9319 test_clip_planes_limits();
9320 test_swapchain_multisample_reset();
9321 test_device_caps();
9322 test_get_info();
9323 test_resource_access();
9325 UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));