kerberos: Add support for SECPKG_CRED_BOTH.
[wine.git] / dlls / d3d8 / tests / device.c
blob8261a3139c59229478ea296b181917758cc47462
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 #include <stdlib.h>
25 #define COBJMACROS
26 #include <initguid.h>
27 #include <d3d8.h>
28 #include "wine/test.h"
30 struct vec3
32 float x, y, z;
35 #define CREATE_DEVICE_FULLSCREEN 0x01
36 #define CREATE_DEVICE_FPU_PRESERVE 0x02
37 #define CREATE_DEVICE_SWVP_ONLY 0x04
38 #define CREATE_DEVICE_LOCKABLE_BACKBUFFER 0x08
40 struct device_desc
42 unsigned int adapter_ordinal;
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)(const DWORD *, const DWORD *, const D3DCAPS8 *, BOOL, char **);
55 static HRESULT (WINAPI *ValidatePixelShader)(const DWORD *, const D3DCAPS8 *, BOOL, char **);
57 static const DWORD simple_vs[] = {0xFFFE0101, /* vs_1_1 */
58 0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0 */
59 0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1 */
60 0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2 */
61 0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3 */
62 0x0000FFFF}; /* END */
63 static const DWORD simple_ps[] = {0xFFFF0101, /* ps_1_1 */
64 0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
65 0x00000042, 0xB00F0000, /* tex t0 */
66 0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000, /* dp3 r0, c1, c0 */
67 0x00000005, 0x800F0000, 0x90E40000, 0x80E40000, /* mul r0, v0, r0 */
68 0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000, /* mul r0, t0, r0 */
69 0x0000FFFF}; /* END */
71 static int get_refcount(IUnknown *object)
73 IUnknown_AddRef( object );
74 return IUnknown_Release( object );
77 static void get_virtual_rect(RECT *rect)
79 rect->left = GetSystemMetrics(SM_XVIRTUALSCREEN);
80 rect->top = GetSystemMetrics(SM_YVIRTUALSCREEN);
81 rect->right = rect->left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
82 rect->bottom = rect->top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
85 static HWND create_window(void)
87 RECT r = {0, 0, 640, 480};
89 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
91 return CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
92 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
95 /* try to make sure pending X events have been processed before continuing */
96 static void flush_events(void)
98 MSG msg;
99 int diff = 200;
100 int min_timeout = 100;
101 DWORD time = GetTickCount() + diff;
103 while (diff > 0)
105 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
106 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
107 diff = time - GetTickCount();
111 static BOOL adapter_is_warp(const D3DADAPTER_IDENTIFIER8 *identifier)
113 return !strcmp(identifier->Driver, "d3d10warp.dll");
116 static BOOL equal_mode_rect(const DEVMODEW *mode1, const DEVMODEW *mode2)
118 return mode1->dmPosition.x == mode2->dmPosition.x
119 && mode1->dmPosition.y == mode2->dmPosition.y
120 && mode1->dmPelsWidth == mode2->dmPelsWidth
121 && mode1->dmPelsHeight == mode2->dmPelsHeight;
124 /* Free original_modes after finished using it */
125 static BOOL save_display_modes(DEVMODEW **original_modes, unsigned int *display_count)
127 unsigned int number, size = 2, count = 0, index = 0;
128 DISPLAY_DEVICEW display_device;
129 DEVMODEW *modes, *tmp;
131 if (!(modes = malloc(size * sizeof(*modes))))
132 return FALSE;
134 display_device.cb = sizeof(display_device);
135 while (EnumDisplayDevicesW(NULL, index++, &display_device, 0))
137 /* Skip software devices */
138 if (swscanf(display_device.DeviceName, L"\\\\.\\DISPLAY%u", &number) != 1)
139 continue;
141 if (!(display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
142 continue;
144 if (count >= size)
146 size *= 2;
147 if (!(tmp = realloc(modes, size * sizeof(*modes))))
149 free(modes);
150 return FALSE;
152 modes = tmp;
155 memset(&modes[count], 0, sizeof(modes[count]));
156 modes[count].dmSize = sizeof(modes[count]);
157 if (!EnumDisplaySettingsW(display_device.DeviceName, ENUM_CURRENT_SETTINGS, &modes[count]))
159 free(modes);
160 return FALSE;
163 lstrcpyW(modes[count++].dmDeviceName, display_device.DeviceName);
166 *original_modes = modes;
167 *display_count = count;
168 return TRUE;
171 static BOOL restore_display_modes(DEVMODEW *modes, unsigned int count)
173 unsigned int index;
174 LONG ret;
176 for (index = 0; index < count; ++index)
178 ret = ChangeDisplaySettingsExW(modes[index].dmDeviceName, &modes[index], NULL,
179 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
180 if (ret != DISP_CHANGE_SUCCESSFUL)
181 return FALSE;
183 ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
184 return ret == DISP_CHANGE_SUCCESSFUL;
187 static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND focus_window, const struct device_desc *desc)
189 D3DPRESENT_PARAMETERS present_parameters = {0};
190 unsigned int adapter_ordinal;
191 IDirect3DDevice8 *device;
192 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
194 adapter_ordinal = D3DADAPTER_DEFAULT;
195 present_parameters.BackBufferWidth = 640;
196 present_parameters.BackBufferHeight = 480;
197 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
198 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
199 present_parameters.hDeviceWindow = focus_window;
200 present_parameters.Windowed = TRUE;
201 present_parameters.EnableAutoDepthStencil = TRUE;
202 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
204 if (desc)
206 adapter_ordinal = desc->adapter_ordinal;
207 present_parameters.BackBufferWidth = desc->width;
208 present_parameters.BackBufferHeight = desc->height;
209 present_parameters.hDeviceWindow = desc->device_window;
210 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
211 if (desc->flags & CREATE_DEVICE_LOCKABLE_BACKBUFFER)
212 present_parameters.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
213 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
214 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
215 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
216 behavior_flags |= D3DCREATE_FPU_PRESERVE;
219 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, adapter_ordinal, D3DDEVTYPE_HAL, focus_window,
220 behavior_flags, &present_parameters, &device)))
221 return device;
223 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
224 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, adapter_ordinal, D3DDEVTYPE_HAL, focus_window,
225 behavior_flags, &present_parameters, &device)))
226 return device;
228 if (desc && desc->flags & CREATE_DEVICE_SWVP_ONLY)
229 return NULL;
230 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
232 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, adapter_ordinal, D3DDEVTYPE_HAL, focus_window,
233 behavior_flags, &present_parameters, &device)))
234 return device;
236 return NULL;
239 static HRESULT reset_device(IDirect3DDevice8 *device, const struct device_desc *desc)
241 D3DPRESENT_PARAMETERS present_parameters = {0};
243 present_parameters.BackBufferWidth = 640;
244 present_parameters.BackBufferHeight = 480;
245 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
246 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
247 present_parameters.hDeviceWindow = NULL;
248 present_parameters.Windowed = TRUE;
249 present_parameters.EnableAutoDepthStencil = TRUE;
250 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
252 if (desc)
254 present_parameters.BackBufferWidth = desc->width;
255 present_parameters.BackBufferHeight = desc->height;
256 present_parameters.hDeviceWindow = desc->device_window;
257 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
260 return IDirect3DDevice8_Reset(device, &present_parameters);
263 #define CHECK_CALL(r,c,d,rc) \
264 if (SUCCEEDED(r)) {\
265 int tmp1 = get_refcount( (IUnknown *)d ); \
266 int rc_new = rc; \
267 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
268 } else {\
269 trace("%s failed: %#08lx\n", c, r); \
272 #define CHECK_RELEASE(obj,d,rc) \
273 if (obj) { \
274 int tmp1, rc_new = rc; \
275 IUnknown_Release( (IUnknown*)obj ); \
276 tmp1 = get_refcount( (IUnknown *)d ); \
277 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
280 #define CHECK_REFCOUNT(obj,rc) \
282 int rc_new = rc; \
283 int count = get_refcount( (IUnknown *)obj ); \
284 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
287 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
289 int rc_new = rc; \
290 int count = IUnknown_Release( (IUnknown *)obj ); \
291 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
294 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
296 int rc_new = rc; \
297 int count = IUnknown_AddRef( (IUnknown *)obj ); \
298 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
301 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
303 void *container_ptr = (void *)0x1337c0d3; \
304 hr = IDirect3DSurface8_GetContainer(obj, &iid, &container_ptr); \
305 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#08lx, container_ptr %p. " \
306 "Expected hr %#08lx, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
307 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
310 static void check_mipmap_levels(IDirect3DDevice8 *device, UINT width, UINT height, UINT count)
312 IDirect3DBaseTexture8* texture = NULL;
313 HRESULT hr = IDirect3DDevice8_CreateTexture( device, width, height, 0, 0,
314 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture8**) &texture );
316 if (SUCCEEDED(hr)) {
317 DWORD levels = IDirect3DBaseTexture8_GetLevelCount(texture);
318 ok(levels == count, "Invalid level count. Expected %d got %lu\n", count, levels);
319 } else
320 trace("CreateTexture failed: %#08lx\n", hr);
322 if (texture) IDirect3DBaseTexture8_Release( texture );
325 static void test_mipmap_levels(void)
327 IDirect3DDevice8 *device;
328 IDirect3D8 *d3d;
329 ULONG refcount;
330 HWND window;
332 window = create_window();
333 ok(!!window, "Failed to create a window.\n");
334 d3d = Direct3DCreate8(D3D_SDK_VERSION);
335 ok(!!d3d, "Failed to create a D3D object.\n");
336 if (!(device = create_device(d3d, window, NULL)))
338 skip("Failed to create a 3D device, skipping test.\n");
339 goto cleanup;
342 check_mipmap_levels(device, 32, 32, 6);
343 check_mipmap_levels(device, 256, 1, 9);
344 check_mipmap_levels(device, 1, 256, 9);
345 check_mipmap_levels(device, 1, 1, 1);
347 refcount = IDirect3DDevice8_Release(device);
348 ok(!refcount, "Device has %lu references left.\n", refcount);
349 cleanup:
350 IDirect3D8_Release(d3d);
351 DestroyWindow(window);
354 static void test_swapchain(void)
356 IDirect3DSwapChain8 *swapchain1;
357 IDirect3DSwapChain8 *swapchain2;
358 IDirect3DSwapChain8 *swapchain3;
359 IDirect3DSurface8 *backbuffer, *stereo_buffer;
360 D3DPRESENT_PARAMETERS d3dpp;
361 IDirect3DDevice8 *device;
362 IDirect3D8 *d3d;
363 ULONG refcount;
364 HWND window, window2;
365 HRESULT hr;
366 struct device_desc device_desc;
368 window = create_window();
369 ok(!!window, "Failed to create a window.\n");
370 window2 = create_window();
371 ok(!!window2, "Failed to create a window.\n");
372 d3d = Direct3DCreate8(D3D_SDK_VERSION);
373 ok(!!d3d, "Failed to create a D3D object.\n");
374 if (!(device = create_device(d3d, window, NULL)))
376 skip("Failed to create a 3D device, skipping test.\n");
377 goto cleanup;
380 backbuffer = (void *)0xdeadbeef;
381 /* IDirect3DDevice8::GetBackBuffer crashes if a NULL output pointer is passed. */
382 hr = IDirect3DDevice8_GetBackBuffer(device, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
383 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
384 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
386 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
387 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#lx.\n", hr);
388 IDirect3DSurface8_Release(backbuffer);
390 /* The back buffer type value is ignored. */
391 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
392 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#lx.\n", hr);
393 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
394 IDirect3DSurface8_Release(stereo_buffer);
395 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
396 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#lx.\n", hr);
397 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
398 IDirect3DSurface8_Release(stereo_buffer);
399 hr = IDirect3DDevice8_GetBackBuffer(device, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
400 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#lx.\n", hr);
401 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
402 IDirect3DSurface8_Release(stereo_buffer);
404 memset(&d3dpp, 0, sizeof(d3dpp));
405 d3dpp.Windowed = TRUE;
406 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
407 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
409 /* Create a bunch of swapchains */
410 d3dpp.BackBufferCount = 0;
411 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
412 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
413 ok(!d3dpp.BackBufferWidth, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
414 ok(!d3dpp.BackBufferHeight, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
415 ok(d3dpp.BackBufferFormat == D3DFMT_A8R8G8B8, "Got unexpected BackBufferFormat %#x.\n", d3dpp.BackBufferFormat);
416 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
417 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
419 d3dpp.hDeviceWindow = NULL;
420 d3dpp.BackBufferCount = 1;
421 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
422 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
424 d3dpp.BackBufferCount = 2;
425 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
426 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
427 if(SUCCEEDED(hr)) {
428 /* Swapchain 3, created with backbuffercount 2 */
429 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, NULL);
430 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
432 backbuffer = (void *) 0xdeadbeef;
433 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
434 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
435 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
436 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
438 /* The back buffer type value is ignored. */
439 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
440 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#lx.\n", hr);
441 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
442 IDirect3DSurface8_Release(stereo_buffer);
443 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
444 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#lx.\n", hr);
445 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
446 IDirect3DSurface8_Release(stereo_buffer);
447 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
448 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#lx.\n", hr);
449 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
450 IDirect3DSurface8_Release(stereo_buffer);
452 backbuffer = (void *) 0xdeadbeef;
453 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
454 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
455 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
456 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
458 backbuffer = (void *) 0xdeadbeef;
459 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
460 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
461 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
462 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
464 backbuffer = (void *) 0xdeadbeef;
465 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
466 ok(FAILED(hr), "Got hr %#lx.\n", hr);
467 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
468 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
471 /* Check the back buffers of the swapchains */
472 /* Swapchain 1, created with backbuffercount 0 */
473 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
474 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
475 ok(!!backbuffer, "Expected a non-NULL backbuffer.\n");
476 if(backbuffer) IDirect3DSurface8_Release(backbuffer);
478 backbuffer = (void *) 0xdeadbeef;
479 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
480 ok(FAILED(hr), "Got hr %#lx.\n", hr);
481 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
482 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
484 /* Swapchain 2 - created with backbuffercount 1 */
485 backbuffer = (void *) 0xdeadbeef;
486 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
487 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
488 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
489 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
491 backbuffer = (void *) 0xdeadbeef;
492 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
493 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
494 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
495 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
497 backbuffer = (void *) 0xdeadbeef;
498 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
499 ok(FAILED(hr), "Got hr %#lx.\n", hr);
500 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
501 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
503 IDirect3DSwapChain8_Release(swapchain3);
504 IDirect3DSwapChain8_Release(swapchain2);
505 IDirect3DSwapChain8_Release(swapchain1);
507 d3dpp.Windowed = FALSE;
508 d3dpp.hDeviceWindow = window;
509 d3dpp.BackBufferCount = 1;
510 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
511 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx\n", hr);
512 d3dpp.hDeviceWindow = window2;
513 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
514 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx\n", hr);
516 device_desc.width = registry_mode.dmPelsWidth;
517 device_desc.height = registry_mode.dmPelsHeight;
518 device_desc.device_window = window;
519 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
520 hr = reset_device(device, &device_desc);
521 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
523 d3dpp.hDeviceWindow = window;
524 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
525 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx\n", hr);
526 d3dpp.hDeviceWindow = window2;
527 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
528 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx\n", hr);
529 d3dpp.Windowed = TRUE;
530 d3dpp.hDeviceWindow = window;
531 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
532 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx\n", hr);
533 d3dpp.hDeviceWindow = window2;
534 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
535 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx\n", hr);
537 refcount = IDirect3DDevice8_Release(device);
538 ok(!refcount, "Device has %lu references left.\n", refcount);
539 cleanup:
540 IDirect3D8_Release(d3d);
541 DestroyWindow(window2);
542 DestroyWindow(window);
545 static void test_refcount(void)
547 IDirect3DVertexBuffer8 *pVertexBuffer = NULL;
548 IDirect3DIndexBuffer8 *pIndexBuffer = NULL;
549 DWORD dVertexShader = -1;
550 DWORD dPixelShader = -1;
551 IDirect3DCubeTexture8 *pCubeTexture = NULL;
552 IDirect3DTexture8 *pTexture = NULL;
553 IDirect3DVolumeTexture8 *pVolumeTexture = NULL;
554 IDirect3DVolume8 *pVolumeLevel = NULL;
555 IDirect3DSurface8 *pStencilSurface = NULL;
556 IDirect3DSurface8 *pImageSurface = NULL;
557 IDirect3DSurface8 *pRenderTarget = NULL;
558 IDirect3DSurface8 *pRenderTarget2 = NULL;
559 IDirect3DSurface8 *pRenderTarget3 = NULL;
560 IDirect3DSurface8 *pTextureLevel = NULL;
561 IDirect3DSurface8 *pBackBuffer = NULL;
562 DWORD dStateBlock = -1;
563 IDirect3DSwapChain8 *pSwapChain = NULL;
564 D3DCAPS8 caps;
565 D3DPRESENT_PARAMETERS d3dpp;
566 IDirect3DDevice8 *device = NULL;
567 ULONG refcount = 0, tmp;
568 IDirect3D8 *d3d, *d3d2;
569 HWND window;
570 HRESULT hr;
572 DWORD decl[] =
574 D3DVSD_STREAM(0),
575 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
576 D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
577 D3DVSD_END()
580 window = create_window();
581 ok(!!window, "Failed to create a window.\n");
582 d3d = Direct3DCreate8(D3D_SDK_VERSION);
583 ok(!!d3d, "Failed to create a D3D object.\n");
585 CHECK_REFCOUNT(d3d, 1);
587 if (!(device = create_device(d3d, window, NULL)))
589 skip("Failed to create a 3D device, skipping test.\n");
590 goto cleanup;
593 IDirect3DDevice8_GetDeviceCaps(device, &caps);
595 refcount = get_refcount((IUnknown *)device);
596 ok(refcount == 1, "Got unexpected refcount %lu.\n", refcount);
598 CHECK_REFCOUNT(d3d, 2);
600 hr = IDirect3DDevice8_GetDirect3D(device, &d3d2);
601 CHECK_CALL(hr, "GetDirect3D", device, refcount);
603 ok(d3d2 == d3d, "Expected IDirect3D8 pointers to be equal.\n");
604 CHECK_REFCOUNT(d3d, 3);
605 CHECK_RELEASE_REFCOUNT(d3d, 2);
608 * Check refcount of implicit surfaces. Findings:
609 * - the container is the device
610 * - they hold a reference to the device
611 * - they are created with a refcount of 0 (Get/Release returns original refcount)
612 * - they are not freed if refcount reaches 0.
613 * - the refcount is not forwarded to the container.
615 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget);
616 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
617 if (pRenderTarget)
619 CHECK_SURFACE_CONTAINER(pRenderTarget, IID_IDirect3DDevice8, device);
620 CHECK_REFCOUNT(pRenderTarget, 1);
622 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
623 CHECK_REFCOUNT(device, refcount);
624 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
625 CHECK_REFCOUNT(device, refcount);
627 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget);
628 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
629 CHECK_REFCOUNT(pRenderTarget, 2);
630 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
631 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
632 CHECK_REFCOUNT(device, --refcount);
634 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
635 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
636 CHECK_REFCOUNT(device, ++refcount);
637 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
638 CHECK_REFCOUNT(device, --refcount);
639 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
640 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
643 /* Render target and back buffer are identical. */
644 hr = IDirect3DDevice8_GetBackBuffer(device, 0, 0, &pBackBuffer);
645 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
646 if (pBackBuffer)
648 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
649 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
650 pRenderTarget, pBackBuffer);
651 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
652 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
653 pBackBuffer = NULL;
655 CHECK_REFCOUNT(device, --refcount);
657 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &pStencilSurface);
658 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
659 if (pStencilSurface)
661 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice8, device);
662 CHECK_REFCOUNT(pStencilSurface, 1);
664 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
665 CHECK_REFCOUNT(device, refcount);
666 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
667 CHECK_REFCOUNT(device, refcount);
669 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
670 CHECK_REFCOUNT(device, --refcount);
672 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
673 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
674 CHECK_REFCOUNT(device, ++refcount);
675 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
676 CHECK_REFCOUNT(device, --refcount);
677 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
678 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
679 pStencilSurface = NULL;
682 /* Buffers */
683 hr = IDirect3DDevice8_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer);
684 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount);
685 if(pIndexBuffer)
687 tmp = get_refcount( (IUnknown *)pIndexBuffer );
689 hr = IDirect3DDevice8_SetIndices(device, pIndexBuffer, 0);
690 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
691 hr = IDirect3DDevice8_SetIndices(device, NULL, 0);
692 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
695 hr = IDirect3DDevice8_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer);
696 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
697 if(pVertexBuffer)
699 IDirect3DVertexBuffer8 *pVBuf = (void*)~0;
700 UINT stride = ~0;
702 tmp = get_refcount( (IUnknown *)pVertexBuffer );
704 hr = IDirect3DDevice8_SetStreamSource(device, 0, pVertexBuffer, 3 * sizeof(float));
705 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
706 hr = IDirect3DDevice8_SetStreamSource(device, 0, NULL, 0);
707 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
709 hr = IDirect3DDevice8_GetStreamSource(device, 0, &pVBuf, &stride);
710 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
711 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
712 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
715 /* Shaders */
716 hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_vs, &dVertexShader, 0);
717 CHECK_CALL(hr, "CreateVertexShader", device, refcount);
718 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
720 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &dPixelShader);
721 CHECK_CALL(hr, "CreatePixelShader", device, refcount);
723 /* Textures */
724 hr = IDirect3DDevice8_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture);
725 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
726 if (pTexture)
728 tmp = get_refcount( (IUnknown *)pTexture );
730 /* SetTexture should not increase refcounts */
731 hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) pTexture);
732 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
733 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
734 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
736 /* This should not increment device refcount */
737 hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
738 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
739 /* But should increment texture's refcount */
740 CHECK_REFCOUNT( pTexture, tmp+1 );
741 /* Because the texture and surface refcount are identical */
742 if (pTextureLevel)
744 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
745 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
746 CHECK_REFCOUNT ( pTexture , tmp+2 );
747 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
748 CHECK_REFCOUNT ( pTexture , tmp+1 );
749 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
750 CHECK_REFCOUNT ( pTextureLevel, tmp );
753 if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
755 hr = IDirect3DDevice8_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture);
756 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
758 else
760 skip("Cube textures not supported\n");
762 if(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
764 hr = IDirect3DDevice8_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
765 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture);
766 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
768 else
770 skip("Volume textures not supported\n");
773 if (pVolumeTexture)
775 tmp = get_refcount( (IUnknown *)pVolumeTexture );
777 /* This should not increment device refcount */
778 hr = IDirect3DVolumeTexture8_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
779 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
780 /* But should increment volume texture's refcount */
781 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
782 /* Because the volume texture and volume refcount are identical */
783 if (pVolumeLevel)
785 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
786 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
787 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
788 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
789 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
790 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
791 CHECK_REFCOUNT ( pVolumeLevel , tmp );
794 /* Surfaces */
795 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32,
796 D3DFMT_D16, D3DMULTISAMPLE_NONE, &pStencilSurface);
797 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
798 CHECK_REFCOUNT( pStencilSurface, 1);
799 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32,
800 D3DFMT_X8R8G8B8, &pImageSurface);
801 CHECK_CALL(hr, "CreateImageSurface", device, ++refcount);
802 CHECK_REFCOUNT( pImageSurface, 1);
803 hr = IDirect3DDevice8_CreateRenderTarget(device, 32, 32,
804 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget3);
805 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
806 CHECK_REFCOUNT( pRenderTarget3, 1);
807 /* Misc */
808 hr = IDirect3DDevice8_CreateStateBlock(device, D3DSBT_ALL, &dStateBlock);
809 CHECK_CALL(hr, "CreateStateBlock", device, refcount);
811 memset(&d3dpp, 0, sizeof(d3dpp));
812 d3dpp.Windowed = TRUE;
813 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
814 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
815 d3dpp.EnableAutoDepthStencil = TRUE;
816 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
817 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
818 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
819 if(pSwapChain)
821 /* check implicit back buffer */
822 hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
823 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
824 CHECK_REFCOUNT( pSwapChain, 1);
825 if(pBackBuffer)
827 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DDevice8, device);
828 CHECK_REFCOUNT( pBackBuffer, 1);
829 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
830 CHECK_REFCOUNT(device, --refcount);
832 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
833 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
834 CHECK_REFCOUNT(device, ++refcount);
835 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
836 CHECK_REFCOUNT(device, --refcount);
837 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
838 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
839 pBackBuffer = NULL;
841 CHECK_REFCOUNT( pSwapChain, 1);
844 if(pVertexBuffer)
846 BYTE *data;
847 /* Vertex buffers can be locked multiple times */
848 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
849 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
850 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
851 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
852 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
853 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
854 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
855 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
858 /* The implicit render target is not freed if refcount reaches 0.
859 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
860 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget2);
861 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
862 if (pRenderTarget2)
864 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
865 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
866 pRenderTarget, pRenderTarget2);
867 CHECK_REFCOUNT(device, --refcount);
868 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
869 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
870 pRenderTarget2 = NULL;
872 pRenderTarget = NULL;
874 cleanup:
875 CHECK_RELEASE(device, device, --refcount);
877 /* Buffers */
878 CHECK_RELEASE(pVertexBuffer, device, --refcount);
879 CHECK_RELEASE(pIndexBuffer, device, --refcount);
880 /* Shaders */
881 if (dVertexShader != ~0u)
882 IDirect3DDevice8_DeleteVertexShader(device, dVertexShader);
883 if (dPixelShader != ~0u)
884 IDirect3DDevice8_DeletePixelShader(device, dPixelShader);
885 /* Textures */
886 CHECK_RELEASE(pTexture, device, --refcount);
887 CHECK_RELEASE(pCubeTexture, device, --refcount);
888 CHECK_RELEASE(pVolumeTexture, device, --refcount);
889 /* Surfaces */
890 CHECK_RELEASE(pStencilSurface, device, --refcount);
891 CHECK_RELEASE(pImageSurface, device, --refcount);
892 CHECK_RELEASE(pRenderTarget3, device, --refcount);
893 /* Misc */
894 if (dStateBlock != ~0u)
895 IDirect3DDevice8_DeleteStateBlock(device, dStateBlock);
896 /* This will destroy device - cannot check the refcount here */
897 if (pSwapChain)
898 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
899 CHECK_RELEASE_REFCOUNT(d3d, 0);
900 DestroyWindow(window);
903 static void test_checkdevicemultisampletype(void)
905 IDirect3D8 *d3d;
906 HWND window;
907 HRESULT hr;
909 window = create_window();
910 ok(!!window, "Failed to create a window.\n");
911 d3d = Direct3DCreate8(D3D_SDK_VERSION);
912 ok(!!d3d, "Failed to create a D3D object.\n");
914 if (IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
915 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES) == D3DERR_NOTAVAILABLE)
917 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
918 goto cleanup;
921 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
922 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE);
923 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
924 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
925 65536, TRUE, D3DMULTISAMPLE_NONE);
926 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
928 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
929 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE);
930 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
931 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
932 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE);
933 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
935 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
936 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES);
937 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
939 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
940 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
941 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES);
942 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
944 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
945 D3DFMT_X8R8G8B8, TRUE, 65536);
946 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
948 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
949 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES);
950 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
952 cleanup:
953 IDirect3D8_Release(d3d);
954 DestroyWindow(window);
957 static void test_invalid_multisample(void)
959 IDirect3DDevice8 *device;
960 IDirect3DSurface8 *rt;
961 IDirect3D8 *d3d;
962 BOOL available;
963 ULONG refcount;
964 HWND window;
965 HRESULT hr;
967 window = create_window();
968 ok(!!window, "Failed to create a window.\n");
969 d3d = Direct3DCreate8(D3D_SDK_VERSION);
970 ok(!!d3d, "Failed to create a D3D object.\n");
972 if (!(device = create_device(d3d, window, NULL)))
974 skip("Failed to create a 3D device, skipping test.\n");
975 goto cleanup;
978 available = SUCCEEDED(IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
979 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES));
981 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128,
982 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, FALSE, &rt);
983 if (available)
985 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
986 IDirect3DSurface8_Release(rt);
988 else
990 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
993 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
994 available = SUCCEEDED(IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
995 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES));
996 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128,
997 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, FALSE, &rt);
998 if (available)
1000 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
1001 IDirect3DSurface8_Release(rt);
1003 else
1005 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
1008 refcount = IDirect3DDevice8_Release(device);
1009 ok(!refcount, "Device has %lu references left.\n", refcount);
1010 cleanup:
1011 IDirect3D8_Release(d3d);
1012 DestroyWindow(window);
1015 static void test_cursor(void)
1017 unsigned int adapter_idx, adapter_count, test_idx;
1018 IDirect3DSurface8 *cursor = NULL;
1019 struct device_desc device_desc;
1020 unsigned int width, height;
1021 IDirect3DDevice8 *device;
1022 HRESULT expected_hr, hr;
1023 D3DDISPLAYMODE mode;
1024 CURSORINFO info;
1025 IDirect3D8 *d3d;
1026 ULONG refcount;
1027 HCURSOR cur;
1028 HWND window;
1029 BOOL ret;
1031 static const DWORD device_flags[] = {0, CREATE_DEVICE_FULLSCREEN};
1032 static const SIZE cursor_sizes[] =
1034 {1, 1},
1035 {2, 4},
1036 {3, 2},
1037 {2, 3},
1038 {6, 6},
1041 window = create_window();
1042 ok(!!window, "Failed to create a window.\n");
1044 ret = SetCursorPos(50, 50);
1045 ok(ret, "Failed to set cursor position.\n");
1046 flush_events();
1048 memset(&info, 0, sizeof(info));
1049 info.cbSize = sizeof(info);
1050 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1051 cur = info.hCursor;
1053 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1054 ok(!!d3d, "Failed to create a D3D object.\n");
1055 if (!(device = create_device(d3d, window, NULL)))
1057 skip("Failed to create a 3D device, skipping test.\n");
1058 goto cleanup;
1061 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
1062 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#lx.\n", hr);
1064 /* Initially hidden */
1065 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
1066 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
1068 /* Not enabled without a surface*/
1069 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
1070 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
1072 /* Fails */
1073 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, NULL);
1074 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
1076 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1077 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1079 IDirect3DSurface8_Release(cursor);
1081 /* On the testbot the cursor handle does not behave as expected in rare situations,
1082 * leading to random test failures. Either the cursor handle changes before we expect
1083 * it to, or it doesn't change afterwards (or already changed before we read the
1084 * initial handle?). I was not able to reproduce this on my own machines. Moving the
1085 * mouse outside the window results in similar behavior. However, I tested various
1086 * obvious failure causes: Was the mouse moved? Was the window hidden or moved? Is
1087 * the window in the background? Neither of those applies. Making the window topmost
1088 * or using a fullscreen device doesn't improve the test's reliability either. */
1089 memset(&info, 0, sizeof(info));
1090 info.cbSize = sizeof(info);
1091 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1092 ok(info.flags & (CURSOR_SHOWING | CURSOR_SUPPRESSED), "Got cursor flags %#lx.\n", info.flags);
1093 ok(info.hCursor == cur || broken(1), "The cursor handle is %p\n", info.hCursor); /* unchanged */
1095 /* Still hidden */
1096 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
1097 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
1099 /* Enabled now*/
1100 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
1101 ok(ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
1103 memset(&info, 0, sizeof(info));
1104 info.cbSize = sizeof(info);
1105 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1106 ok(info.flags & (CURSOR_SHOWING | CURSOR_SUPPRESSED), "Got cursor flags %#lx.\n", info.flags);
1107 ok(info.hCursor != cur || broken(1), "The cursor handle is %p\n", info.hCursor);
1109 /* Cursor dimensions must all be powers of two */
1110 for (test_idx = 0; test_idx < ARRAY_SIZE(cursor_sizes); ++test_idx)
1112 width = cursor_sizes[test_idx].cx;
1113 height = cursor_sizes[test_idx].cy;
1114 hr = IDirect3DDevice8_CreateImageSurface(device, width, height, D3DFMT_A8R8G8B8, &cursor);
1115 ok(hr == D3D_OK, "Test %u: CreateImageSurface failed, hr %#lx.\n", test_idx, hr);
1116 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1117 if (width && !(width & (width - 1)) && height && !(height & (height - 1)))
1118 expected_hr = D3D_OK;
1119 else
1120 expected_hr = D3DERR_INVALIDCALL;
1121 ok(hr == expected_hr, "Test %u: Expect SetCursorProperties return %#lx, got %#lx.\n",
1122 test_idx, expected_hr, hr);
1123 IDirect3DSurface8_Release(cursor);
1126 refcount = IDirect3DDevice8_Release(device);
1127 ok(!refcount, "Device has %lu references left.\n", refcount);
1129 /* Cursor dimensions must not exceed adapter display mode */
1130 device_desc.device_window = window;
1131 device_desc.width = 640;
1132 device_desc.height = 480;
1134 adapter_count = IDirect3D8_GetAdapterCount(d3d);
1135 for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
1137 for (test_idx = 0; test_idx < ARRAY_SIZE(device_flags); ++test_idx)
1139 device_desc.adapter_ordinal = adapter_idx;
1140 device_desc.flags = device_flags[test_idx];
1141 if (!(device = create_device(d3d, window, &device_desc)))
1143 skip("Adapter %u test %u: Failed to create a D3D device.\n", adapter_idx, test_idx);
1144 break;
1147 hr = IDirect3D8_GetAdapterDisplayMode(d3d, adapter_idx, &mode);
1148 ok(hr == D3D_OK, "Adapter %u test %u: GetAdapterDisplayMode failed, hr %#lx.\n",
1149 adapter_idx, test_idx, hr);
1151 /* Find the largest width and height that are powers of two and less than the display mode */
1152 width = 1;
1153 height = 1;
1154 while (width * 2 <= mode.Width)
1155 width *= 2;
1156 while (height * 2 <= mode.Height)
1157 height *= 2;
1159 hr = IDirect3DDevice8_CreateImageSurface(device, width, height, D3DFMT_A8R8G8B8, &cursor);
1160 ok(hr == D3D_OK, "Adapter %u test %u: CreateImageSurface failed, hr %#lx.\n",
1161 adapter_idx, test_idx, hr);
1162 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1163 ok(hr == D3D_OK, "Adapter %u test %u: SetCursorProperties failed, hr %#lx.\n",
1164 adapter_idx, test_idx, hr);
1165 IDirect3DSurface8_Release(cursor);
1167 hr = IDirect3DDevice8_CreateImageSurface(device, width * 2, height, D3DFMT_A8R8G8B8,
1168 &cursor);
1169 ok(hr == D3D_OK, "Adapter %u test %u: CreateImageSurface failed, hr %#lx.\n",
1170 adapter_idx, test_idx, hr);
1171 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1172 ok(hr == D3DERR_INVALIDCALL, "Adapter %u test %u: Got hr %#lx.\n", adapter_idx, test_idx, hr);
1173 IDirect3DSurface8_Release(cursor);
1175 hr = IDirect3DDevice8_CreateImageSurface(device, width, height * 2, D3DFMT_A8R8G8B8,
1176 &cursor);
1177 ok(hr == D3D_OK, "Adapter %u test %u: CreateImageSurface failed, hr %#lx.\n",
1178 adapter_idx, test_idx, hr);
1179 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1180 ok(hr == D3DERR_INVALIDCALL, "Adapter %u test %u: Got hr %#lx.\n", adapter_idx, test_idx, hr);
1181 IDirect3DSurface8_Release(cursor);
1183 refcount = IDirect3DDevice8_Release(device);
1184 ok(!refcount, "Adapter %u: Device has %lu references left.\n", adapter_idx, refcount);
1187 cleanup:
1188 IDirect3D8_Release(d3d);
1189 DestroyWindow(window);
1192 static const POINT *expect_pos;
1194 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
1196 if (message == WM_MOUSEMOVE)
1198 if (expect_pos && expect_pos->x && expect_pos->y)
1200 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
1202 ClientToScreen(window, &p);
1203 if (expect_pos->x == p.x && expect_pos->y == p.y)
1204 ++expect_pos;
1208 return DefWindowProcA(window, message, wparam, lparam);
1211 static void test_cursor_pos(void)
1213 IDirect3DSurface8 *cursor;
1214 IDirect3DDevice8 *device;
1215 WNDCLASSA wc = {0};
1216 IDirect3D8 *d3d8;
1217 UINT refcount;
1218 HWND window;
1219 HRESULT hr;
1220 BOOL ret;
1221 POINT pt;
1223 /* Note that we don't check for movement we're not supposed to receive.
1224 * That's because it's hard to distinguish from the user accidentally
1225 * moving the mouse. */
1226 static const POINT points[] =
1228 {50, 50},
1229 {75, 75},
1230 {100, 100},
1231 {125, 125},
1232 {150, 150},
1233 {125, 125},
1234 {150, 150},
1235 {150, 150},
1236 {0, 0},
1239 /* Windows 10 1709 is unreliable. One or more of the cursor movements we
1240 * expect don't show up. Moving the mouse to a defined position beforehand
1241 * seems to get it into better shape - only the final 150x150 move we do
1242 * below is missing - it looks as if this Windows version filters redundant
1243 * SetCursorPos calls on the user32 level, although I am not entirely sure.
1245 * The weird thing is that the previous test leaves the cursor position
1246 * reliably at 512x384 on the testbot. So the 50x50 mouse move shouldn't
1247 * be stripped away anyway, but it might be a difference between moving the
1248 * cursor through SetCursorPos vs moving it by changing the display mode. */
1249 ret = SetCursorPos(99, 99);
1250 ok(ret, "Failed to set cursor position.\n");
1251 flush_events();
1253 /* Check if we can move the cursor. If we're running in a virtual desktop
1254 * that does not have focus or the mouse is outside the desktop window, some
1255 * window managers (e.g. kwin) will refuse to let us steal the pointer. That
1256 * is reasonable, but breaks the test. */
1257 ret = GetCursorPos(&pt);
1258 ok(ret, "Failed to get cursor position.\n");
1259 if (pt.x != 99 || pt.y != 99)
1261 skip("Could not warp the cursor (cur pos %ld,%ld), skipping test.\n", pt.x, pt.y);
1262 return;
1265 wc.lpfnWndProc = test_cursor_proc;
1266 wc.lpszClassName = "d3d8_test_cursor_wc";
1267 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1268 window = CreateWindowA("d3d8_test_cursor_wc", "d3d8_test", WS_POPUP | WS_SYSMENU,
1269 0, 0, 320, 240, NULL, NULL, NULL, NULL);
1270 ShowWindow(window, SW_SHOW);
1271 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1272 ok(!!d3d8, "Failed to create a D3D object.\n");
1274 if (!(device = create_device(d3d8, window, NULL)))
1276 skip("Failed to create a D3D device, skipping tests.\n");
1277 goto done;
1280 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
1281 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#lx.\n", hr);
1282 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1283 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#lx.\n", hr);
1284 IDirect3DSurface8_Release(cursor);
1285 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
1286 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
1288 flush_events();
1289 expect_pos = points;
1291 ret = SetCursorPos(50, 50);
1292 ok(ret, "Failed to set cursor position.\n");
1293 flush_events();
1295 IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
1296 flush_events();
1297 /* SetCursorPosition() eats duplicates. FIXME: Since we accept unexpected
1298 * mouse moves the test doesn't actually demonstrate that. */
1299 IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
1300 flush_events();
1302 ret = SetCursorPos(100, 100);
1303 ok(ret, "Failed to set cursor position.\n");
1304 flush_events();
1305 /* Even if the position was set with SetCursorPos(). */
1306 IDirect3DDevice8_SetCursorPosition(device, 100, 100, 0);
1307 flush_events();
1309 IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
1310 flush_events();
1311 ret = SetCursorPos(150, 150);
1312 ok(ret, "Failed to set cursor position.\n");
1313 flush_events();
1314 IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
1315 flush_events();
1317 IDirect3DDevice8_SetCursorPosition(device, 150, 150, 0);
1318 flush_events();
1319 /* SetCursorPos() doesn't. Except for Win10 1709. */
1320 ret = SetCursorPos(150, 150);
1321 ok(ret, "Failed to set cursor position.\n");
1322 flush_events();
1324 ok((!expect_pos->x && !expect_pos->y) || broken(expect_pos - points == 7),
1325 "Didn't receive MOUSEMOVE %u (%ld, %ld).\n",
1326 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
1328 refcount = IDirect3DDevice8_Release(device);
1329 ok(!refcount, "Device has %u references left.\n", refcount);
1330 done:
1331 DestroyWindow(window);
1332 UnregisterClassA("d3d8_test_cursor_wc", GetModuleHandleA(NULL));
1333 IDirect3D8_Release(d3d8);
1336 static void test_states(void)
1338 IDirect3DDevice8 *device;
1339 IDirect3D8 *d3d;
1340 ULONG refcount;
1341 HWND window;
1342 HRESULT hr;
1344 window = create_window();
1345 ok(!!window, "Failed to create a window.\n");
1346 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1347 ok(!!d3d, "Failed to create a D3D object.\n");
1348 if (!(device = create_device(d3d, window, NULL)))
1350 skip("Failed to create a 3D device, skipping test.\n");
1351 goto cleanup;
1354 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZVISIBLE, TRUE);
1355 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1356 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZVISIBLE, FALSE);
1357 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
1359 refcount = IDirect3DDevice8_Release(device);
1360 ok(!refcount, "Device has %lu references left.\n", refcount);
1361 cleanup:
1362 IDirect3D8_Release(d3d);
1363 DestroyWindow(window);
1366 static void test_shader_versions(void)
1368 IDirect3D8 *d3d;
1369 D3DCAPS8 caps;
1370 HRESULT hr;
1372 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1373 ok(!!d3d, "Failed to create a D3D object.\n");
1375 hr = IDirect3D8_GetDeviceCaps(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
1376 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to get device caps, hr %#lx.\n", hr);
1377 IDirect3D8_Release(d3d);
1378 if (FAILED(hr))
1380 skip("No Direct3D support, skipping test.\n");
1381 return;
1384 ok(caps.VertexShaderVersion <= D3DVS_VERSION(1,1),
1385 "Got unexpected VertexShaderVersion %#lx.\n", caps.VertexShaderVersion);
1386 ok(caps.PixelShaderVersion <= D3DPS_VERSION(1,4),
1387 "Got unexpected PixelShaderVersion %#lx.\n", caps.PixelShaderVersion);
1390 static void test_display_formats(void)
1392 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
1393 unsigned int backbuffer, display;
1394 unsigned int windowed, i;
1395 D3DDISPLAYMODE mode;
1396 IDirect3D8 *d3d8;
1397 BOOL should_pass;
1398 BOOL has_modes;
1399 HRESULT hr;
1401 static const struct
1403 const char *name;
1404 D3DFORMAT format;
1405 D3DFORMAT alpha_format;
1406 BOOL display;
1407 BOOL windowed;
1409 formats[] =
1411 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
1412 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
1413 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
1414 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
1415 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
1416 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
1419 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1420 ok(!!d3d8, "Failed to create a D3D object.\n");
1422 for (display = 0; display < ARRAY_SIZE(formats); ++display)
1424 for (i = 0, has_modes = FALSE; SUCCEEDED(IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &mode)); ++i)
1426 if (mode.Format == formats[display].format)
1428 has_modes = TRUE;
1429 break;
1433 for (windowed = 0; windowed <= 1; ++windowed)
1435 for (backbuffer = 0; backbuffer < ARRAY_SIZE(formats); ++backbuffer)
1437 should_pass = FALSE;
1439 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
1441 D3DFORMAT backbuffer_format;
1443 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
1444 backbuffer_format = formats[display].format;
1445 else
1446 backbuffer_format = formats[backbuffer].format;
1448 hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, device_type, formats[display].format,
1449 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
1450 should_pass = (hr == D3D_OK) && (formats[display].format == formats[backbuffer].format
1451 || (formats[display].alpha_format
1452 && formats[display].alpha_format == formats[backbuffer].alpha_format));
1455 hr = IDirect3D8_CheckDeviceType(d3d8, D3DADAPTER_DEFAULT, device_type,
1456 formats[display].format, formats[backbuffer].format, windowed);
1457 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
1458 "Got unexpected hr %#lx for %s / %s, windowed %#x, should_pass %#x.\n",
1459 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
1464 IDirect3D8_Release(d3d8);
1467 /* Test adapter display modes */
1468 static void test_display_modes(void)
1470 UINT max_modes, i;
1471 D3DDISPLAYMODE dmode;
1472 IDirect3D8 *d3d;
1473 HRESULT res;
1475 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1476 ok(!!d3d, "Failed to create a D3D object.\n");
1478 max_modes = IDirect3D8_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT);
1479 ok(max_modes > 0 ||
1480 broken(max_modes == 0), /* VMware */
1481 "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
1483 for (i = 0; i < max_modes; ++i)
1485 res = IDirect3D8_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, i, &dmode);
1486 ok(res==D3D_OK, "EnumAdapterModes returned %#08lx for mode %u!\n", res, i);
1487 if(res != D3D_OK)
1488 continue;
1490 ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
1491 "Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
1494 IDirect3D8_Release(d3d);
1497 struct mode
1499 unsigned int w;
1500 unsigned int h;
1503 static int compare_mode(const void *a, const void *b)
1505 const struct mode *mode_a = a;
1506 const struct mode *mode_b = b;
1507 int w = mode_a->w - mode_b->w;
1508 int h = mode_a->h - mode_b->h;
1509 return abs(w) >= abs(h) ? -w : -h;
1512 static void test_reset(void)
1514 UINT width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1515 UINT height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1516 IDirect3DDevice8 *device1 = NULL;
1517 IDirect3DDevice8 *device2 = NULL;
1518 struct device_desc device_desc;
1519 D3DDISPLAYMODE d3ddm, d3ddm2;
1520 D3DSURFACE_DESC surface_desc;
1521 D3DPRESENT_PARAMETERS d3dpp;
1522 IDirect3DSurface8 *surface;
1523 IDirect3DTexture8 *texture;
1524 IDirect3DVertexBuffer8 *vb;
1525 IDirect3DIndexBuffer8 *ib;
1526 UINT adapter_mode_count;
1527 D3DLOCKED_RECT lockrect;
1528 UINT mode_count = 0;
1529 DEVMODEW devmode;
1530 IDirect3D8 *d3d8;
1531 RECT winrect, client_rect;
1532 D3DVIEWPORT8 vp;
1533 ULONG refcount;
1534 D3DCAPS8 caps;
1535 DWORD shader;
1536 DWORD value;
1537 HWND window;
1538 HRESULT hr;
1539 LONG ret;
1540 UINT i;
1542 static const DWORD decl[] =
1544 D3DVSD_STREAM(0),
1545 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4),
1546 D3DVSD_END(),
1549 struct mode *modes = NULL;
1551 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1552 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1553 ok(!!window, "Failed to create a window.\n");
1554 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1555 ok(!!d3d8, "Failed to create a D3D object.\n");
1557 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1558 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
1559 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
1560 modes = malloc(sizeof(*modes) * adapter_mode_count);
1561 for (i = 0; i < adapter_mode_count; ++i)
1563 UINT j;
1565 memset(&d3ddm2, 0, sizeof(d3ddm2));
1566 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm2);
1567 ok(SUCCEEDED(hr), "EnumAdapterModes failed, hr %#lx.\n", hr);
1569 if (d3ddm2.Format != d3ddm.Format)
1570 continue;
1572 for (j = 0; j < mode_count; ++j)
1574 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1575 break;
1577 if (j == mode_count)
1579 modes[j].w = d3ddm2.Width;
1580 modes[j].h = d3ddm2.Height;
1581 ++mode_count;
1584 /* We use them as invalid modes. */
1585 if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
1586 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
1588 skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
1589 d3ddm2.Width, d3ddm2.Height);
1590 goto cleanup;
1594 if (mode_count < 2)
1596 skip("Less than 2 modes supported, skipping mode tests.\n");
1597 goto cleanup;
1600 /* Prefer higher resolutions. */
1601 qsort(modes, mode_count, sizeof(*modes), compare_mode);
1603 i = 0;
1604 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1606 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
1607 device_desc.width = modes[i].w;
1608 device_desc.height = modes[i].h;
1609 device_desc.device_window = window;
1610 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1611 if (!(device1 = create_device(d3d8, window, &device_desc)))
1613 skip("Failed to create a D3D device, skipping tests.\n");
1614 goto cleanup;
1616 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1617 /* This skips the test on testbot Win 8 VMs. */
1618 if (hr == D3DERR_DEVICELOST)
1620 skip("Device is lost.\n");
1621 goto cleanup;
1623 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1625 hr = IDirect3DDevice8_GetDeviceCaps(device1, &caps);
1626 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#lx.\n", hr);
1628 width = GetSystemMetrics(SM_CXSCREEN);
1629 height = GetSystemMetrics(SM_CYSCREEN);
1630 ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1631 ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1633 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1634 ok(SUCCEEDED(hr), "GetViewport failed, hr %#lx.\n", hr);
1635 ok(vp.X == 0, "D3DVIEWPORT->X = %lu, expected 0.\n", vp.X);
1636 ok(vp.Y == 0, "D3DVIEWPORT->Y = %lu, expected 0.\n", vp.Y);
1637 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %lu, expected %u.\n", vp.Width, modes[i].w);
1638 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %lu, expected %u.\n", vp.Height, modes[i].h);
1639 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1640 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1642 i = 1;
1643 vp.X = 10;
1644 vp.Y = 20;
1645 vp.Width = modes[i].w / 2;
1646 vp.Height = modes[i].h / 2;
1647 vp.MinZ = 0.2f;
1648 vp.MaxZ = 0.3f;
1649 hr = IDirect3DDevice8_SetViewport(device1, &vp);
1650 ok(SUCCEEDED(hr), "SetViewport failed, hr %#lx.\n", hr);
1652 hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1653 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
1654 ok(!!value, "Got unexpected value %#lx for D3DRS_LIGHTING.\n", value);
1655 hr = IDirect3DDevice8_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1656 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
1658 memset(&d3dpp, 0, sizeof(d3dpp));
1659 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1660 d3dpp.Windowed = FALSE;
1661 d3dpp.BackBufferWidth = modes[i].w;
1662 d3dpp.BackBufferHeight = modes[i].h;
1663 d3dpp.BackBufferFormat = d3ddm.Format;
1664 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1665 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1666 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1667 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1669 hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1670 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
1671 ok(!!value, "Got unexpected value %#lx for D3DRS_LIGHTING.\n", value);
1673 memset(&vp, 0, sizeof(vp));
1674 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1675 ok(SUCCEEDED(hr), "GetViewport failed, hr %#lx.\n", hr);
1676 ok(vp.X == 0, "D3DVIEWPORT->X = %lu, expected 0.\n", vp.X);
1677 ok(vp.Y == 0, "D3DVIEWPORT->Y = %lu, expected 0.\n", vp.Y);
1678 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %lu, expected %u.\n", vp.Width, modes[i].w);
1679 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %lu, expected %u.\n", vp.Height, modes[i].h);
1680 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1681 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1683 width = GetSystemMetrics(SM_CXSCREEN);
1684 height = GetSystemMetrics(SM_CYSCREEN);
1685 ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1686 ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1688 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1689 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#lx.\n", hr);
1690 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1691 ok(hr == D3D_OK, "GetDesc failed, hr %#lx.\n", hr);
1692 ok(surface_desc.Width == modes[i].w, "Back buffer width is %u, expected %u.\n",
1693 surface_desc.Width, modes[i].w);
1694 ok(surface_desc.Height == modes[i].h, "Back buffer height is %u, expected %u.\n",
1695 surface_desc.Height, modes[i].h);
1696 IDirect3DSurface8_Release(surface);
1698 memset(&d3dpp, 0, sizeof(d3dpp));
1699 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1700 d3dpp.Windowed = TRUE;
1701 d3dpp.BackBufferWidth = 400;
1702 d3dpp.BackBufferHeight = 300;
1703 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1704 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1705 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1706 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1707 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1709 memset(&vp, 0, sizeof(vp));
1710 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1711 ok(SUCCEEDED(hr), "GetViewport failed, hr %#lx.\n", hr);
1712 ok(vp.X == 0, "D3DVIEWPORT->X = %lu, expected 0.\n", vp.X);
1713 ok(vp.Y == 0, "D3DVIEWPORT->Y = %lu, expected 0.\n", vp.Y);
1714 ok(vp.Width == 400, "D3DVIEWPORT->Width = %lu, expected 400.\n", vp.Width);
1715 ok(vp.Height == 300, "D3DVIEWPORT->Height = %lu, expected 300.\n", vp.Height);
1716 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1717 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1719 width = GetSystemMetrics(SM_CXSCREEN);
1720 height = GetSystemMetrics(SM_CYSCREEN);
1721 ok(width == orig_width, "Screen width is %u, expected %u.\n", width, orig_width);
1722 ok(height == orig_height, "Screen height is %u, expected %u.\n", height, orig_height);
1724 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1725 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#lx.\n", hr);
1726 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1727 ok(hr == D3D_OK, "GetDesc failed, hr %#lx.\n", hr);
1728 ok(surface_desc.Width == 400, "Back buffer width is %u, expected 400.\n",
1729 surface_desc.Width);
1730 ok(surface_desc.Height == 300, "Back buffer height is %u, expected 300.\n",
1731 surface_desc.Height);
1732 IDirect3DSurface8_Release(surface);
1734 memset(&devmode, 0, sizeof(devmode));
1735 devmode.dmSize = sizeof(devmode);
1736 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1737 devmode.dmPelsWidth = modes[1].w;
1738 devmode.dmPelsHeight = modes[1].h;
1739 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1740 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", ret);
1741 width = GetSystemMetrics(SM_CXSCREEN);
1742 height = GetSystemMetrics(SM_CYSCREEN);
1743 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1744 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1746 d3dpp.BackBufferWidth = 500;
1747 d3dpp.BackBufferHeight = 400;
1748 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1749 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1750 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1751 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1752 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1754 width = GetSystemMetrics(SM_CXSCREEN);
1755 height = GetSystemMetrics(SM_CYSCREEN);
1756 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1757 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1759 ZeroMemory(&vp, sizeof(vp));
1760 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1761 ok(SUCCEEDED(hr), "GetViewport failed, hr %#lx.\n", hr);
1762 ok(vp.X == 0, "D3DVIEWPORT->X = %ld.\n", vp.X);
1763 ok(vp.Y == 0, "D3DVIEWPORT->Y = %ld.\n", vp.Y);
1764 ok(vp.Width == 500, "D3DVIEWPORT->Width = %ld.\n", vp.Width);
1765 ok(vp.Height == 400, "D3DVIEWPORT->Height = %ld.\n", vp.Height);
1766 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
1767 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
1769 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1770 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#lx.\n", hr);
1771 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1772 ok(hr == D3D_OK, "GetDesc failed, hr %#lx.\n", hr);
1773 ok(surface_desc.Width == 500, "Back buffer width is %u, expected 500.\n",
1774 surface_desc.Width);
1775 ok(surface_desc.Height == 400, "Back buffer height is %u, expected 400.\n",
1776 surface_desc.Height);
1777 IDirect3DSurface8_Release(surface);
1779 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1780 devmode.dmPelsWidth = orig_width;
1781 devmode.dmPelsHeight = orig_height;
1782 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1783 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", ret);
1784 width = GetSystemMetrics(SM_CXSCREEN);
1785 height = GetSystemMetrics(SM_CYSCREEN);
1786 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1787 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1789 winrect.left = 0;
1790 winrect.top = 0;
1791 winrect.right = 200;
1792 winrect.bottom = 150;
1793 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1794 ok(SetWindowPos(window, NULL, 0, 0,
1795 winrect.right-winrect.left,
1796 winrect.bottom-winrect.top,
1797 SWP_NOMOVE|SWP_NOZORDER),
1798 "SetWindowPos failed\n");
1800 /* Windows 10 gives us a different size than we requested with some DPI scaling settings (e.g. 172%). */
1801 GetClientRect(window, &client_rect);
1803 memset(&d3dpp, 0, sizeof(d3dpp));
1804 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1805 d3dpp.Windowed = TRUE;
1806 d3dpp.BackBufferWidth = 0;
1807 d3dpp.BackBufferHeight = 0;
1808 d3dpp.BackBufferFormat = d3ddm.Format;
1809 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1810 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1811 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1812 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1814 ok(!d3dpp.BackBufferWidth, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1815 ok(!d3dpp.BackBufferHeight, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1816 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1817 d3dpp.BackBufferFormat, d3ddm.Format);
1818 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1819 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1820 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1821 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1822 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1823 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1824 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1825 ok(!d3dpp.Flags, "Got unexpected Flags %#lx.\n", d3dpp.Flags);
1826 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1827 d3dpp.FullScreen_RefreshRateInHz);
1828 ok(!d3dpp.FullScreen_PresentationInterval, "Got unexpected FullScreen_PresentationInterval %#x.\n",
1829 d3dpp.FullScreen_PresentationInterval);
1831 memset(&vp, 0, sizeof(vp));
1832 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1833 ok(SUCCEEDED(hr), "GetViewport failed, hr %#lx.\n", hr);
1834 if (SUCCEEDED(hr))
1836 ok(vp.X == 0, "D3DVIEWPORT->X = %lu, expected 0.\n", vp.X);
1837 ok(vp.Y == 0, "D3DVIEWPORT->Y = %lu, expected 0.\n", vp.Y);
1838 ok(vp.Width == client_rect.right, "D3DVIEWPORT->Width = %ld, expected %ld.\n",
1839 vp.Width, client_rect.right);
1840 ok(vp.Height == client_rect.bottom, "D3DVIEWPORT->Height = %ld, expected %ld.\n",
1841 vp.Height, client_rect.bottom);
1842 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1843 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1846 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1847 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#lx.\n", hr);
1848 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1849 ok(hr == D3D_OK, "GetDesc failed, hr %#lx.\n", hr);
1850 ok(surface_desc.Format == d3ddm.Format, "Got unexpected Format %#x, expected %#x.\n",
1851 surface_desc.Format, d3ddm.Format);
1852 ok(!surface_desc.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1853 ok(surface_desc.Width == client_rect.right,
1854 "Back buffer width is %u, expected %ld.\n", surface_desc.Width, client_rect.right);
1855 ok(surface_desc.Height == client_rect.bottom,
1856 "Back buffer height is %u, expected %ld.\n", surface_desc.Height, client_rect.bottom);
1857 IDirect3DSurface8_Release(surface);
1859 memset(&d3dpp, 0, sizeof(d3dpp));
1860 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1861 d3dpp.Windowed = TRUE;
1862 d3dpp.BackBufferWidth = 400;
1863 d3dpp.BackBufferHeight = 300;
1864 d3dpp.BackBufferFormat = d3ddm.Format;
1866 /* Reset fails if there is a resource in the default pool. */
1867 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texture);
1868 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#lx.\n", hr);
1869 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1870 ok(hr == D3DERR_DEVICELOST, "Got hr %#lx.\n", hr);
1871 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1872 ok(hr == D3DERR_DEVICENOTRESET, "Got hr %#lx.\n", hr);
1873 IDirect3DTexture8_Release(texture);
1874 /* Reset again to get the device out of the lost state. */
1875 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1876 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1877 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1878 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1880 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1882 IDirect3DVolumeTexture8 *volume_texture;
1884 hr = IDirect3DDevice8_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1885 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture);
1886 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#lx.\n", hr);
1887 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1888 ok(hr == D3DERR_DEVICELOST, "Got hr %#lx.\n", hr);
1889 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1890 ok(hr == D3DERR_DEVICENOTRESET, "Got hr %#lx.\n", hr);
1891 IDirect3DVolumeTexture8_Release(volume_texture);
1892 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1893 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1894 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1895 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1897 else
1899 skip("Volume textures not supported.\n");
1902 /* Test with DEFAULT pool resources bound but otherwise not referenced. */
1903 hr = IDirect3DDevice8_CreateVertexBuffer(device1, 16, 0,
1904 D3DFVF_XYZ, D3DPOOL_DEFAULT, &vb);
1905 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1906 hr = IDirect3DDevice8_SetStreamSource(device1, 0, vb, 16);
1907 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1908 refcount = IDirect3DVertexBuffer8_Release(vb);
1909 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1910 hr = IDirect3DDevice8_CreateIndexBuffer(device1, 16, 0,
1911 D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib);
1912 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1913 hr = IDirect3DDevice8_SetIndices(device1, ib, 0);
1914 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1915 refcount = IDirect3DIndexBuffer8_Release(ib);
1916 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1917 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 0, 0,
1918 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
1919 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1920 hr = IDirect3DDevice8_SetTexture(device1, i, (IDirect3DBaseTexture8 *)texture);
1921 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1923 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1924 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#lx.\n", hr);
1925 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1926 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#lx.\n", hr);
1928 /* Crashes on Windows. */
1929 if (0)
1931 hr = IDirect3DDevice8_GetIndices(device1, &ib, &i);
1932 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
1934 refcount = IDirect3DTexture8_Release(texture);
1935 ok(!refcount, "Unexpected refcount %lu.\n", refcount);
1937 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1938 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1939 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1940 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
1942 /* Scratch, sysmem and managed pool resources are fine. */
1943 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1944 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#lx.\n", hr);
1945 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1946 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1947 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1948 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1949 IDirect3DTexture8_Release(texture);
1951 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1952 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#lx.\n", hr);
1953 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1954 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1955 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1956 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
1957 IDirect3DTexture8_Release(texture);
1959 hr = IDirect3DDevice8_CreateVertexBuffer(device1, 16, 0,
1960 D3DFVF_XYZ, D3DPOOL_SYSTEMMEM, &vb);
1961 ok(hr == D3D_OK, "Failed to create vertex buffer, hr %#lx.\n", hr);
1962 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1963 ok(hr == D3D_OK, "Failed to reset device, hr %#lx.\n", hr);
1964 IDirect3DVertexBuffer8_Release(vb);
1966 hr = IDirect3DDevice8_CreateIndexBuffer(device1, 16, 0,
1967 D3DFMT_INDEX16, D3DPOOL_SYSTEMMEM, &ib);
1968 ok(hr == D3D_OK, "Failed to create index buffer, hr %#lx.\n", hr);
1969 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1970 ok(hr == D3D_OK, "Failed to reset device, hr %#lx.\n", hr);
1971 IDirect3DIndexBuffer8_Release(ib);
1973 /* The depth stencil should get reset to the auto depth stencil when present. */
1974 hr = IDirect3DDevice8_SetRenderTarget(device1, NULL, NULL);
1975 ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#lx.\n", hr);
1977 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1978 ok(hr == D3DERR_NOTFOUND, "Got hr %#lx.\n", hr);
1979 ok(!surface, "Depth / stencil buffer should be NULL.\n");
1981 d3dpp.EnableAutoDepthStencil = TRUE;
1982 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1983 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1984 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1986 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1987 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#lx.\n", hr);
1988 ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1989 if (surface) IDirect3DSurface8_Release(surface);
1991 d3dpp.EnableAutoDepthStencil = FALSE;
1992 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1993 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
1995 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1996 ok(hr == D3DERR_NOTFOUND, "Got hr %#lx.\n", hr);
1997 ok(!surface, "Depth / stencil buffer should be NULL.\n");
1999 /* Will a sysmem or scratch resource survive while locked? */
2000 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
2001 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#lx.\n", hr);
2002 hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
2003 ok(SUCCEEDED(hr), "LockRect failed, hr %#lx.\n", hr);
2004 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2005 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
2006 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2007 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
2008 IDirect3DTexture8_UnlockRect(texture, 0);
2009 IDirect3DTexture8_Release(texture);
2011 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
2012 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#lx.\n", hr);
2013 hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
2014 ok(SUCCEEDED(hr), "LockRect failed, hr %#lx.\n", hr);
2015 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2016 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
2017 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2018 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
2019 IDirect3DTexture8_UnlockRect(texture, 0);
2020 IDirect3DTexture8_Release(texture);
2022 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture);
2023 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#lx.\n", hr);
2024 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2025 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
2026 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2027 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
2028 IDirect3DTexture8_Release(texture);
2030 /* A reference held to an implicit surface causes failures as well. */
2031 hr = IDirect3DDevice8_GetBackBuffer(device1, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2032 ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#lx.\n", hr);
2033 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2034 ok(hr == D3DERR_DEVICELOST, "Got hr %#lx.\n", hr);
2035 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2036 ok(hr == D3DERR_DEVICENOTRESET, "Got hr %#lx.\n", hr);
2037 IDirect3DSurface8_Release(surface);
2038 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2039 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
2040 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2041 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
2043 /* Shaders are fine as well. */
2044 hr = IDirect3DDevice8_CreateVertexShader(device1, decl, simple_vs, &shader, 0);
2045 ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#lx.\n", hr);
2046 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2047 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
2048 hr = IDirect3DDevice8_DeleteVertexShader(device1, shader);
2049 ok(SUCCEEDED(hr), "DeleteVertexShader failed, hr %#lx.\n", hr);
2051 /* Try setting invalid modes. */
2052 memset(&d3dpp, 0, sizeof(d3dpp));
2053 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2054 d3dpp.Windowed = FALSE;
2055 d3dpp.BackBufferWidth = 32;
2056 d3dpp.BackBufferHeight = 32;
2057 d3dpp.BackBufferFormat = d3ddm.Format;
2058 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2059 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2060 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2061 ok(hr == D3DERR_DEVICENOTRESET, "Got hr %#lx.\n", hr);
2063 memset(&d3dpp, 0, sizeof(d3dpp));
2064 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2065 d3dpp.Windowed = FALSE;
2066 d3dpp.BackBufferWidth = 801;
2067 d3dpp.BackBufferHeight = 600;
2068 d3dpp.BackBufferFormat = d3ddm.Format;
2069 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2070 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2071 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2072 ok(hr == D3DERR_DEVICENOTRESET, "Got hr %#lx.\n", hr);
2074 memset(&d3dpp, 0, sizeof(d3dpp));
2075 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2076 d3dpp.Windowed = FALSE;
2077 d3dpp.BackBufferWidth = 0;
2078 d3dpp.BackBufferHeight = 0;
2079 d3dpp.BackBufferFormat = d3ddm.Format;
2080 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
2081 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2082 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
2083 ok(hr == D3DERR_DEVICENOTRESET, "Got hr %#lx.\n", hr);
2085 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
2086 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
2088 memset(&d3dpp, 0, sizeof(d3dpp));
2089 d3dpp.Windowed = TRUE;
2090 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2091 d3dpp.BackBufferFormat = d3ddm.Format;
2092 d3dpp.EnableAutoDepthStencil = FALSE;
2093 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2095 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2096 window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
2097 if (FAILED(hr))
2099 skip("Failed to create device, hr %#lx.\n", hr);
2100 goto cleanup;
2103 hr = IDirect3DDevice8_TestCooperativeLevel(device2);
2104 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#lx.\n", hr);
2106 d3dpp.Windowed = TRUE;
2107 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2108 d3dpp.BackBufferWidth = 400;
2109 d3dpp.BackBufferHeight = 300;
2110 d3dpp.BackBufferFormat = d3ddm.Format;
2111 d3dpp.EnableAutoDepthStencil = TRUE;
2112 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2114 hr = IDirect3DDevice8_Reset(device2, &d3dpp);
2115 ok(SUCCEEDED(hr), "Reset failed, hr %#lx.\n", hr);
2116 if (FAILED(hr))
2117 goto cleanup;
2119 hr = IDirect3DDevice8_GetDepthStencilSurface(device2, &surface);
2120 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#lx.\n", hr);
2121 ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
2122 if (surface)
2123 IDirect3DSurface8_Release(surface);
2125 cleanup:
2126 free(modes);
2127 if (device2)
2128 IDirect3DDevice8_Release(device2);
2129 if (device1)
2130 IDirect3DDevice8_Release(device1);
2131 IDirect3D8_Release(d3d8);
2132 DestroyWindow(window);
2135 static void test_scene(void)
2137 IDirect3DDevice8 *device;
2138 IDirect3D8 *d3d;
2139 ULONG refcount;
2140 HWND window;
2141 HRESULT hr;
2143 window = create_window();
2144 ok(!!window, "Failed to create a window.\n");
2145 d3d = Direct3DCreate8(D3D_SDK_VERSION);
2146 ok(!!d3d, "Failed to create a D3D object.\n");
2147 if (!(device = create_device(d3d, window, NULL)))
2149 skip("Failed to create a 3D device, skipping test.\n");
2150 goto cleanup;
2153 /* Test an EndScene without BeginScene. Should return an error */
2154 hr = IDirect3DDevice8_EndScene(device);
2155 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2157 /* Test a normal BeginScene / EndScene pair, this should work */
2158 hr = IDirect3DDevice8_BeginScene(device);
2159 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2160 hr = IDirect3DDevice8_EndScene(device);
2161 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2163 /* Test another EndScene without having begun a new scene. Should return an error */
2164 hr = IDirect3DDevice8_EndScene(device);
2165 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2167 /* Two nested BeginScene and EndScene calls */
2168 hr = IDirect3DDevice8_BeginScene(device);
2169 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2170 hr = IDirect3DDevice8_BeginScene(device);
2171 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2172 hr = IDirect3DDevice8_EndScene(device);
2173 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2174 hr = IDirect3DDevice8_EndScene(device);
2175 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2177 /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
2179 refcount = IDirect3DDevice8_Release(device);
2180 ok(!refcount, "Device has %lu references left.\n", refcount);
2181 cleanup:
2182 IDirect3D8_Release(d3d);
2183 DestroyWindow(window);
2186 static void test_shader(void)
2188 DWORD hPixelShader = 0, hVertexShader = 0;
2189 DWORD hPixelShader2 = 0, hVertexShader2 = 0;
2190 DWORD hTempHandle;
2191 D3DCAPS8 caps;
2192 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
2193 IDirect3DDevice8 *device;
2194 IDirect3D8 *d3d;
2195 DWORD data_size;
2196 ULONG refcount;
2197 HWND window;
2198 HRESULT hr;
2199 void *data;
2201 static DWORD dwVertexDecl[] =
2203 D3DVSD_STREAM(0),
2204 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
2205 D3DVSD_END()
2207 DWORD decl_normal_float2[] =
2209 D3DVSD_STREAM(0),
2210 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
2211 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT2), /* D3DVSDE_NORMAL, Register v1 */
2212 D3DVSD_END()
2214 DWORD decl_normal_float4[] =
2216 D3DVSD_STREAM(0),
2217 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
2218 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT4), /* D3DVSDE_NORMAL, Register v1 */
2219 D3DVSD_END()
2221 DWORD decl_normal_d3dcolor[] =
2223 D3DVSD_STREAM(0),
2224 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
2225 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL, Register v1 */
2226 D3DVSD_END()
2228 const DWORD vertex_decl_size = sizeof(dwVertexDecl);
2229 const DWORD simple_vs_size = sizeof(simple_vs);
2230 const DWORD simple_ps_size = sizeof(simple_ps);
2232 window = create_window();
2233 ok(!!window, "Failed to create a window.\n");
2234 d3d = Direct3DCreate8(D3D_SDK_VERSION);
2235 ok(!!d3d, "Failed to create a D3D object.\n");
2236 if (!(device = create_device(d3d, window, NULL)))
2238 skip("Failed to create a 3D device, skipping test.\n");
2239 goto cleanup;
2242 IDirect3DDevice8_GetDeviceCaps(device, &caps);
2244 /* Test setting and retrieving a FVF */
2245 hr = IDirect3DDevice8_SetVertexShader(device, fvf);
2246 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
2247 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2248 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
2249 ok(hTempHandle == fvf, "Got vertex shader %#lx, expected %#lx.\n", hTempHandle, fvf);
2251 /* First create a vertex shader */
2252 hr = IDirect3DDevice8_SetVertexShader(device, 0);
2253 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
2254 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, simple_vs, &hVertexShader, 0);
2255 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2256 /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
2257 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2258 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2259 ok(!hTempHandle, "Got vertex shader %#lx.\n", hTempHandle);
2260 /* Assign the shader, then verify that GetVertexShader works */
2261 hr = IDirect3DDevice8_SetVertexShader(device, hVertexShader);
2262 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2263 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2264 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2265 ok(hTempHandle == hVertexShader, "Got vertex shader %#lx, expected %#lx.\n", hTempHandle, hVertexShader);
2266 /* Verify that we can retrieve the declaration */
2267 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, NULL, &data_size);
2268 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2269 ok(data_size == vertex_decl_size, "Got data_size %lu, expected %lu.\n", data_size, vertex_decl_size);
2270 data = malloc(vertex_decl_size);
2271 data_size = 1;
2272 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, data, &data_size);
2273 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2274 ok(data_size == 1, "Got data_size %lu.\n", data_size);
2275 data_size = vertex_decl_size;
2276 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, data, &data_size);
2277 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2278 ok(data_size == vertex_decl_size, "Got data_size %lu, expected %lu.\n", data_size, vertex_decl_size);
2279 ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
2280 free(data);
2281 /* Verify that we can retrieve the shader function */
2282 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, NULL, &data_size);
2283 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2284 ok(data_size == simple_vs_size, "Got data_size %lu, expected %lu.\n", data_size, simple_vs_size);
2285 data = malloc(simple_vs_size);
2286 data_size = 1;
2287 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, data, &data_size);
2288 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2289 ok(data_size == 1, "Got data_size %lu.\n", data_size);
2290 data_size = simple_vs_size;
2291 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, data, &data_size);
2292 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2293 ok(data_size == simple_vs_size, "Got data_size %lu, expected %lu.\n", data_size, simple_vs_size);
2294 ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
2295 free(data);
2296 /* Delete the assigned shader. This is supposed to work */
2297 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2298 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2299 /* The shader should be unset now */
2300 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2301 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2302 ok(!hTempHandle, "Got vertex shader %#lx.\n", hTempHandle);
2304 /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
2305 * First try the fixed function shader function, then a custom one
2307 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float2, 0, &hVertexShader, 0);
2308 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2309 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float4, 0, &hVertexShader, 0);
2310 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2311 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_d3dcolor, 0, &hVertexShader, 0);
2312 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2314 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float2, simple_vs, &hVertexShader, 0);
2315 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2316 IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2318 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
2320 /* The same with a pixel shader */
2321 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader);
2322 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2323 /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
2324 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2325 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2326 ok(!hTempHandle, "Got pixel shader %#lx.\n", hTempHandle);
2327 /* Assign the shader, then verify that GetPixelShader works */
2328 hr = IDirect3DDevice8_SetPixelShader(device, hPixelShader);
2329 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2330 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2331 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2332 ok(hTempHandle == hPixelShader, "Got pixel shader %#lx, expected %#lx.\n", hTempHandle, hPixelShader);
2333 /* Verify that we can retrieve the shader function */
2334 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, NULL, &data_size);
2335 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2336 ok(data_size == simple_ps_size, "Got data_size %lu, expected %lu.\n", data_size, simple_ps_size);
2337 data = malloc(simple_ps_size);
2338 data_size = 1;
2339 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, data, &data_size);
2340 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2341 ok(data_size == 1, "Got data_size %lu.\n", data_size);
2342 data_size = simple_ps_size;
2343 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, data, &data_size);
2344 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2345 ok(data_size == simple_ps_size, "Got data_size %lu, expected %lu.\n", data_size, simple_ps_size);
2346 ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
2347 free(data);
2348 /* Delete the assigned shader. This is supposed to work */
2349 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2350 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2351 /* The shader should be unset now */
2352 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2353 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2354 ok(!hTempHandle, "Got pixel shader %#lx.\n", hTempHandle);
2356 /* What happens if a non-bound shader is deleted? */
2357 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader);
2358 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2359 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader2);
2360 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2362 hr = IDirect3DDevice8_SetPixelShader(device, hPixelShader);
2363 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2364 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader2);
2365 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2366 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2367 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2368 ok(hTempHandle == hPixelShader, "Got pixel shader %#lx, expected %#lx.\n", hTempHandle, hPixelShader);
2369 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2370 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2372 /* Check for double delete. */
2373 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader2);
2374 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "Got hr %#lx.\n", hr);
2375 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2376 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "Got hr %#lx.\n", hr);
2378 else
2380 skip("Pixel shaders not supported\n");
2383 /* What happens if a non-bound shader is deleted? */
2384 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, NULL, &hVertexShader, 0);
2385 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2386 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, NULL, &hVertexShader2, 0);
2387 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2389 hr = IDirect3DDevice8_SetVertexShader(device, hVertexShader);
2390 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2391 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader2);
2392 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2393 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2394 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2395 ok(hTempHandle == hVertexShader, "Got vertex shader %#lx, expected %#lx.\n", hTempHandle, hVertexShader);
2396 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2397 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2399 /* Check for double delete. */
2400 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader2);
2401 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2402 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2403 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
2405 refcount = IDirect3DDevice8_Release(device);
2406 ok(!refcount, "Device has %lu references left.\n", refcount);
2407 cleanup:
2408 IDirect3D8_Release(d3d);
2409 DestroyWindow(window);
2412 static void test_limits(void)
2414 IDirect3DTexture8 *texture;
2415 IDirect3DDevice8 *device;
2416 IDirect3D8 *d3d;
2417 unsigned int i;
2418 ULONG refcount;
2419 HWND window;
2420 HRESULT hr;
2422 window = create_window();
2423 ok(!!window, "Failed to create a window.\n");
2424 d3d = Direct3DCreate8(D3D_SDK_VERSION);
2425 ok(!!d3d, "Failed to create a D3D object.\n");
2426 if (!(device = create_device(d3d, window, NULL)))
2428 skip("Failed to create a 3D device, skipping test.\n");
2429 goto cleanup;
2432 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture);
2433 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2435 /* There are 8 texture stages. We should be able to access all of them */
2436 for (i = 0; i < 8; ++i)
2438 hr = IDirect3DDevice8_SetTexture(device, i, (IDirect3DBaseTexture8 *)texture);
2439 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2440 hr = IDirect3DDevice8_SetTexture(device, i, NULL);
2441 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2442 hr = IDirect3DDevice8_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2443 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2446 /* Investigations show that accessing higher textures stage states does
2447 * not return an error either. Writing to too high texture stages
2448 * (approximately texture 40) causes memory corruption in windows, so
2449 * there is no bounds checking. */
2450 IDirect3DTexture8_Release(texture);
2451 refcount = IDirect3DDevice8_Release(device);
2452 ok(!refcount, "Device has %lu references left.\n", refcount);
2453 cleanup:
2454 IDirect3D8_Release(d3d);
2455 DestroyWindow(window);
2458 static void test_lights(void)
2460 IDirect3DDevice8 *device;
2461 IDirect3D8 *d3d8;
2462 ULONG refcount;
2463 HWND window;
2464 HRESULT hr;
2465 unsigned int i;
2466 BOOL enabled;
2467 D3DCAPS8 caps;
2469 window = create_window();
2470 ok(!!window, "Failed to create a window.\n");
2471 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2472 ok(!!d3d8, "Failed to create a D3D object.\n");
2473 if (!(device = create_device(d3d8, window, NULL)))
2475 skip("Failed to create a 3D device, skipping test.\n");
2476 goto cleanup;
2479 memset(&caps, 0, sizeof(caps));
2480 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
2481 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2483 for(i = 1; i <= caps.MaxActiveLights; i++) {
2484 hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
2485 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2486 hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
2487 ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "Got hr %#lx.\n", hr);
2488 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2491 /* TODO: Test the rendering results in this situation */
2492 hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
2493 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2494 hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
2495 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2496 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2497 hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
2498 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2500 for(i = 1; i <= caps.MaxActiveLights; i++) {
2501 hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
2502 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2505 refcount = IDirect3DDevice8_Release(device);
2506 ok(!refcount, "Device has %lu references left.\n", refcount);
2507 cleanup:
2508 IDirect3D8_Release(d3d8);
2509 DestroyWindow(window);
2512 static void test_set_stream_source(void)
2514 IDirect3DVertexBuffer8 *vb, *current_vb;
2515 IDirect3DDevice8 *device;
2516 unsigned int stride;
2517 IDirect3D8 *d3d8;
2518 ULONG refcount;
2519 HWND window;
2520 HRESULT hr;
2522 window = create_window();
2523 ok(!!window, "Failed to create a window.\n");
2524 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2525 ok(!!d3d8, "Failed to create a D3D object.\n");
2526 if (!(device = create_device(d3d8, window, NULL)))
2528 skip("Failed to create a 3D device, skipping test.\n");
2529 goto cleanup;
2532 hr = IDirect3DDevice8_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb);
2533 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2535 hr = IDirect3DDevice8_SetStreamSource(device, 0, vb, 32);
2536 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2538 hr = IDirect3DDevice8_SetStreamSource(device, 0, NULL, 0);
2539 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2540 hr = IDirect3DDevice8_GetStreamSource(device, 0, &current_vb, &stride);
2541 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2542 ok(!current_vb, "Got unexpected vb %p.\n", current_vb);
2543 ok(stride == 32, "Got unexpected stride %u.\n", stride);
2545 hr = IDirect3DDevice8_SetStreamSource(device, 0, vb, 0);
2546 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2547 hr = IDirect3DDevice8_GetStreamSource(device, 0, &current_vb, &stride);
2548 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
2549 ok(current_vb == vb, "Got unexpected vb %p.\n", current_vb);
2550 IDirect3DVertexBuffer8_Release(current_vb);
2551 ok(!stride, "Got unexpected stride %u.\n", stride);
2553 IDirect3DVertexBuffer8_Release(vb);
2554 refcount = IDirect3DDevice8_Release(device);
2555 ok(!refcount, "Device has %lu references left.\n", refcount);
2556 cleanup:
2557 IDirect3D8_Release(d3d8);
2558 DestroyWindow(window);
2561 static void test_render_zero_triangles(void)
2563 IDirect3DDevice8 *device;
2564 IDirect3D8 *d3d8;
2565 ULONG refcount;
2566 HWND window;
2567 HRESULT hr;
2569 static const struct
2571 struct vec3 position;
2572 struct vec3 normal;
2573 DWORD diffuse;
2575 quad[] =
2577 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2578 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2579 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2580 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2583 window = create_window();
2584 ok(!!window, "Failed to create a window.\n");
2585 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2586 ok(!!d3d8, "Failed to create a D3D object.\n");
2587 if (!(device = create_device(d3d8, window, NULL)))
2589 skip("Failed to create a 3D device, skipping test.\n");
2590 goto cleanup;
2593 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2594 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2596 hr = IDirect3DDevice8_BeginScene(device);
2597 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
2598 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
2599 0 /* PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
2600 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
2601 hr = IDirect3DDevice8_EndScene(device);
2602 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
2604 IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2606 refcount = IDirect3DDevice8_Release(device);
2607 ok(!refcount, "Device has %lu references left.\n", refcount);
2608 cleanup:
2609 IDirect3D8_Release(d3d8);
2610 DestroyWindow(window);
2613 static void test_depth_stencil_reset(void)
2615 D3DPRESENT_PARAMETERS present_parameters;
2616 D3DDISPLAYMODE display_mode;
2617 IDirect3DSurface8 *surface, *orig_rt;
2618 IDirect3DDevice8 *device = NULL;
2619 IDirect3D8 *d3d8;
2620 UINT refcount;
2621 HRESULT hr;
2622 HWND hwnd;
2624 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2625 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2626 ok(!!hwnd, "Failed to create a window.\n");
2627 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2628 ok(!!d3d8, "Failed to create a D3D object.\n");
2630 IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
2631 memset(&present_parameters, 0, sizeof(present_parameters));
2632 present_parameters.Windowed = TRUE;
2633 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2634 present_parameters.BackBufferFormat = display_mode.Format;
2635 present_parameters.EnableAutoDepthStencil = TRUE;
2636 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2638 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2639 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
2640 if(FAILED(hr))
2642 skip("Failed to create device, hr %#lx.\n", hr);
2643 goto cleanup;
2646 hr = IDirect3DDevice8_GetRenderTarget(device, &orig_rt);
2647 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2649 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2650 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
2652 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2653 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2655 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
2656 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2657 ok(surface == orig_rt, "Render target is %p, should be %p\n", surface, orig_rt);
2658 if (surface) IDirect3DSurface8_Release(surface);
2659 IDirect3DSurface8_Release(orig_rt);
2661 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2662 ok(hr == D3DERR_NOTFOUND, "Got hr %#lx.\n", hr);
2663 ok(surface == NULL, "Depth stencil should be NULL\n");
2665 present_parameters.EnableAutoDepthStencil = TRUE;
2666 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2667 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2668 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2670 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2671 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2672 ok(surface != NULL, "Depth stencil should not be NULL\n");
2673 if (surface) IDirect3DSurface8_Release(surface);
2675 present_parameters.EnableAutoDepthStencil = FALSE;
2676 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2677 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2679 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2680 ok(hr == D3DERR_NOTFOUND, "Got hr %#lx.\n", hr);
2681 ok(surface == NULL, "Depth stencil should be NULL\n");
2683 refcount = IDirect3DDevice8_Release(device);
2684 ok(!refcount, "Device has %u references left.\n", refcount);
2685 device = NULL;
2687 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
2689 ZeroMemory( &present_parameters, sizeof(present_parameters) );
2690 present_parameters.Windowed = TRUE;
2691 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2692 present_parameters.BackBufferFormat = display_mode.Format;
2693 present_parameters.EnableAutoDepthStencil = FALSE;
2694 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2696 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2697 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2699 if(FAILED(hr))
2701 skip("Failed to create device, hr %#lx.\n", hr);
2702 goto cleanup;
2705 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2706 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2708 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2709 present_parameters.Windowed = TRUE;
2710 present_parameters.BackBufferWidth = 400;
2711 present_parameters.BackBufferHeight = 300;
2712 present_parameters.EnableAutoDepthStencil = TRUE;
2713 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2715 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2716 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2718 if (FAILED(hr)) goto cleanup;
2720 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2721 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
2722 ok(surface != NULL, "Depth stencil should not be NULL\n");
2723 if (surface) IDirect3DSurface8_Release(surface);
2725 cleanup:
2726 if (device)
2728 refcount = IDirect3DDevice8_Release(device);
2729 ok(!refcount, "Device has %u references left.\n", refcount);
2731 IDirect3D8_Release(d3d8);
2732 DestroyWindow(hwnd);
2735 static HWND filter_messages;
2737 enum message_window
2739 DEVICE_WINDOW,
2740 FOCUS_WINDOW,
2743 struct message
2745 UINT message;
2746 enum message_window window;
2747 BOOL check_wparam;
2748 WPARAM expect_wparam;
2749 HRESULT device_state;
2750 WINDOWPOS *store_wp;
2753 static const struct message *expect_messages;
2754 static HWND device_window, focus_window;
2755 static LONG windowposchanged_received, syscommand_received;
2756 static IDirect3DDevice8 *focus_test_device;
2758 struct wndproc_thread_param
2760 HWND dummy_window;
2761 HANDLE window_created;
2762 HANDLE test_finished;
2763 BOOL running_in_foreground;
2766 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2768 HRESULT hr;
2770 if (filter_messages && filter_messages == hwnd)
2772 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2773 todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2776 if (expect_messages)
2778 HWND w;
2780 switch (expect_messages->window)
2782 case DEVICE_WINDOW:
2783 w = device_window;
2784 break;
2786 case FOCUS_WINDOW:
2787 w = focus_window;
2788 break;
2790 default:
2791 w = NULL;
2792 break;
2795 if (hwnd == w && expect_messages->message == message)
2797 if (expect_messages->check_wparam)
2798 ok(wparam == expect_messages->expect_wparam,
2799 "Got unexpected wparam %#Ix for message %#x, expected %#Ix.\n",
2800 wparam, message, expect_messages->expect_wparam);
2802 if (expect_messages->store_wp)
2803 *expect_messages->store_wp = *(WINDOWPOS *)lparam;
2805 if (focus_test_device)
2807 hr = IDirect3DDevice8_TestCooperativeLevel(focus_test_device);
2808 /* Wined3d marks the device lost earlier than Windows (it follows ddraw
2809 * behavior. See test_wndproc before the focus_loss_messages sequence
2810 * about the D3DERR_DEVICENOTRESET behavior, */
2811 todo_wine_if(message != WM_ACTIVATEAPP || hr == D3D_OK)
2812 ok(hr == expect_messages->device_state,
2813 "Got device state %#lx on message %#x, expected %#lx.\n",
2814 hr, message, expect_messages->device_state);
2817 ++expect_messages;
2821 /* KDE randomly does something with the hidden window during the
2822 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
2823 * message. A WM_WINDOWPOSCHANGED message is not generated, so
2824 * just flag WM_WINDOWPOSCHANGED as bad. */
2825 if (message == WM_WINDOWPOSCHANGED)
2826 InterlockedIncrement(&windowposchanged_received);
2827 else if (message == WM_SYSCOMMAND)
2828 InterlockedIncrement(&syscommand_received);
2830 return DefWindowProcA(hwnd, message, wparam, lparam);
2833 static DWORD WINAPI wndproc_thread(void *param)
2835 struct wndproc_thread_param *p = param;
2836 DWORD res;
2837 BOOL ret;
2839 p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2840 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
2841 registry_mode.dmPelsHeight, 0, 0, 0, 0);
2842 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2844 ret = SetEvent(p->window_created);
2845 ok(ret, "SetEvent failed, last error %#lx.\n", GetLastError());
2847 for (;;)
2849 MSG msg;
2851 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2852 res = WaitForSingleObject(p->test_finished, 100);
2853 if (res == WAIT_OBJECT_0) break;
2854 if (res != WAIT_TIMEOUT)
2856 ok(0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
2857 break;
2861 DestroyWindow(p->dummy_window);
2863 return 0;
2866 static void test_wndproc(void)
2868 unsigned int adapter_mode_count, i, d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
2869 struct wndproc_thread_param thread_params;
2870 struct device_desc device_desc;
2871 static WINDOWPOS windowpos;
2872 IDirect3DDevice8 *device;
2873 WNDCLASSA wc = {0};
2874 IDirect3D8 *d3d8;
2875 HANDLE thread;
2876 LONG_PTR proc;
2877 ULONG ref;
2878 DWORD res, tid;
2879 HWND tmp;
2880 HRESULT hr;
2881 D3DDISPLAYMODE d3ddm;
2882 DEVMODEW devmode;
2883 LONG change_ret, device_style;
2884 BOOL ret;
2886 static const struct message create_messages[] =
2888 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2889 /* Do not test wparam here. If device creation succeeds,
2890 * wparam is WA_ACTIVE. If device creation fails (testbot)
2891 * wparam is set to WA_INACTIVE on some Windows versions. */
2892 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
2893 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
2894 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2895 {WM_MOVE, DEVICE_WINDOW, FALSE, 0},
2896 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
2897 {0, 0, FALSE, 0},
2899 static const struct message focus_loss_messages[] =
2901 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
2902 * not reliable on X11 WMs. When the window focus follows the
2903 * mouse pointer the message is not sent.
2904 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
2905 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
2906 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2907 * not deterministic. */
2908 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
2909 /* Windows sends WM_ACTIVATE to the device window, indicating that
2910 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
2911 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
2912 * leaves the device window active, breaking re-activation in the
2913 * lost device test.
2914 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
2915 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
2916 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED,
2917 D3DERR_DEVICENOTRESET},
2918 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, D3DERR_DEVICELOST},
2919 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
2920 * not deterministic. It may be sent after the focus window handling
2921 * or before. */
2922 {0, 0, FALSE, 0, 0},
2924 static const struct message reactivate_messages[] =
2926 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2927 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2928 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
2929 {0, 0, FALSE, 0},
2931 static const struct message focus_loss_messages_hidden[] =
2933 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2934 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2935 {0, 0, FALSE, 0},
2937 static const struct message focus_loss_messages_filtered[] =
2939 /* WM_ACTIVATE is delivered to the window proc because it is
2940 * generated by SetForegroundWindow before the d3d routine
2941 * starts it work. Don't check for it due to focus-follows-mouse
2942 * WMs though. */
2943 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
2944 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2945 {0, 0, FALSE, 0},
2947 static const struct message reactivate_messages_filtered[] =
2949 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
2950 {0, 0, FALSE, 0},
2952 static const struct message sc_restore_messages[] =
2954 /* WM_SYSCOMMAND is delivered only once, after d3d has already
2955 * processed it. Our wndproc has no way to prevent d3d from
2956 * handling the message. The second DefWindowProc call done by
2957 * our wndproc doesn't do any changes to the window because it
2958 * is already restored due to d3d's handling. */
2959 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2960 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2961 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
2962 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
2963 {0, 0, FALSE, 0},
2965 static const struct message sc_minimize_messages[] =
2967 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
2968 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2969 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2970 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2971 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
2972 {0, 0, FALSE, 0},
2974 static const struct message sc_maximize_messages[] =
2976 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
2977 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2978 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2979 /* Windows always sends WM_MOVE here.
2981 * In the first case, we are maximizing from a minimized state, and
2982 * hence the client rect moves from the minimized position to (0, 0).
2984 * In the second case, we are maximizing from an on-screen restored
2985 * state. The window is at (0, 0), but it has a caption, so the client
2986 * rect is offset, and the *client* will move to (0, 0) when maximized.
2988 * Wine doesn't send WM_MOVE here because it messes with the window
2989 * styles when switching to fullscreen, and hence the client rect is
2990 * already at (0, 0). Obviously Wine shouldn't do this, but it's hard to
2991 * fix, and the WM_MOVE is not particularly interesting, so just ignore
2992 * it. */
2993 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MAXIMIZED},
2994 {0, 0, FALSE, 0},
2996 static const struct message mode_change_messages[] =
2998 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2999 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3000 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3001 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3002 * differs between Wine and Windows. */
3003 /* TODO 2: Windows sends a second WM_WINDOWPOSCHANGING(SWP_NOMOVE | SWP_NOSIZE
3004 * | SWP_NOACTIVATE) in this situation, suggesting a difference in their ShowWindow
3005 * implementation. This SetWindowPos call could in theory affect the Z order. Wine's
3006 * ShowWindow does not send such a message because the window is already visible. */
3007 {0, 0, FALSE, 0},
3009 static const struct message mode_change_messages_hidden[] =
3011 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3012 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3013 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3014 {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0},
3015 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, ~0U, &windowpos},
3016 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3017 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3018 * differs between Wine and Windows. */
3019 {0, 0, FALSE, 0},
3022 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3023 ok(!!d3d8, "Failed to create a D3D object.\n");
3025 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
3026 for (i = 0; i < adapter_mode_count; ++i)
3028 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm);
3029 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
3031 if (d3ddm.Format != D3DFMT_X8R8G8B8)
3032 continue;
3033 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3034 continue;
3035 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3036 * refuses to create a device at these sizes. */
3037 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3038 continue;
3040 if (!user32_width)
3042 user32_width = d3ddm.Width;
3043 user32_height = d3ddm.Height;
3044 continue;
3047 /* Make sure the d3d mode is smaller in width or height and at most
3048 * equal in the other dimension than the mode passed to
3049 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3050 * the ChangeDisplaySettings parameters + 12. */
3051 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3052 continue;
3053 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3055 d3d_width = d3ddm.Width;
3056 d3d_height = d3ddm.Height;
3057 break;
3059 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3061 d3d_width = user32_width;
3062 d3d_height = user32_height;
3063 user32_width = d3ddm.Width;
3064 user32_height = d3ddm.Height;
3065 break;
3069 if (!d3d_width)
3071 skip("Could not find adequate modes, skipping mode tests.\n");
3072 IDirect3D8_Release(d3d8);
3073 return;
3076 filter_messages = NULL;
3077 expect_messages = NULL;
3079 wc.lpfnWndProc = test_proc;
3080 wc.lpszClassName = "d3d8_test_wndproc_wc";
3081 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3083 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3084 ok(!!thread_params.window_created, "CreateEvent failed, last error %#lx.\n", GetLastError());
3085 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3086 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#lx.\n", GetLastError());
3088 memset(&devmode, 0, sizeof(devmode));
3089 devmode.dmSize = sizeof(devmode);
3090 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3091 devmode.dmPelsWidth = user32_width;
3092 devmode.dmPelsHeight = user32_height;
3093 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3094 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3096 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3097 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3098 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3099 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3100 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3101 ok(!!thread, "Failed to create thread, last error %#lx.\n", GetLastError());
3103 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3104 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
3106 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3107 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3108 (LONG_PTR)test_proc, proc);
3109 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3110 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3111 (LONG_PTR)test_proc, proc);
3113 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3114 device_window, focus_window, thread_params.dummy_window);
3116 tmp = GetFocus();
3117 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3118 if (thread_params.running_in_foreground)
3120 tmp = GetForegroundWindow();
3121 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3122 thread_params.dummy_window, tmp);
3124 else
3125 skip("Not running in foreground, skip foreground window test\n");
3127 flush_events();
3129 expect_messages = create_messages;
3131 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
3132 device_desc.device_window = device_window;
3133 device_desc.width = d3d_width;
3134 device_desc.height = d3d_height;
3135 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3136 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3138 skip("Failed to create a D3D device, skipping tests.\n");
3139 goto done;
3142 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3143 expect_messages->message, expect_messages->window);
3144 expect_messages = NULL;
3146 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3148 tmp = GetFocus();
3149 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3150 tmp = GetForegroundWindow();
3151 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3153 SetForegroundWindow(focus_window);
3154 flush_events();
3156 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3157 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3158 (LONG_PTR)test_proc, proc);
3160 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3161 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3163 /* Change the mode while the device is in use and then drop focus. */
3164 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3165 devmode.dmPelsWidth = user32_width;
3166 devmode.dmPelsHeight = user32_height;
3167 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3168 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx, i=%u.\n", change_ret, i);
3170 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3171 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3172 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3173 hr = IDirect3DDevice8_TestCooperativeLevel(device);
3174 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3175 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#lx.\n", hr);
3177 expect_messages = focus_loss_messages;
3178 focus_test_device = device;
3179 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3180 * manually changing the focus. It generates the same messages, but the task
3181 * bar still shows the previous foreground window as active, and the window has
3182 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3183 * the device is difficult, see below. */
3184 SetForegroundWindow(GetDesktopWindow());
3185 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3186 expect_messages->message, expect_messages->window);
3187 expect_messages = NULL;
3188 tmp = GetFocus();
3189 ok(tmp != device_window, "The device window is active.\n");
3190 ok(tmp != focus_window, "The focus window is active.\n");
3191 focus_test_device = NULL;
3193 /* The Present call is necessary to make native realize the device is lost. */
3194 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
3195 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#lx.\n", hr);
3196 hr = IDirect3DDevice8_TestCooperativeLevel(device);
3197 /* Focus-follows-mouse WMs prematurely reactivate our window. */
3198 todo_wine_if (hr == D3DERR_DEVICENOTRESET)
3199 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#lx.\n", hr);
3201 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3202 ok(ret, "Failed to get display mode.\n");
3203 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3204 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %lux%lu.\n",
3205 devmode.dmPelsWidth, devmode.dmPelsHeight);
3207 /* I have to minimize and restore the focus window, otherwise native d3d8 fails
3208 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3209 * restore is triggered by the user.
3211 * fvwm randomly sends a focus loss notification when we minimize, so do it
3212 * before checking the incoming messages. It might match WM_ACTIVATEAPP but has
3213 * a wrong WPARAM. Use SW_SHOWMINNOACTIVE to make sure we don't accidentally
3214 * activate the window at this point and miss our WM_ACTIVATEAPP(wparam=1). */
3215 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3216 flush_events();
3217 expect_messages = reactivate_messages;
3218 ShowWindow(focus_window, SW_RESTORE);
3219 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3220 SetForegroundWindow(focus_window);
3221 flush_events();
3222 SetForegroundWindow(focus_window);
3223 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3224 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3225 expect_messages->message, expect_messages->window, i);
3226 expect_messages = NULL;
3228 hr = IDirect3DDevice8_TestCooperativeLevel(device);
3229 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#lx.\n", hr);
3231 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3232 ok(ret, "Failed to get display mode.\n");
3233 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3234 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected screen size %lux%lu.\n",
3235 devmode.dmPelsWidth, devmode.dmPelsHeight);
3237 hr = reset_device(device, &device_desc);
3238 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3240 /* Remove the WS_VISIBLE flag to test hidden windows. This is enough to trigger d3d's hidden
3241 * window codepath, but does not actually hide the window without a SetWindowPos(SWP_FRAMECHANGED)
3242 * call. This way we avoid focus changes and random failures on focus follows mouse WMs. */
3243 device_style = GetWindowLongA(device_window, GWL_STYLE);
3244 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3245 flush_events();
3247 expect_messages = focus_loss_messages_hidden;
3248 windowposchanged_received = 0;
3249 SetForegroundWindow(GetDesktopWindow());
3250 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3251 expect_messages->message, expect_messages->window);
3253 /* kwin sometimes resizes hidden windows. The d3d8 version of this test has been reliable on
3254 * Windows so far, but the d3d9 equivalent rarely fails since Windows 8. */
3255 flaky
3256 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3258 expect_messages = NULL;
3259 flush_events();
3261 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3262 ok(ret, "Failed to get display mode.\n");
3263 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpected width %lu.\n", devmode.dmPelsWidth);
3264 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpected height %lu.\n", devmode.dmPelsHeight);
3266 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3267 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3268 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3269 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3270 flush_events();
3272 syscommand_received = 0;
3273 expect_messages = sc_restore_messages;
3274 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3275 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3276 expect_messages->message, expect_messages->window);
3277 ok(syscommand_received == 1, "Got %lu WM_SYSCOMMAND messages.\n", syscommand_received);
3278 expect_messages = NULL;
3279 flush_events();
3281 expect_messages = sc_minimize_messages;
3282 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3283 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3284 expect_messages->message, expect_messages->window);
3285 expect_messages = NULL;
3286 flush_events();
3288 expect_messages = sc_maximize_messages;
3289 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3290 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3291 expect_messages->message, expect_messages->window);
3292 expect_messages = NULL;
3293 flush_events();
3295 SetForegroundWindow(GetDesktopWindow());
3296 ShowWindow(device_window, SW_MINIMIZE);
3297 ShowWindow(focus_window, SW_MINIMIZE);
3298 ShowWindow(focus_window, SW_RESTORE);
3299 SetForegroundWindow(focus_window);
3300 flush_events();
3302 /* Releasing a device in lost state breaks follow-up tests on native. */
3303 hr = reset_device(device, &device_desc);
3304 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3306 filter_messages = focus_window;
3307 ref = IDirect3DDevice8_Release(device);
3308 ok(!ref, "Got unexpected refcount %lu.\n", ref);
3310 /* Fix up the mode until Wine's device release behavior is fixed. */
3311 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3312 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
3314 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3315 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3316 (LONG_PTR)test_proc, proc);
3318 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3319 * on native in the test below. It isn't needed anyways. Creating the third
3320 * device will show it again. */
3321 filter_messages = NULL;
3322 ShowWindow(device_window, SW_HIDE);
3323 /* Remove the maximized state from the SYSCOMMAND test while we're not
3324 * interfering with a device. */
3325 ShowWindow(focus_window, SW_SHOWNORMAL);
3327 /* On Windows 10 style change messages are delivered on device
3328 * creation. */
3329 device_desc.device_window = focus_window;
3330 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3332 skip("Failed to create a D3D device, skipping tests.\n");
3333 goto done;
3335 SetForegroundWindow(focus_window); /* make sure that the window has focus */
3337 filter_messages = NULL;
3339 expect_messages = focus_loss_messages_filtered;
3340 windowposchanged_received = 0;
3341 SetForegroundWindow(GetDesktopWindow());
3342 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3343 expect_messages->message, expect_messages->window);
3344 expect_messages = NULL;
3346 /* The window is iconic even though no message was sent. */
3347 ok(IsIconic(focus_window), "The focus window is not iconic.\n");
3349 hr = IDirect3DDevice8_TestCooperativeLevel(device);
3350 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#lx.\n", hr);
3352 syscommand_received = 0;
3353 expect_messages = sc_restore_messages;
3354 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3355 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3356 expect_messages->message, expect_messages->window);
3357 ok(syscommand_received == 1, "Got %lu WM_SYSCOMMAND messages.\n", syscommand_received);
3358 expect_messages = NULL;
3359 flush_events();
3361 /* For FVWM. */
3362 ShowWindow(focus_window, SW_RESTORE);
3363 flush_events();
3365 expect_messages = sc_minimize_messages;
3366 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3367 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3368 expect_messages->message, expect_messages->window);
3369 expect_messages = NULL;
3370 /* Needed to make the next test reliably send WM_SIZE(SIZE_MAXIMIZED). Without
3371 * this call it sends WM_SIZE(SIZE_RESTORED). */
3372 ShowWindow(focus_window, SW_RESTORE);
3373 flush_events();
3375 expect_messages = sc_maximize_messages;
3376 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3377 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3378 expect_messages->message, expect_messages->window);
3379 expect_messages = NULL;
3380 flush_events();
3381 SetForegroundWindow(GetDesktopWindow());
3382 flush_events();
3384 /* ShowWindow(SW_RESTORE); SetForegroundWindow(desktop); SetForegroundWindow(focus);
3385 * results in the second SetForegroundWindow call failing and the device not being
3386 * restored on native. Directly using ShowWindow(SW_RESTORE) works, but it means
3387 * we cannot test for the absence of WM_WINDOWPOSCHANGED messages. */
3388 expect_messages = reactivate_messages_filtered;
3389 ShowWindow(focus_window, SW_RESTORE);
3390 SetForegroundWindow(focus_window);
3391 flush_events();
3392 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it\n",
3393 expect_messages->message, expect_messages->window);
3394 expect_messages = NULL;
3396 filter_messages = focus_window;
3397 hr = IDirect3DDevice8_TestCooperativeLevel(device);
3398 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#lx.\n", hr);
3400 filter_messages = NULL;
3401 hr = reset_device(device, &device_desc);
3402 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3404 ref = IDirect3DDevice8_Release(device);
3405 ok(!ref, "Got unexpected refcount %lu.\n", ref);
3406 filter_messages = NULL;
3408 ShowWindow(device_window, SW_RESTORE);
3409 SetForegroundWindow(focus_window);
3410 flush_events();
3412 filter_messages = focus_window;
3413 device_desc.device_window = device_window;
3414 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3416 skip("Failed to create a D3D device, skipping tests.\n");
3417 goto done;
3419 filter_messages = NULL;
3420 flush_events();
3422 device_desc.width = user32_width;
3423 device_desc.height = user32_height;
3425 expect_messages = mode_change_messages;
3426 filter_messages = focus_window;
3427 hr = reset_device(device, &device_desc);
3428 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3429 filter_messages = NULL;
3431 flush_events();
3432 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3433 expect_messages->message, expect_messages->window, i);
3434 expect_messages = NULL;
3436 /* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
3437 device_style = GetWindowLongA(device_window, GWL_STYLE);
3438 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3440 flush_events();
3441 device_desc.width = d3d_width;
3442 device_desc.height = d3d_height;
3443 memset(&windowpos, 0, sizeof(windowpos));
3445 expect_messages = mode_change_messages_hidden;
3446 filter_messages = focus_window;
3447 hr = reset_device(device, &device_desc);
3448 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3449 filter_messages = NULL;
3451 flush_events();
3452 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
3453 expect_messages->message, expect_messages->window);
3454 expect_messages = NULL;
3456 ok(windowpos.hwnd == device_window && !windowpos.hwndInsertAfter
3457 && !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
3458 && windowpos.flags == (SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE),
3459 "Got unexpected WINDOWPOS hwnd=%p, insertAfter=%p, x=%d, y=%d, cx=%d, cy=%d, flags=%x\n",
3460 windowpos.hwnd, windowpos.hwndInsertAfter, windowpos.x, windowpos.y, windowpos.cx,
3461 windowpos.cy, windowpos.flags);
3463 device_style = GetWindowLongA(device_window, GWL_STYLE);
3464 ok(device_style & WS_VISIBLE, "Expected the device window to be visible.\n");
3466 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3467 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3469 ref = IDirect3DDevice8_Release(device);
3470 ok(!ref, "Got unexpected refcount %lu.\n", ref);
3472 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3473 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#Ix, got %#Ix.\n",
3474 (LONG_PTR)DefWindowProcA, proc);
3476 done:
3477 filter_messages = NULL;
3478 expect_messages = NULL;
3479 IDirect3D8_Release(d3d8);
3481 SetEvent(thread_params.test_finished);
3482 WaitForSingleObject(thread, INFINITE);
3483 CloseHandle(thread_params.test_finished);
3484 CloseHandle(thread_params.window_created);
3485 CloseHandle(thread);
3487 DestroyWindow(device_window);
3488 DestroyWindow(focus_window);
3489 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3490 change_ret = ChangeDisplaySettingsExW(NULL, NULL, NULL, 0, NULL);
3491 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
3494 static void test_wndproc_windowed(void)
3496 struct wndproc_thread_param thread_params;
3497 struct device_desc device_desc;
3498 IDirect3DDevice8 *device;
3499 WNDCLASSA wc = {0};
3500 IDirect3D8 *d3d8;
3501 HANDLE thread;
3502 LONG_PTR proc;
3503 HRESULT hr;
3504 ULONG ref;
3505 DWORD res, tid;
3506 HWND tmp;
3508 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3509 ok(!!d3d8, "Failed to create a D3D object.\n");
3511 filter_messages = NULL;
3512 expect_messages = NULL;
3514 wc.lpfnWndProc = test_proc;
3515 wc.lpszClassName = "d3d8_test_wndproc_wc";
3516 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3518 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3519 ok(!!thread_params.window_created, "CreateEvent failed, last error %#lx.\n", GetLastError());
3520 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3521 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#lx.\n", GetLastError());
3523 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3524 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3525 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3526 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3527 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3528 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3529 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3530 ok(!!thread, "Failed to create thread, last error %#lx.\n", GetLastError());
3532 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3533 ok(res == WAIT_OBJECT_0, "Wait failed (%#lx), last error %#lx.\n", res, GetLastError());
3535 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3536 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3537 (LONG_PTR)test_proc, proc);
3538 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3539 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3540 (LONG_PTR)test_proc, proc);
3542 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3543 device_window, focus_window, thread_params.dummy_window);
3545 tmp = GetFocus();
3546 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3547 if (thread_params.running_in_foreground)
3549 tmp = GetForegroundWindow();
3550 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3551 thread_params.dummy_window, tmp);
3553 else
3554 skip("Not running in foreground, skip foreground window test\n");
3556 filter_messages = focus_window;
3558 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
3559 device_desc.device_window = device_window;
3560 device_desc.width = registry_mode.dmPelsWidth;
3561 device_desc.height = registry_mode.dmPelsHeight;
3562 device_desc.flags = 0;
3563 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3565 skip("Failed to create a D3D device, skipping tests.\n");
3566 goto done;
3569 tmp = GetFocus();
3570 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3571 tmp = GetForegroundWindow();
3572 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3573 thread_params.dummy_window, tmp);
3575 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3576 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3577 (LONG_PTR)test_proc, proc);
3579 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3580 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3581 (LONG_PTR)test_proc, proc);
3583 filter_messages = NULL;
3585 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3586 hr = reset_device(device, &device_desc);
3587 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3589 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3590 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3591 (LONG_PTR)test_proc, proc);
3593 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3594 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3596 device_desc.flags = 0;
3597 hr = reset_device(device, &device_desc);
3598 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3600 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3601 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3602 (LONG_PTR)test_proc, proc);
3604 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3605 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3606 (LONG_PTR)test_proc, proc);
3608 filter_messages = focus_window;
3610 ref = IDirect3DDevice8_Release(device);
3611 ok(!ref, "Got unexpected refcount %lu.\n", ref);
3613 filter_messages = device_window;
3615 device_desc.device_window = focus_window;
3616 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3618 skip("Failed to create a D3D device, skipping tests.\n");
3619 goto done;
3622 filter_messages = NULL;
3624 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3625 hr = reset_device(device, &device_desc);
3626 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3628 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3629 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3630 (LONG_PTR)test_proc, proc);
3632 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3633 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3635 device_desc.flags = 0;
3636 hr = reset_device(device, &device_desc);
3637 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3639 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3640 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3641 (LONG_PTR)test_proc, proc);
3643 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3644 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3645 (LONG_PTR)test_proc, proc);
3647 filter_messages = device_window;
3649 ref = IDirect3DDevice8_Release(device);
3650 ok(!ref, "Got unexpected refcount %lu.\n", ref);
3652 device_desc.device_window = device_window;
3653 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3655 skip("Failed to create a D3D device, skipping tests.\n");
3656 goto done;
3659 filter_messages = NULL;
3661 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3662 hr = reset_device(device, &device_desc);
3663 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3665 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3666 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3667 (LONG_PTR)test_proc, proc);
3669 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3670 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
3672 device_desc.flags = 0;
3673 hr = reset_device(device, &device_desc);
3674 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
3676 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3677 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3678 (LONG_PTR)test_proc, proc);
3680 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3681 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
3682 (LONG_PTR)test_proc, proc);
3684 filter_messages = device_window;
3686 ref = IDirect3DDevice8_Release(device);
3687 ok(!ref, "Got unexpected refcount %lu.\n", ref);
3689 done:
3690 filter_messages = NULL;
3691 IDirect3D8_Release(d3d8);
3693 SetEvent(thread_params.test_finished);
3694 WaitForSingleObject(thread, INFINITE);
3695 CloseHandle(thread_params.test_finished);
3696 CloseHandle(thread_params.window_created);
3697 CloseHandle(thread);
3699 DestroyWindow(device_window);
3700 DestroyWindow(focus_window);
3701 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3704 static const GUID d3d8_private_data_test_guid =
3706 0xfdb37466,
3707 0x428f,
3708 0x4edf,
3709 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
3712 #if defined(__i386__) || (defined(__x86_64__) && !defined(__arm64ec__) && (defined(__GNUC__) || defined(__clang__)))
3714 static inline void set_fpu_cw(WORD cw)
3716 #if defined(_MSC_VER) && defined(__i386__)
3717 __asm fnclex;
3718 __asm fldcw cw;
3719 #else
3720 __asm__ volatile ("fnclex");
3721 __asm__ volatile ("fldcw %0" : : "m" (cw));
3722 #endif
3725 static inline WORD get_fpu_cw(void)
3727 WORD cw = 0;
3728 #if defined(_MSC_VER) && defined(__i386__)
3729 __asm fnstcw cw;
3730 #else
3731 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3732 #endif
3733 return cw;
3736 static WORD callback_cw, callback_set_cw;
3737 static DWORD callback_tid;
3739 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
3741 *out = NULL;
3742 return E_NOINTERFACE;
3745 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
3747 callback_cw = get_fpu_cw();
3748 set_fpu_cw(callback_set_cw);
3749 callback_tid = GetCurrentThreadId();
3750 return 2;
3753 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
3755 callback_cw = get_fpu_cw();
3756 set_fpu_cw(callback_set_cw);
3757 callback_tid = GetCurrentThreadId();
3758 return 1;
3761 static const IUnknownVtbl dummy_object_vtbl =
3763 dummy_object_QueryInterface,
3764 dummy_object_AddRef,
3765 dummy_object_Release,
3768 static void test_fpu_setup(void)
3770 struct device_desc device_desc;
3771 IDirect3DDevice8 *device;
3772 IDirect3D8 *d3d8;
3773 HWND window;
3774 HRESULT hr;
3775 WORD cw;
3776 IDirect3DSurface8 *surface;
3777 IUnknown dummy_object = {&dummy_object_vtbl};
3779 window = create_window();
3780 ok(!!window, "Failed to create a window.\n");
3781 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3782 ok(!!d3d8, "Failed to create a D3D object.\n");
3784 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
3785 device_desc.device_window = window;
3786 device_desc.width = 640;
3787 device_desc.height = 480;
3788 device_desc.flags = 0;
3790 set_fpu_cw(0xf60);
3791 cw = get_fpu_cw();
3792 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3794 if (!(device = create_device(d3d8, window, &device_desc)))
3796 skip("Failed to create a 3D device, skipping test.\n");
3797 set_fpu_cw(0x37f);
3798 goto done;
3801 cw = get_fpu_cw();
3802 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3804 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3805 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#lx.\n", hr);
3807 callback_set_cw = 0xf60;
3808 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3809 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3810 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
3811 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
3812 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3813 cw = get_fpu_cw();
3814 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3816 callback_cw = 0;
3817 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3818 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3819 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
3820 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
3821 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3823 callback_set_cw = 0x7f;
3824 set_fpu_cw(0x7f);
3826 IDirect3DSurface8_Release(surface);
3828 callback_cw = 0;
3829 IDirect3DDevice8_Release(device);
3830 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
3831 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3833 cw = get_fpu_cw();
3834 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3835 set_fpu_cw(0xf60);
3836 cw = get_fpu_cw();
3837 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3839 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
3840 device = create_device(d3d8, window, &device_desc);
3841 ok(!!device, "CreateDevice failed.\n");
3843 cw = get_fpu_cw();
3844 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3846 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3847 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#lx.\n", hr);
3849 callback_cw = 0;
3850 callback_set_cw = 0x37f;
3851 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3852 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3853 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
3854 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
3855 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3856 cw = get_fpu_cw();
3857 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
3859 IDirect3DSurface8_Release(surface);
3861 callback_cw = 0;
3862 IDirect3DDevice8_Release(device);
3863 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0x37f.\n", callback_cw);
3864 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3866 done:
3867 DestroyWindow(window);
3868 IDirect3D8_Release(d3d8);
3871 #else
3873 static void test_fpu_setup(void)
3877 #endif
3879 static void test_ApplyStateBlock(void)
3881 IDirect3DDevice8 *device;
3882 IDirect3D8 *d3d8;
3883 HWND window;
3884 HRESULT hr;
3885 DWORD received, token;
3887 window = create_window();
3888 ok(!!window, "Failed to create a window.\n");
3889 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3890 ok(!!d3d8, "Failed to create a D3D object.\n");
3891 if (!(device = create_device(d3d8, window, NULL)))
3893 skip("Failed to create a 3D device, skipping test.\n");
3894 goto cleanup;
3897 IDirect3DDevice8_BeginStateBlock(device);
3898 IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
3899 IDirect3DDevice8_EndStateBlock(device, &token);
3900 ok(token, "Received zero stateblock handle.\n");
3901 IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
3903 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3904 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
3905 ok(!received, "Expected = FALSE, received TRUE.\n");
3907 hr = IDirect3DDevice8_ApplyStateBlock(device, 0);
3908 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
3909 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3910 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
3911 ok(!received, "Expected FALSE, received TRUE.\n");
3913 hr = IDirect3DDevice8_ApplyStateBlock(device, token);
3914 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
3915 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3916 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
3917 ok(received, "Expected TRUE, received FALSE.\n");
3919 IDirect3DDevice8_DeleteStateBlock(device, token);
3920 IDirect3DDevice8_Release(device);
3921 cleanup:
3922 IDirect3D8_Release(d3d8);
3923 DestroyWindow(window);
3926 static void test_depth_stencil_size(void)
3928 IDirect3DDevice8 *device;
3929 IDirect3DSurface8 *ds, *rt, *ds_bigger, *ds_bigger2;
3930 IDirect3DSurface8 *surf;
3931 IDirect3D8 *d3d8;
3932 HRESULT hr;
3933 HWND hwnd;
3935 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3936 100, 100, 160, 160, NULL, NULL, NULL, NULL);
3937 ok(!!hwnd, "Failed to create a window.\n");
3938 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3939 ok(!!d3d8, "Failed to create a D3D object.\n");
3941 if (!(device = create_device(d3d8, hwnd, NULL)))
3943 skip("Failed to create a 3D device, skipping test.\n");
3944 goto cleanup;
3947 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
3948 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateRenderTarget failed, hr %#lx.\n", hr);
3949 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds);
3950 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#lx.\n", hr);
3951 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger);
3952 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#lx.\n", hr);
3953 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger2);
3954 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#lx.\n", hr);
3956 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
3957 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
3958 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds_bigger);
3959 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#lx.\n", hr);
3961 /* try to set the small ds without changing the render target at the same time */
3962 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds);
3963 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
3964 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds_bigger2);
3965 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#lx.\n", hr);
3967 hr = IDirect3DDevice8_GetRenderTarget(device, &surf);
3968 ok(hr == D3D_OK, "IDirect3DDevice8_GetRenderTarget failed, hr %#lx.\n", hr);
3969 ok(surf == rt, "The render target is %p, expected %p\n", surf, rt);
3970 IDirect3DSurface8_Release(surf);
3971 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
3972 ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr %#lx.\n", hr);
3973 ok(surf == ds_bigger2, "The depth stencil is %p, expected %p\n", surf, ds_bigger2);
3974 IDirect3DSurface8_Release(surf);
3976 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
3977 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#lx.\n", hr);
3978 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
3979 ok(FAILED(hr), "IDirect3DDevice8_GetDepthStencilSurface should have failed, hr %#lx.\n", hr);
3980 ok(surf == NULL, "The depth stencil is %p, expected NULL\n", surf);
3981 if (surf) IDirect3DSurface8_Release(surf);
3983 IDirect3DSurface8_Release(rt);
3984 IDirect3DSurface8_Release(ds);
3985 IDirect3DSurface8_Release(ds_bigger);
3986 IDirect3DSurface8_Release(ds_bigger2);
3988 cleanup:
3989 IDirect3D8_Release(d3d8);
3990 DestroyWindow(hwnd);
3993 static void test_window_style(void)
3995 RECT focus_rect, fullscreen_rect, r;
3996 LONG device_style, device_exstyle;
3997 LONG focus_style, focus_exstyle;
3998 struct device_desc device_desc;
3999 LONG style, expected_style;
4000 IDirect3DDevice8 *device;
4001 IDirect3D8 *d3d8;
4002 HRESULT hr;
4003 ULONG ref;
4004 BOOL ret;
4006 focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4007 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4008 device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4009 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4010 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4011 ok(!!d3d8, "Failed to create a D3D object.\n");
4013 device_style = GetWindowLongA(device_window, GWL_STYLE);
4014 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4015 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4016 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4018 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4019 GetWindowRect(focus_window, &focus_rect);
4021 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4022 device_desc.device_window = device_window;
4023 device_desc.width = registry_mode.dmPelsWidth;
4024 device_desc.height = registry_mode.dmPelsHeight;
4025 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4026 if (!(device = create_device(d3d8, focus_window, &device_desc)))
4028 skip("Failed to create a D3D device, skipping tests.\n");
4029 goto done;
4032 style = GetWindowLongA(device_window, GWL_STYLE);
4033 expected_style = device_style | WS_VISIBLE;
4034 todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_OVERLAPPEDWINDOW)) /* w1064v1809 */,
4035 "Expected device window style %#lx, got %#lx.\n",
4036 expected_style, style);
4037 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4038 expected_style = device_exstyle | WS_EX_TOPMOST;
4039 todo_wine ok(style == expected_style || broken(style == (expected_style & ~WS_EX_OVERLAPPEDWINDOW)) /* w1064v1809 */,
4040 "Expected device window extended style %#lx, got %#lx.\n",
4041 expected_style, style);
4043 style = GetWindowLongA(focus_window, GWL_STYLE);
4044 ok(style == focus_style, "Expected focus window style %#lx, got %#lx.\n",
4045 focus_style, style);
4046 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4047 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx.\n",
4048 focus_exstyle, style);
4050 GetWindowRect(device_window, &r);
4051 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4052 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4053 GetClientRect(device_window, &r);
4054 todo_wine ok(!EqualRect(&r, &fullscreen_rect) || broken(!(style & WS_THICKFRAME)) /* w1064v1809 */,
4055 "Client rect and window rect are equal.\n");
4056 GetWindowRect(focus_window, &r);
4057 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&focus_rect),
4058 wine_dbgstr_rect(&r));
4060 device_desc.flags = 0;
4061 hr = reset_device(device, &device_desc);
4062 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
4064 style = GetWindowLongA(device_window, GWL_STYLE);
4065 expected_style = device_style | WS_VISIBLE;
4066 ok(style == expected_style, "Expected device window style %#lx, got %#lx.\n",
4067 expected_style, style);
4068 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4069 expected_style = device_exstyle | WS_EX_TOPMOST;
4070 ok(style == expected_style, "Expected device window extended style %#lx, got %#lx.\n",
4071 expected_style, style);
4073 style = GetWindowLongA(focus_window, GWL_STYLE);
4074 ok(style == focus_style, "Expected focus window style %#lx, got %#lx.\n",
4075 focus_style, style);
4076 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4077 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx.\n",
4078 focus_exstyle, style);
4080 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4081 hr = reset_device(device, &device_desc);
4082 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
4083 ret = SetForegroundWindow(GetDesktopWindow());
4084 ok(ret, "Failed to set foreground window.\n");
4086 style = GetWindowLongA(device_window, GWL_STYLE);
4087 expected_style = device_style | WS_MINIMIZE | WS_VISIBLE;
4088 todo_wine ok(style == expected_style, "Expected device window style %#lx, got %#lx.\n",
4089 expected_style, style);
4090 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4091 expected_style = device_exstyle | WS_EX_TOPMOST;
4092 todo_wine ok(style == expected_style, "Expected device window extended style %#lx, got %#lx.\n",
4093 expected_style, style);
4095 style = GetWindowLongA(focus_window, GWL_STYLE);
4096 ok(style == focus_style, "Expected focus window style %#lx, got %#lx.\n",
4097 focus_style, style);
4098 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4099 ok(style == focus_exstyle, "Expected focus window extended style %#lx, got %#lx.\n",
4100 focus_exstyle, style);
4102 /* Follow-up tests fail on native if the device is destroyed while lost. */
4103 ShowWindow(focus_window, SW_MINIMIZE);
4104 ShowWindow(focus_window, SW_RESTORE);
4105 ret = SetForegroundWindow(focus_window);
4106 ok(ret, "Failed to set foreground window.\n");
4107 flush_events();
4108 hr = reset_device(device, &device_desc);
4109 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
4111 ref = IDirect3DDevice8_Release(device);
4112 ok(!ref, "Got unexpected refcount %lu.\n", ref);
4114 done:
4115 IDirect3D8_Release(d3d8);
4117 DestroyWindow(device_window);
4118 DestroyWindow(focus_window);
4121 static void test_unsupported_shaders(void)
4123 IDirect3DDevice8 *device;
4124 IDirect3D8 *d3d;
4125 ULONG refcount;
4126 DWORD vs, ps;
4127 HWND window;
4128 HRESULT hr;
4129 D3DCAPS8 caps;
4131 static const DWORD vs_2_0[] =
4133 0xfffe0200, /* vs_2_0 */
4134 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
4135 0x02000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
4136 0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002, /* add oD0, r1, c2 */
4137 0x02000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
4138 0x0000ffff /* end */
4140 static const DWORD ps_2_0[] =
4142 0xffff0200, /* ps_2_0 */
4143 0x02000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
4144 0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002, /* add r0, r1, c2 */
4145 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */
4146 0x0000ffff /* end */
4148 #if 0
4149 vs_1_1
4150 dcl_position v0
4151 def c255, 1.0, 1.0, 1.0, 1.0
4152 add r0, v0, c255
4153 mov oPos, r0
4154 #endif
4155 static const DWORD vs_1_255[] =
4157 0xfffe0101,
4158 0x0000001f, 0x80000000, 0x900f0000,
4159 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
4160 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
4161 0x00000001, 0xc00f0000, 0x80e40000,
4162 0x0000ffff
4164 #if 0
4165 vs_1_1
4166 dcl_position v0
4167 def c256, 1.0, 1.0, 1.0, 1.0
4168 add r0, v0, c256
4169 mov oPos, r0
4170 #endif
4171 static const DWORD vs_1_256[] =
4173 0xfffe0101,
4174 0x0000001f, 0x80000000, 0x900f0000,
4175 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
4176 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
4177 0x00000001, 0xc00f0000, 0x80e40000,
4178 0x0000ffff
4181 static const DWORD decl[] =
4183 D3DVSD_STREAM(0),
4184 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
4185 D3DVSD_END()
4188 window = create_window();
4189 ok(!!window, "Failed to create a window.\n");
4190 d3d = Direct3DCreate8(D3D_SDK_VERSION);
4191 ok(!!d3d, "Failed to create a D3D object.\n");
4192 if (!(device = create_device(d3d, window, NULL)))
4194 skip("Failed to create a D3D device, skipping tests.\n");
4195 IDirect3D8_Release(d3d);
4196 DestroyWindow(window);
4197 return;
4200 hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_ps, &vs, 0);
4201 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4203 hr = IDirect3DDevice8_CreatePixelShader(device, simple_vs, &ps);
4204 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4206 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_2_0, &vs, 0);
4207 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4209 hr = IDirect3DDevice8_CreatePixelShader(device, ps_2_0, &ps);
4210 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4212 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4213 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
4214 if (caps.MaxVertexShaderConst < 256)
4216 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_255, &vs, 0);
4217 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
4219 else
4221 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_255, &vs, 0);
4222 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
4223 hr = IDirect3DDevice8_DeleteVertexShader(device, vs);
4224 ok(hr == D3D_OK, "Got hr %#lx.\n", hr);
4225 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_256, &vs, 0);
4226 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
4229 refcount = IDirect3DDevice8_Release(device);
4230 ok(!refcount, "Device has %lu references left.\n", refcount);
4231 IDirect3D8_Release(d3d);
4232 DestroyWindow(window);
4235 static void test_mode_change(void)
4237 unsigned int display_count = 0, d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4238 DEVMODEW old_devmode, devmode, devmode2, *original_modes = NULL;
4239 struct device_desc device_desc, device_desc2;
4240 WCHAR second_monitor_name[CCHDEVICENAME];
4241 IDirect3DDevice8 *device, *device2;
4242 RECT d3d_rect, focus_rect, r;
4243 IDirect3DSurface8 *backbuffer;
4244 MONITORINFOEXW monitor_info;
4245 HMONITOR second_monitor;
4246 D3DSURFACE_DESC desc;
4247 IDirect3D8 *d3d8;
4248 ULONG refcount;
4249 UINT adapter_mode_count, i;
4250 HRESULT hr;
4251 BOOL ret;
4252 LONG change_ret;
4253 D3DDISPLAYMODE d3ddm;
4255 memset(&devmode, 0, sizeof(devmode));
4256 devmode.dmSize = sizeof(devmode);
4257 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4258 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4259 ok(equal_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
4260 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode);
4261 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4262 ok(equal_mode_rect(&devmode, &registry_mode), "Got a different mode.\n");
4264 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4265 ok(!!d3d8, "Failed to create a D3D object.\n");
4267 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
4268 for (i = 0; i < adapter_mode_count; ++i)
4270 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm);
4271 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#lx.\n", hr);
4273 if (d3ddm.Format != D3DFMT_X8R8G8B8)
4274 continue;
4275 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4276 continue;
4277 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4278 * refuses to create a device at these sizes. */
4279 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4280 continue;
4282 if (!user32_width)
4284 user32_width = d3ddm.Width;
4285 user32_height = d3ddm.Height;
4286 continue;
4289 /* Make sure the d3d mode is smaller in width or height and at most
4290 * equal in the other dimension than the mode passed to
4291 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4292 * the ChangeDisplaySettings parameters + 12. */
4293 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4294 continue;
4295 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4297 d3d_width = d3ddm.Width;
4298 d3d_height = d3ddm.Height;
4299 break;
4301 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4303 d3d_width = user32_width;
4304 d3d_height = user32_height;
4305 user32_width = d3ddm.Width;
4306 user32_height = d3ddm.Height;
4307 break;
4311 if (!d3d_width)
4313 skip("Could not find adequate modes, skipping mode tests.\n");
4314 IDirect3D8_Release(d3d8);
4315 return;
4318 ret = save_display_modes(&original_modes, &display_count);
4319 ok(ret, "Failed to save original display modes.\n");
4321 memset(&devmode, 0, sizeof(devmode));
4322 devmode.dmSize = sizeof(devmode);
4323 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4324 devmode.dmPelsWidth = user32_width;
4325 devmode.dmPelsHeight = user32_height;
4326 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4327 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
4329 /* Make the windows visible, otherwise device::release does not restore the mode if
4330 * the application is not in foreground like on the testbot. */
4331 focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4332 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4333 device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
4334 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4336 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4337 GetWindowRect(focus_window, &focus_rect);
4339 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4340 device_desc.device_window = device_window;
4341 device_desc.width = d3d_width;
4342 device_desc.height = d3d_height;
4343 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4344 if (!(device = create_device(d3d8, focus_window, &device_desc)))
4346 skip("Failed to create a D3D device, skipping tests.\n");
4347 goto done;
4350 devmode.dmPelsWidth = user32_width;
4351 devmode.dmPelsHeight = user32_height;
4352 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4353 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
4355 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4356 ok(ret, "Failed to get display mode.\n");
4357 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4358 "Expected resolution %ux%u, got %lux%lu.\n",
4359 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4361 GetWindowRect(device_window, &r);
4362 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&d3d_rect),
4363 wine_dbgstr_rect(&r));
4364 GetWindowRect(focus_window, &r);
4365 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&focus_rect),
4366 wine_dbgstr_rect(&r));
4368 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4369 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#lx.\n", hr);
4370 hr = IDirect3DSurface8_GetDesc(backbuffer, &desc);
4371 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#lx.\n", hr);
4372 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4373 desc.Width, d3d_width);
4374 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4375 desc.Height, d3d_height);
4376 IDirect3DSurface8_Release(backbuffer);
4378 refcount = IDirect3DDevice8_Release(device);
4379 ok(!refcount, "Device has %lu references left.\n", refcount);
4381 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4382 ok(ret, "Failed to get display mode.\n");
4383 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4384 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4385 "Expected resolution %lux%lu, got %lux%lu.\n",
4386 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4388 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4389 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
4391 /* The mode restore also happens when the device was created at the original screen size. */
4393 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4394 device_desc.device_window = device_window;
4395 device_desc.width = registry_mode.dmPelsWidth;
4396 device_desc.height = registry_mode.dmPelsHeight;
4397 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4398 ok(!!(device = create_device(d3d8, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4400 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4401 devmode.dmPelsWidth = user32_width;
4402 devmode.dmPelsHeight = user32_height;
4403 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4404 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#lx.\n", change_ret);
4406 refcount = IDirect3DDevice8_Release(device);
4407 ok(!refcount, "Device has %lu references left.\n", refcount);
4409 memset(&devmode2, 0, sizeof(devmode2));
4410 devmode2.dmSize = sizeof(devmode2);
4411 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4412 ok(ret, "Failed to get display mode.\n");
4413 ok(devmode2.dmPelsWidth == registry_mode.dmPelsWidth
4414 && devmode2.dmPelsHeight == registry_mode.dmPelsHeight,
4415 "Expected resolution %lux%lu, got %lux%lu.\n", registry_mode.dmPelsWidth,
4416 registry_mode.dmPelsHeight, devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4417 ret = restore_display_modes(original_modes, display_count);
4418 ok(ret, "Failed to restore display modes.\n");
4420 /* Test that no mode restorations if no mode changes happened */
4421 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
4422 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
4424 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4425 device_desc.device_window = device_window;
4426 device_desc.width = d3d_width;
4427 device_desc.height = d3d_height;
4428 device_desc.flags = 0;
4429 device = create_device(d3d8, device_window, &device_desc);
4430 ok(!!device, "Failed to create a D3D device.\n");
4431 refcount = IDirect3DDevice8_Release(device);
4432 ok(!refcount, "Device has %lu references left.\n", refcount);
4434 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4435 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4436 ok(equal_mode_rect(&devmode2, &registry_mode), "Got a different mode.\n");
4437 ret = restore_display_modes(original_modes, display_count);
4438 ok(ret, "Failed to restore display modes.\n");
4440 /* Test that mode restorations use display settings in the registry with a fullscreen device */
4441 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
4442 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
4444 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4445 device_desc.device_window = device_window;
4446 device_desc.width = registry_mode.dmPelsWidth;
4447 device_desc.height = registry_mode.dmPelsHeight;
4448 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4449 device = create_device(d3d8, device_window, &device_desc);
4450 ok(!!device, "Failed to create a D3D device.\n");
4451 refcount = IDirect3DDevice8_Release(device);
4452 ok(!refcount, "Device has %lu references left.\n", refcount);
4454 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4455 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4456 ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4457 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
4458 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4459 ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4460 ret = restore_display_modes(original_modes, display_count);
4461 ok(ret, "Failed to restore display modes.\n");
4463 /* Test that mode restorations use display settings in the registry with a fullscreen device
4464 * having the same display mode and then reset to a different mode */
4465 change_ret = ChangeDisplaySettingsW(&devmode, CDS_UPDATEREGISTRY | CDS_NORESET);
4466 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsW failed with %ld.\n", change_ret);
4468 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4469 device_desc.device_window = device_window;
4470 device_desc.width = registry_mode.dmPelsWidth;
4471 device_desc.height = registry_mode.dmPelsHeight;
4472 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4473 device = create_device(d3d8, device_window, &device_desc);
4474 ok(!!device, "Failed to create a D3D device.\n");
4476 device_desc.width = d3d_width;
4477 device_desc.height = d3d_height;
4478 hr = reset_device(device, &device_desc);
4479 ok(hr == D3D_OK, "Failed to reset device, hr %#lx.\n", hr);
4480 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4481 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4482 ok(devmode2.dmPelsWidth == d3d_width && devmode2.dmPelsHeight == d3d_height,
4483 "Expected resolution %ux%u, got %lux%lu.\n", d3d_width, d3d_height,
4484 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4486 refcount = IDirect3DDevice8_Release(device);
4487 ok(!refcount, "Device has %lu references left.\n", refcount);
4489 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode2);
4490 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4491 ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4492 ret = EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &devmode2);
4493 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4494 ok(equal_mode_rect(&devmode2, &devmode), "Got a different mode.\n");
4495 ret = restore_display_modes(original_modes, display_count);
4496 ok(ret, "Failed to restore display modes.\n");
4498 if (IDirect3D8_GetAdapterCount(d3d8) < 2)
4500 skip("Following tests require two adapters.\n");
4501 goto done;
4504 second_monitor = IDirect3D8_GetAdapterMonitor(d3d8, 1);
4505 monitor_info.cbSize = sizeof(monitor_info);
4506 ret = GetMonitorInfoW(second_monitor, (MONITORINFO *)&monitor_info);
4507 ok(ret, "GetMonitorInfoW failed, error %#lx.\n", GetLastError());
4508 lstrcpyW(second_monitor_name, monitor_info.szDevice);
4510 memset(&old_devmode, 0, sizeof(old_devmode));
4511 old_devmode.dmSize = sizeof(old_devmode);
4512 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &old_devmode);
4513 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4515 i = 0;
4516 d3d_width = 0;
4517 d3d_height = 0;
4518 user32_width = 0;
4519 user32_height = 0;
4520 while (EnumDisplaySettingsW(second_monitor_name, i++, &devmode))
4522 if (devmode.dmPelsWidth == old_devmode.dmPelsWidth
4523 && devmode.dmPelsHeight == old_devmode.dmPelsHeight)
4524 continue;
4526 if (!d3d_width && !d3d_height)
4528 d3d_width = devmode.dmPelsWidth;
4529 d3d_height = devmode.dmPelsHeight;
4530 continue;
4533 if (devmode.dmPelsWidth == d3d_width && devmode.dmPelsHeight == d3d_height)
4534 continue;
4536 user32_width = devmode.dmPelsWidth;
4537 user32_height = devmode.dmPelsHeight;
4538 break;
4540 if (!user32_width || !user32_height)
4542 skip("Failed to find three different display modes for the second monitor.\n");
4543 goto done;
4546 /* Test that mode restorations also happen for non-primary monitors on device resets */
4547 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4548 device_desc.device_window = device_window;
4549 device_desc.width = registry_mode.dmPelsWidth;
4550 device_desc.height = registry_mode.dmPelsHeight;
4551 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4552 device = create_device(d3d8, device_window, &device_desc);
4553 ok(!!device, "Failed to create a D3D device.\n");
4555 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4556 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4557 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4558 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4559 if (devmode2.dmPelsWidth == old_devmode.dmPelsWidth
4560 && devmode2.dmPelsHeight == old_devmode.dmPelsHeight)
4562 skip("Failed to change display settings of the second monitor.\n");
4563 refcount = IDirect3DDevice8_Release(device);
4564 ok(!refcount, "Device has %lu references left.\n", refcount);
4565 goto done;
4568 device_desc.flags = 0;
4569 hr = reset_device(device, &device_desc);
4570 ok(hr == D3D_OK, "Failed to reset device, hr %#lx.\n", hr);
4572 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4573 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4574 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4575 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4576 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4577 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4578 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
4579 ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
4580 ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %lu, got %u.\n",
4581 old_devmode.dmPelsWidth, d3ddm.Width);
4582 ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %lu, got %u.\n",
4583 old_devmode.dmPelsHeight, d3ddm.Height);
4585 refcount = IDirect3DDevice8_Release(device);
4586 ok(!refcount, "Device has %lu references left.\n", refcount);
4587 ret = restore_display_modes(original_modes, display_count);
4588 ok(ret, "Failed to restore display modes.\n");
4590 /* Test that mode restorations happen for non-primary monitors on device releases */
4591 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4592 device_desc.device_window = device_window;
4593 device_desc.width = registry_mode.dmPelsWidth;
4594 device_desc.height = registry_mode.dmPelsHeight;
4595 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4596 device = create_device(d3d8, device_window, &device_desc);
4597 ok(!!device, "Failed to create a D3D device.\n");
4599 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4600 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4602 refcount = IDirect3DDevice8_Release(device);
4603 ok(!refcount, "Device has %lu references left.\n", refcount);
4605 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4606 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4607 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4608 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4609 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4610 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4611 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
4612 ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
4613 ok(d3ddm.Width == old_devmode.dmPelsWidth, "Expected width %lu, got %u.\n",
4614 old_devmode.dmPelsWidth, d3ddm.Width);
4615 ok(d3ddm.Height == old_devmode.dmPelsHeight, "Expected height %lu, got %u.\n",
4616 old_devmode.dmPelsHeight, d3ddm.Height);
4617 ret = restore_display_modes(original_modes, display_count);
4618 ok(ret, "Failed to restore display modes.\n");
4620 /* Test that mode restorations for non-primary monitors use display settings in the registry */
4621 device = create_device(d3d8, device_window, &device_desc);
4622 ok(!!device, "Failed to create a D3D device.\n");
4624 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL,
4625 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
4626 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4628 refcount = IDirect3DDevice8_Release(device);
4629 ok(!refcount, "Device has %lu references left.\n", refcount);
4631 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4632 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4633 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4634 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4635 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4636 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4637 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4638 ok(devmode2.dmPelsWidth == devmode.dmPelsWidth && devmode2.dmPelsHeight == devmode.dmPelsHeight,
4639 "Expected resolution %lux%lu, got %lux%lu.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4640 devmode2.dmPelsWidth, devmode2.dmPelsHeight);
4641 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
4642 ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
4643 ok(d3ddm.Width == devmode.dmPelsWidth && d3ddm.Height == devmode.dmPelsHeight,
4644 "Expected resolution %lux%lu, got %ux%u.\n", devmode.dmPelsWidth, devmode.dmPelsHeight,
4645 d3ddm.Width, d3ddm.Height);
4646 ret = restore_display_modes(original_modes, display_count);
4647 ok(ret, "Failed to restore display modes.\n");
4649 /* Test mode restorations when there are two fullscreen devices and one of them got reset */
4650 device = create_device(d3d8, focus_window, &device_desc);
4651 ok(!!device, "Failed to create a D3D device.\n");
4653 device_desc2.adapter_ordinal = 1;
4654 device_desc2.device_window = device_window;
4655 device_desc2.width = d3d_width;
4656 device_desc2.height = d3d_height;
4657 device_desc2.flags = CREATE_DEVICE_FULLSCREEN;
4658 device2 = create_device(d3d8, focus_window, &device_desc2);
4659 ok(!!device2, "Failed to create a D3D device.\n");
4661 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4662 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4664 device_desc.flags = 0;
4665 hr = reset_device(device, &device_desc);
4666 ok(hr == D3D_OK, "Failed to reset device, hr %#lx.\n", hr);
4668 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4669 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4670 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4671 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4672 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4673 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4674 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
4675 ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
4676 ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
4677 "Expected resolution %lux%lu, got %ux%u.\n", old_devmode.dmPelsWidth,
4678 old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
4680 refcount = IDirect3DDevice8_Release(device2);
4681 ok(!refcount, "Device has %lu references left.\n", refcount);
4682 refcount = IDirect3DDevice8_Release(device);
4683 ok(!refcount, "Device has %lu references left.\n", refcount);
4684 ret = restore_display_modes(original_modes, display_count);
4685 ok(ret, "Failed to restore display modes.\n");
4687 /* Test mode restoration when there are two fullscreen devices and one of them got released */
4688 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4689 device = create_device(d3d8, focus_window, &device_desc);
4690 ok(!!device, "Failed to create a D3D device.\n");
4691 device2 = create_device(d3d8, focus_window, &device_desc2);
4692 ok(!!device2, "Failed to create a D3D device.\n");
4694 change_ret = ChangeDisplaySettingsExW(second_monitor_name, &devmode, NULL, CDS_RESET, NULL);
4695 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret);
4697 refcount = IDirect3DDevice8_Release(device);
4698 ok(!refcount, "Device has %lu references left.\n", refcount);
4700 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_CURRENT_SETTINGS, &devmode2);
4701 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4702 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4703 ret = EnumDisplaySettingsW(second_monitor_name, ENUM_REGISTRY_SETTINGS, &devmode2);
4704 ok(ret, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
4705 ok(equal_mode_rect(&devmode2, &old_devmode), "Got a different mode.\n");
4706 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, 1, &d3ddm);
4707 ok(hr == S_OK, "GetAdapterDisplayMode failed, hr %#lx.\n", hr);
4708 ok(d3ddm.Width == old_devmode.dmPelsWidth && d3ddm.Height == old_devmode.dmPelsHeight,
4709 "Expected resolution %lux%lu, got %ux%u.\n", old_devmode.dmPelsWidth,
4710 old_devmode.dmPelsHeight, d3ddm.Width, d3ddm.Height);
4712 refcount = IDirect3DDevice8_Release(device2);
4713 ok(!refcount, "Device has %lu references left.\n", refcount);
4715 done:
4716 DestroyWindow(device_window);
4717 DestroyWindow(focus_window);
4718 IDirect3D8_Release(d3d8);
4719 ret = restore_display_modes(original_modes, display_count);
4720 ok(ret, "Failed to restore display modes.\n");
4721 free(original_modes);
4724 static void test_device_window_reset(void)
4726 RECT fullscreen_rect, device_rect, r;
4727 struct device_desc device_desc;
4728 IDirect3DDevice8 *device;
4729 WNDCLASSA wc = {0};
4730 IDirect3D8 *d3d8;
4731 LONG_PTR proc;
4732 HRESULT hr;
4733 ULONG ref;
4735 filter_messages = NULL;
4736 expect_messages = NULL;
4738 wc.lpfnWndProc = test_proc;
4739 wc.lpszClassName = "d3d8_test_wndproc_wc";
4740 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4742 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4743 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4744 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4745 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4746 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4747 ok(!!d3d8, "Failed to create a D3D object.\n");
4749 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4750 GetWindowRect(device_window, &device_rect);
4752 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4753 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
4754 (LONG_PTR)test_proc, proc);
4755 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4756 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
4757 (LONG_PTR)test_proc, proc);
4759 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
4760 device_desc.device_window = NULL;
4761 device_desc.width = registry_mode.dmPelsWidth;
4762 device_desc.height = registry_mode.dmPelsHeight;
4763 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4764 if (!(device = create_device(d3d8, focus_window, &device_desc)))
4766 skip("Failed to create a D3D device, skipping tests.\n");
4767 goto done;
4770 GetWindowRect(focus_window, &r);
4771 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4772 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4773 GetWindowRect(device_window, &r);
4774 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&device_rect),
4775 wine_dbgstr_rect(&r));
4777 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4778 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
4779 (LONG_PTR)test_proc, proc);
4780 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4781 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
4783 device_desc.device_window = device_window;
4784 hr = reset_device(device, &device_desc);
4785 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4787 GetWindowRect(focus_window, &r);
4788 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4789 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4790 GetWindowRect(device_window, &r);
4791 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
4792 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4794 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4795 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#Ix, got %#Ix.\n",
4796 (LONG_PTR)test_proc, proc);
4797 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4798 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#Ix.\n", (LONG_PTR)test_proc);
4800 ref = IDirect3DDevice8_Release(device);
4801 ok(!ref, "Got unexpected refcount %lu.\n", ref);
4803 done:
4804 IDirect3D8_Release(d3d8);
4805 DestroyWindow(device_window);
4806 DestroyWindow(focus_window);
4807 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
4810 static void depth_blit_test(void)
4812 IDirect3DDevice8 *device = NULL;
4813 IDirect3DSurface8 *backbuffer, *ds1, *ds2, *ds3;
4814 RECT src_rect;
4815 const POINT dst_point = {0, 0};
4816 IDirect3D8 *d3d8;
4817 HRESULT hr;
4818 HWND hwnd;
4820 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4821 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4822 ok(!!hwnd, "Failed to create a window.\n");
4823 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4824 ok(!!d3d8, "Failed to create a D3D object.\n");
4826 if (!(device = create_device(d3d8, hwnd, NULL)))
4828 skip("Failed to create a D3D device, skipping tests.\n");
4829 goto done;
4832 hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
4833 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#lx.\n", hr);
4834 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds1);
4835 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#lx.\n", hr);
4836 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds2);
4837 ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#lx.\n", hr);
4838 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds3);
4839 ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#lx.\n", hr);
4841 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
4842 ok(SUCCEEDED(hr), "Clear failed, hr %#lx.\n", hr);
4844 /* Partial blit. */
4845 SetRect(&src_rect, 0, 0, 320, 240);
4846 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4847 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4848 /* Flipped. */
4849 SetRect(&src_rect, 0, 480, 640, 0);
4850 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4851 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4852 /* Full, explicit. */
4853 SetRect(&src_rect, 0, 0, 640, 480);
4854 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4855 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4856 /* Depth -> color blit.*/
4857 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, backbuffer, &dst_point);
4858 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4859 /* Full, NULL rects, current depth stencil -> unbound depth stencil */
4860 hr = IDirect3DDevice8_CopyRects(device, ds1, NULL, 0, ds2, NULL);
4861 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4862 /* Full, NULL rects, unbound depth stencil -> current depth stencil */
4863 hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds1, NULL);
4864 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4865 /* Full, NULL rects, unbound depth stencil -> unbound depth stencil */
4866 hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds3, NULL);
4867 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
4869 IDirect3DSurface8_Release(backbuffer);
4870 IDirect3DSurface8_Release(ds3);
4871 IDirect3DSurface8_Release(ds2);
4872 IDirect3DSurface8_Release(ds1);
4874 done:
4875 if (device) IDirect3DDevice8_Release(device);
4876 IDirect3D8_Release(d3d8);
4877 DestroyWindow(hwnd);
4880 static void test_reset_resources(void)
4882 IDirect3DSurface8 *surface, *rt;
4883 IDirect3DTexture8 *texture;
4884 IDirect3DDevice8 *device;
4885 IDirect3D8 *d3d8;
4886 HWND window;
4887 HRESULT hr;
4888 ULONG ref;
4890 window = create_window();
4891 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4892 ok(!!d3d8, "Failed to create a D3D object.\n");
4894 if (!(device = create_device(d3d8, window, NULL)))
4896 skip("Failed to create a D3D device, skipping tests.\n");
4897 goto done;
4900 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24S8,
4901 D3DMULTISAMPLE_NONE, &surface);
4902 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#lx.\n", hr);
4904 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
4905 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
4906 ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#lx.\n", hr);
4907 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &rt);
4908 ok(SUCCEEDED(hr), "Failed to get surface, hr %#lx.\n", hr);
4909 IDirect3DTexture8_Release(texture);
4911 hr = IDirect3DDevice8_SetRenderTarget(device, rt, surface);
4912 ok(SUCCEEDED(hr), "Failed to set render target surface, hr %#lx.\n", hr);
4913 IDirect3DSurface8_Release(rt);
4914 IDirect3DSurface8_Release(surface);
4916 hr = reset_device(device, NULL);
4917 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4919 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
4920 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#lx.\n", hr);
4921 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
4922 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#lx.\n", hr);
4923 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
4924 IDirect3DSurface8_Release(surface);
4925 IDirect3DSurface8_Release(rt);
4927 ref = IDirect3DDevice8_Release(device);
4928 ok(!ref, "Got unexpected refcount %lu.\n", ref);
4930 done:
4931 IDirect3D8_Release(d3d8);
4932 DestroyWindow(window);
4935 static void test_set_rt_vp_scissor(void)
4937 IDirect3DDevice8 *device;
4938 IDirect3DSurface8 *rt;
4939 IDirect3D8 *d3d8;
4940 DWORD stateblock;
4941 D3DVIEWPORT8 vp;
4942 UINT refcount;
4943 HWND window;
4944 HRESULT hr;
4946 window = create_window();
4947 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4948 ok(!!d3d8, "Failed to create a D3D object.\n");
4949 if (!(device = create_device(d3d8, window, NULL)))
4951 skip("Failed to create a D3D device, skipping tests.\n");
4952 IDirect3D8_Release(d3d8);
4953 DestroyWindow(window);
4954 return;
4957 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
4958 D3DMULTISAMPLE_NONE, FALSE, &rt);
4959 ok(SUCCEEDED(hr), "Failed to create render target, hr %#lx.\n", hr);
4961 hr = IDirect3DDevice8_GetViewport(device, &vp);
4962 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
4963 ok(!vp.X, "Got unexpected vp.X %lu.\n", vp.X);
4964 ok(!vp.Y, "Got unexpected vp.Y %lu.\n", vp.Y);
4965 ok(vp.Width == 640, "Got unexpected vp.Width %lu.\n", vp.Width);
4966 ok(vp.Height == 480, "Got unexpected vp.Height %lu.\n", vp.Height);
4967 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4968 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4970 hr = IDirect3DDevice8_BeginStateBlock(device);
4971 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#lx.\n", hr);
4973 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4974 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
4976 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
4977 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#lx.\n", hr);
4978 hr = IDirect3DDevice8_DeleteStateBlock(device, stateblock);
4979 ok(SUCCEEDED(hr), "Failed to delete stateblock, hr %#lx.\n", hr);
4981 hr = IDirect3DDevice8_GetViewport(device, &vp);
4982 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
4983 ok(!vp.X, "Got unexpected vp.X %lu.\n", vp.X);
4984 ok(!vp.Y, "Got unexpected vp.Y %lu.\n", vp.Y);
4985 ok(vp.Width == 128, "Got unexpected vp.Width %lu.\n", vp.Width);
4986 ok(vp.Height == 128, "Got unexpected vp.Height %lu.\n", vp.Height);
4987 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4988 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4990 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4991 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
4993 vp.X = 10;
4994 vp.Y = 20;
4995 vp.Width = 30;
4996 vp.Height = 40;
4997 vp.MinZ = 0.25f;
4998 vp.MaxZ = 0.75f;
4999 hr = IDirect3DDevice8_SetViewport(device, &vp);
5000 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#lx.\n", hr);
5002 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
5003 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
5005 hr = IDirect3DDevice8_GetViewport(device, &vp);
5006 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#lx.\n", hr);
5007 ok(!vp.X, "Got unexpected vp.X %lu.\n", vp.X);
5008 ok(!vp.Y, "Got unexpected vp.Y %lu.\n", vp.Y);
5009 ok(vp.Width == 128, "Got unexpected vp.Width %lu.\n", vp.Width);
5010 ok(vp.Height == 128, "Got unexpected vp.Height %lu.\n", vp.Height);
5011 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5012 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5014 IDirect3DSurface8_Release(rt);
5015 refcount = IDirect3DDevice8_Release(device);
5016 ok(!refcount, "Device has %u references left.\n", refcount);
5017 IDirect3D8_Release(d3d8);
5018 DestroyWindow(window);
5021 static void test_validate_vs(void)
5023 static DWORD vs_code[] =
5025 0xfffe0101, /* vs_1_1 */
5026 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
5027 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
5028 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
5029 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
5030 0x0000ffff, /* end */
5032 D3DCAPS8 caps;
5033 char *errors;
5034 HRESULT hr;
5036 static DWORD declaration_valid1[] =
5038 D3DVSD_STREAM(0),
5039 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4),
5040 D3DVSD_END()
5042 static DWORD declaration_valid2[] =
5044 D3DVSD_STREAM(0),
5045 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT2),
5046 D3DVSD_END()
5048 static DWORD declaration_invalid[] =
5050 D3DVSD_STREAM(0),
5051 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT4),
5052 D3DVSD_END()
5055 hr = ValidateVertexShader(NULL, NULL, NULL, FALSE, NULL);
5056 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5057 hr = ValidateVertexShader(NULL, NULL, NULL, TRUE, NULL);
5058 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5059 hr = ValidateVertexShader(NULL, NULL, NULL, FALSE, &errors);
5060 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5061 ok(!*errors, "Got unexpected string \"%s\".\n", errors);
5062 HeapFree(GetProcessHeap(), 0, errors);
5063 hr = ValidateVertexShader(NULL, NULL, NULL, TRUE, &errors);
5064 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5065 ok(!!*errors, "Got unexpected empty string.\n");
5066 HeapFree(GetProcessHeap(), 0, errors);
5068 hr = ValidateVertexShader(vs_code, NULL, NULL, FALSE, NULL);
5069 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5070 hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, NULL);
5071 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5072 hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, &errors);
5073 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5074 ok(!*errors, "Got unexpected string \"%s\".\n", errors);
5075 HeapFree(GetProcessHeap(), 0, errors);
5077 hr = ValidateVertexShader(vs_code, declaration_valid1, NULL, FALSE, NULL);
5078 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5079 hr = ValidateVertexShader(vs_code, declaration_valid2, NULL, FALSE, NULL);
5080 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5081 hr = ValidateVertexShader(vs_code, declaration_invalid, NULL, FALSE, NULL);
5082 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5084 memset(&caps, 0, sizeof(caps));
5085 caps.VertexShaderVersion = D3DVS_VERSION(1, 1);
5086 caps.MaxVertexShaderConst = 4;
5087 hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL);
5088 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5089 caps.VertexShaderVersion = D3DVS_VERSION(1, 0);
5090 hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL);
5091 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5092 caps.VertexShaderVersion = D3DVS_VERSION(1, 2);
5093 hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL);
5094 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5095 caps.VertexShaderVersion = D3DVS_VERSION(8, 8);
5096 hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL);
5097 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5098 caps.VertexShaderVersion = D3DVS_VERSION(1, 1);
5099 caps.MaxVertexShaderConst = 3;
5100 hr = ValidateVertexShader(vs_code, NULL, &caps, FALSE, NULL);
5101 todo_wine ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5103 *vs_code = D3DVS_VERSION(1, 0);
5104 hr = ValidateVertexShader(vs_code, NULL, NULL, FALSE, NULL);
5105 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5106 *vs_code = D3DVS_VERSION(1, 2);
5107 hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, NULL);
5108 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5109 hr = ValidateVertexShader(vs_code, NULL, NULL, FALSE, &errors);
5110 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5111 ok(!*errors, "Got unexpected string \"%s\".\n", errors);
5112 HeapFree(GetProcessHeap(), 0, errors);
5113 hr = ValidateVertexShader(vs_code, NULL, NULL, TRUE, &errors);
5114 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5115 ok(!!*errors, "Got unexpected empty string.\n");
5116 HeapFree(GetProcessHeap(), 0, errors);
5119 static void test_validate_ps(void)
5121 static DWORD ps_1_1_code[] =
5123 0xffff0101, /* ps_1_1 */
5124 0x00000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
5125 0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002, /* add r0, r1, c2 */
5126 0x0000ffff /* end */
5128 static const DWORD ps_2_0_code[] =
5130 0xffff0200, /* ps_2_0 */
5131 0x02000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
5132 0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002, /* add r0, r1, c2 */
5133 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */
5134 0x0000ffff /* end */
5136 D3DCAPS8 caps;
5137 char *errors;
5138 HRESULT hr;
5140 hr = ValidatePixelShader(NULL, NULL, FALSE, NULL);
5141 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5142 hr = ValidatePixelShader(NULL, NULL, TRUE, NULL);
5143 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5144 errors = (void *)0xcafeface;
5145 hr = ValidatePixelShader(NULL, NULL, FALSE, &errors);
5146 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5147 ok(errors == (void *)0xcafeface, "Got unexpected errors %p.\n", errors);
5148 errors = (void *)0xcafeface;
5149 hr = ValidatePixelShader(NULL, NULL, TRUE, &errors);
5150 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5151 ok(errors == (void *)0xcafeface, "Got unexpected errors %p.\n", errors);
5153 hr = ValidatePixelShader(ps_1_1_code, NULL, FALSE, NULL);
5154 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5155 hr = ValidatePixelShader(ps_1_1_code, NULL, TRUE, NULL);
5156 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5157 hr = ValidatePixelShader(ps_1_1_code, NULL, TRUE, &errors);
5158 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5159 ok(!*errors, "Got unexpected string \"%s\".\n", errors);
5160 HeapFree(GetProcessHeap(), 0, errors);
5162 memset(&caps, 0, sizeof(caps));
5163 caps.PixelShaderVersion = D3DPS_VERSION(1, 1);
5164 hr = ValidatePixelShader(ps_1_1_code, &caps, FALSE, NULL);
5165 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5166 caps.PixelShaderVersion = D3DPS_VERSION(1, 0);
5167 hr = ValidatePixelShader(ps_1_1_code, &caps, FALSE, NULL);
5168 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5169 caps.PixelShaderVersion = D3DPS_VERSION(1, 2);
5170 hr = ValidatePixelShader(ps_1_1_code, &caps, FALSE, NULL);
5171 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5172 caps.PixelShaderVersion = D3DPS_VERSION(8, 8);
5173 hr = ValidatePixelShader(ps_1_1_code, &caps, FALSE, NULL);
5174 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5176 *ps_1_1_code = D3DPS_VERSION(1, 0);
5177 hr = ValidatePixelShader(ps_1_1_code, NULL, FALSE, NULL);
5178 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5179 *ps_1_1_code = D3DPS_VERSION(1, 4);
5180 hr = ValidatePixelShader(ps_1_1_code, NULL, FALSE, NULL);
5181 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
5182 hr = ValidatePixelShader(ps_2_0_code, NULL, FALSE, NULL);
5183 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5184 *ps_1_1_code = D3DPS_VERSION(1, 5);
5185 hr = ValidatePixelShader(ps_1_1_code, NULL, TRUE, NULL);
5186 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5187 hr = ValidatePixelShader(ps_1_1_code, NULL, FALSE, &errors);
5188 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5189 ok(!*errors, "Got unexpected string \"%s\".\n", errors);
5190 HeapFree(GetProcessHeap(), 0, errors);
5191 hr = ValidatePixelShader(ps_1_1_code, NULL, TRUE, &errors);
5192 ok(hr == E_FAIL, "Got unexpected hr %#lx.\n", hr);
5193 ok(!!*errors, "Got unexpected empty string.\n");
5194 HeapFree(GetProcessHeap(), 0, errors);
5197 static void test_volume_get_container(void)
5199 IDirect3DVolumeTexture8 *texture = NULL;
5200 IDirect3DVolume8 *volume = NULL;
5201 IDirect3DDevice8 *device;
5202 IUnknown *container;
5203 IDirect3D8 *d3d8;
5204 ULONG refcount;
5205 D3DCAPS8 caps;
5206 HWND window;
5207 HRESULT hr;
5209 window = create_window();
5210 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5211 ok(!!d3d8, "Failed to create a D3D object.\n");
5212 if (!(device = create_device(d3d8, window, NULL)))
5214 skip("Failed to create a D3D device, skipping tests.\n");
5215 IDirect3D8_Release(d3d8);
5216 DestroyWindow(window);
5217 return;
5220 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5221 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
5222 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5224 skip("No volume texture support, skipping tests.\n");
5225 IDirect3DDevice8_Release(device);
5226 IDirect3D8_Release(d3d8);
5227 DestroyWindow(window);
5228 return;
5231 hr = IDirect3DDevice8_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5232 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
5233 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#lx.\n", hr);
5234 ok(!!texture, "Got unexpected texture %p.\n", texture);
5236 hr = IDirect3DVolumeTexture8_GetVolumeLevel(texture, 0, &volume);
5237 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#lx.\n", hr);
5238 ok(!!volume, "Got unexpected volume %p.\n", volume);
5240 /* These should work... */
5241 container = NULL;
5242 hr = IDirect3DVolume8_GetContainer(volume, &IID_IUnknown, (void **)&container);
5243 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#lx.\n", hr);
5244 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5245 IUnknown_Release(container);
5247 container = NULL;
5248 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DResource8, (void **)&container);
5249 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#lx.\n", hr);
5250 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5251 IUnknown_Release(container);
5253 container = NULL;
5254 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DBaseTexture8, (void **)&container);
5255 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#lx.\n", hr);
5256 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5257 IUnknown_Release(container);
5259 container = NULL;
5260 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolumeTexture8, (void **)&container);
5261 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#lx.\n", hr);
5262 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5263 IUnknown_Release(container);
5265 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5266 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolume8, (void **)&container);
5267 ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
5268 ok(!container, "Got unexpected container %p.\n", container);
5270 IDirect3DVolume8_Release(volume);
5271 IDirect3DVolumeTexture8_Release(texture);
5272 refcount = IDirect3DDevice8_Release(device);
5273 ok(!refcount, "Device has %lu references left.\n", refcount);
5274 IDirect3D8_Release(d3d8);
5275 DestroyWindow(window);
5278 static void test_vb_lock_flags(void)
5280 static const struct
5282 DWORD flags;
5283 const char *debug_string;
5284 HRESULT result;
5286 test_data[] =
5288 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5289 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5290 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5291 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5292 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5293 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3D_OK },
5294 /* Completely bogus flags aren't an error. */
5295 {0xdeadbeef, "0xdeadbeef", D3D_OK },
5297 IDirect3DVertexBuffer8 *buffer;
5298 IDirect3DDevice8 *device;
5299 IDirect3D8 *d3d8;
5300 unsigned int i;
5301 ULONG refcount;
5302 HWND window;
5303 HRESULT hr;
5304 BYTE *data;
5306 window = create_window();
5307 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5308 ok(!!d3d8, "Failed to create a D3D object.\n");
5309 if (!(device = create_device(d3d8, window, NULL)))
5311 skip("Failed to create a D3D device, skipping tests.\n");
5312 IDirect3D8_Release(d3d8);
5313 DestroyWindow(window);
5314 return;
5317 hr = IDirect3DDevice8_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
5318 0, D3DPOOL_DEFAULT, &buffer);
5319 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#lx.\n", hr);
5321 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5323 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &data, test_data[i].flags);
5324 ok(hr == test_data[i].result, "Got unexpected hr %#lx for %s.\n",
5325 hr, test_data[i].debug_string);
5326 if (SUCCEEDED(hr))
5328 ok(!!data, "Got unexpected data %p.\n", data);
5329 hr = IDirect3DVertexBuffer8_Unlock(buffer);
5330 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
5334 IDirect3DVertexBuffer8_Release(buffer);
5335 refcount = IDirect3DDevice8_Release(device);
5336 ok(!refcount, "Device has %lu references left.\n", refcount);
5337 IDirect3D8_Release(d3d8);
5338 DestroyWindow(window);
5341 /* Test the default texture stage state values */
5342 static void test_texture_stage_states(void)
5344 IDirect3DDevice8 *device;
5345 IDirect3D8 *d3d8;
5346 unsigned int i;
5347 ULONG refcount;
5348 D3DCAPS8 caps;
5349 DWORD value;
5350 HWND window;
5351 HRESULT hr;
5353 window = create_window();
5354 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5355 ok(!!d3d8, "Failed to create a D3D object.\n");
5356 if (!(device = create_device(d3d8, window, NULL)))
5358 skip("Failed to create a D3D device, skipping tests.\n");
5359 IDirect3D8_Release(d3d8);
5360 DestroyWindow(window);
5361 return;
5364 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5365 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
5367 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
5369 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
5370 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5371 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
5372 "Got unexpected value %#lx for D3DTSS_COLOROP, stage %u.\n", value, i);
5373 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
5374 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5375 ok(value == D3DTA_TEXTURE, "Got unexpected value %#lx for D3DTSS_COLORARG1, stage %u.\n", value, i);
5376 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
5377 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5378 ok(value == D3DTA_CURRENT, "Got unexpected value %#lx for D3DTSS_COLORARG2, stage %u.\n", value, i);
5379 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
5380 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5381 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
5382 "Got unexpected value %#lx for D3DTSS_ALPHAOP, stage %u.\n", value, i);
5383 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
5384 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5385 ok(value == D3DTA_TEXTURE, "Got unexpected value %#lx for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
5386 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
5387 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5388 ok(value == D3DTA_CURRENT, "Got unexpected value %#lx for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
5389 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
5390 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5391 ok(!value, "Got unexpected value %#lx for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
5392 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
5393 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5394 ok(!value, "Got unexpected value %#lx for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
5395 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
5396 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5397 ok(!value, "Got unexpected value %#lx for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
5398 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
5399 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5400 ok(!value, "Got unexpected value %#lx for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
5401 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
5402 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5403 ok(value == i, "Got unexpected value %#lx for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
5404 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
5405 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5406 ok(!value, "Got unexpected value %#lx for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
5407 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
5408 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5409 ok(!value, "Got unexpected value %#lx for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
5410 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
5411 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5412 ok(value == D3DTTFF_DISABLE,
5413 "Got unexpected value %#lx for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
5414 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
5415 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5416 ok(value == D3DTA_CURRENT, "Got unexpected value %#lx for D3DTSS_COLORARG0, stage %u.\n", value, i);
5417 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
5418 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5419 ok(value == D3DTA_CURRENT, "Got unexpected value %#lx for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
5420 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
5421 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#lx.\n", hr);
5422 ok(value == D3DTA_CURRENT, "Got unexpected value %#lx for D3DTSS_RESULTARG, stage %u.\n", value, i);
5425 refcount = IDirect3DDevice8_Release(device);
5426 ok(!refcount, "Device has %lu references left.\n", refcount);
5427 IDirect3D8_Release(d3d8);
5428 DestroyWindow(window);
5431 static void test_cube_textures(void)
5433 IDirect3DCubeTexture8 *texture;
5434 IDirect3DDevice8 *device;
5435 IDirect3D8 *d3d8;
5436 ULONG refcount;
5437 D3DCAPS8 caps;
5438 HWND window;
5439 HRESULT hr;
5441 window = create_window();
5442 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5443 ok(!!d3d8, "Failed to create a D3D object.\n");
5444 if (!(device = create_device(d3d8, window, NULL)))
5446 skip("Failed to create a D3D device, skipping tests.\n");
5447 IDirect3D8_Release(d3d8);
5448 DestroyWindow(window);
5449 return;
5452 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5453 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
5455 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
5457 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
5458 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#lx.\n", hr);
5459 IDirect3DCubeTexture8_Release(texture);
5460 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
5461 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#lx.\n", hr);
5462 IDirect3DCubeTexture8_Release(texture);
5463 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
5464 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#lx.\n", hr);
5465 IDirect3DCubeTexture8_Release(texture);
5467 else
5469 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
5470 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for D3DPOOL_DEFAULT cube texture.\n", hr);
5471 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
5472 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for D3DPOOL_MANAGED cube texture.\n", hr);
5473 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
5474 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
5476 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture);
5477 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#lx.\n", hr);
5478 IDirect3DCubeTexture8_Release(texture);
5480 refcount = IDirect3DDevice8_Release(device);
5481 ok(!refcount, "Device has %lu references left.\n", refcount);
5482 IDirect3D8_Release(d3d8);
5483 DestroyWindow(window);
5486 static void test_get_set_texture(void)
5488 const IDirect3DBaseTexture8Vtbl *texture_vtbl;
5489 IDirect3DBaseTexture8 *texture;
5490 IDirect3DDevice8 *device;
5491 IDirect3D8 *d3d;
5492 ULONG refcount;
5493 HWND window;
5494 HRESULT hr;
5496 window = create_window();
5497 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5498 ok(!!d3d, "Failed to create a D3D object.\n");
5499 if (!(device = create_device(d3d, window, NULL)))
5501 skip("Failed to create a D3D device, skipping tests.\n");
5502 IDirect3D8_Release(d3d);
5503 DestroyWindow(window);
5504 return;
5507 texture = (IDirect3DBaseTexture8 *)0xdeadbeef;
5508 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
5509 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5510 hr = IDirect3DDevice8_GetTexture(device, 0, &texture);
5511 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
5512 ok(!texture, "Got unexpected texture %p.\n", texture);
5514 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
5515 D3DPOOL_MANAGED, (IDirect3DTexture8 **)&texture);
5516 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
5517 texture_vtbl = texture->lpVtbl;
5518 texture->lpVtbl = (IDirect3DBaseTexture8Vtbl *)0xdeadbeef;
5519 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
5520 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
5521 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
5522 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
5523 texture->lpVtbl = NULL;
5524 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
5525 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
5526 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
5527 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
5528 texture->lpVtbl = texture_vtbl;
5529 IDirect3DBaseTexture8_Release(texture);
5531 refcount = IDirect3DDevice8_Release(device);
5532 ok(!refcount, "Device has %lu references left.\n", refcount);
5533 IDirect3D8_Release(d3d);
5534 DestroyWindow(window);
5537 /* Test the behaviour of the IDirect3DDevice8::CreateImageSurface() method.
5539 * The expected behaviour (as documented in the original DX8 docs) is that the
5540 * call returns a surface in the SYSTEMMEM pool. Games like Max Payne 1 and 2
5541 * depend on this behaviour.
5543 * A short remark in the DX9 docs however states that the pool of the returned
5544 * surface object is D3DPOOL_SCRATCH. This is misinformation and would result
5545 * in screenshots not appearing in the savegame loading menu of both games
5546 * mentioned above (engine tries to display a texture from the scratch pool).
5548 * This test verifies that the behaviour described in the original d3d8 docs
5549 * is the correct one. For more information about this issue, see the MSDN:
5550 * d3d9 docs: "Converting to Direct3D 9"
5551 * d3d9 reference: "IDirect3DDevice9::CreateOffscreenPlainSurface"
5552 * d3d8 reference: "IDirect3DDevice8::CreateImageSurface" */
5553 static void test_image_surface_pool(void)
5555 IDirect3DSurface8 *surface;
5556 IDirect3DDevice8 *device;
5557 D3DSURFACE_DESC desc;
5558 IDirect3D8 *d3d8;
5559 ULONG refcount;
5560 HWND window;
5561 HRESULT hr;
5563 window = create_window();
5564 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5565 ok(!!d3d8, "Failed to create a D3D object.\n");
5566 if (!(device = create_device(d3d8, window, NULL)))
5568 skip("Failed to create a D3D device, skipping tests.\n");
5569 IDirect3D8_Release(d3d8);
5570 DestroyWindow(window);
5571 return;
5574 hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
5575 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
5576 hr = IDirect3DSurface8_GetDesc(surface, &desc);
5577 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
5578 ok(desc.Pool == D3DPOOL_SYSTEMMEM, "Got unexpected pool %#x.\n", desc.Pool);
5579 IDirect3DSurface8_Release(surface);
5581 refcount = IDirect3DDevice8_Release(device);
5582 ok(!refcount, "Device has %lu references left.\n", refcount);
5583 IDirect3D8_Release(d3d8);
5584 DestroyWindow(window);
5587 static void test_surface_get_container(void)
5589 IDirect3DTexture8 *texture = NULL;
5590 IDirect3DSurface8 *surface = NULL;
5591 IDirect3DDevice8 *device;
5592 IUnknown *container;
5593 IDirect3D8 *d3d8;
5594 ULONG refcount;
5595 HWND window;
5596 HRESULT hr;
5598 window = create_window();
5599 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5600 ok(!!d3d8, "Failed to create a D3D object.\n");
5601 if (!(device = create_device(d3d8, window, NULL)))
5603 skip("Failed to create a D3D device, skipping tests.\n");
5604 IDirect3D8_Release(d3d8);
5605 DestroyWindow(window);
5606 return;
5609 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0,
5610 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
5611 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
5612 ok(!!texture, "Got unexpected texture %p.\n", texture);
5614 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5615 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
5616 ok(!!surface, "Got unexpected surface %p.\n", surface);
5618 /* These should work... */
5619 container = NULL;
5620 hr = IDirect3DSurface8_GetContainer(surface, &IID_IUnknown, (void **)&container);
5621 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#lx.\n", hr);
5622 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5623 IUnknown_Release(container);
5625 container = NULL;
5626 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DResource8, (void **)&container);
5627 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#lx.\n", hr);
5628 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5629 IUnknown_Release(container);
5631 container = NULL;
5632 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DBaseTexture8, (void **)&container);
5633 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#lx.\n", hr);
5634 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5635 IUnknown_Release(container);
5637 container = NULL;
5638 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DTexture8, (void **)&container);
5639 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#lx.\n", hr);
5640 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5641 IUnknown_Release(container);
5643 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5644 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DSurface8, (void **)&container);
5645 ok(hr == E_NOINTERFACE, "Got unexpected hr %#lx.\n", hr);
5646 ok(!container, "Got unexpected container %p.\n", container);
5648 IDirect3DSurface8_Release(surface);
5649 IDirect3DTexture8_Release(texture);
5650 refcount = IDirect3DDevice8_Release(device);
5651 ok(!refcount, "Device has %lu references left.\n", refcount);
5652 IDirect3D8_Release(d3d8);
5653 DestroyWindow(window);
5656 static void test_lockrect_invalid(void)
5658 static const RECT valid[] =
5660 {60, 60, 68, 68},
5661 {120, 60, 128, 68},
5662 {60, 120, 68, 128},
5664 static const RECT invalid[] =
5666 {60, 60, 60, 68}, /* 0 height */
5667 {60, 60, 68, 60}, /* 0 width */
5668 {68, 60, 60, 68}, /* left > right */
5669 {60, 68, 68, 60}, /* top > bottom */
5670 {-8, 60, 0, 68}, /* left < surface */
5671 {60, -8, 68, 0}, /* top < surface */
5672 {-16, 60, -8, 68}, /* right < surface */
5673 {60, -16, 68, -8}, /* bottom < surface */
5674 {60, 60, 136, 68}, /* right > surface */
5675 {60, 60, 68, 136}, /* bottom > surface */
5676 {136, 60, 144, 68}, /* left > surface */
5677 {60, 136, 68, 144}, /* top > surface */
5679 IDirect3DSurface8 *surface;
5680 IDirect3DTexture8 *texture;
5681 IDirect3DCubeTexture8 *cube_texture;
5682 D3DLOCKED_RECT locked_rect;
5683 IDirect3DDevice8 *device;
5684 HRESULT hr, expected_hr;
5685 IDirect3D8 *d3d8;
5686 unsigned int i, r;
5687 ULONG refcount;
5688 HWND window;
5689 BYTE *base;
5690 unsigned int offset, expected_offset;
5691 static const struct
5693 D3DRESOURCETYPE type;
5694 D3DPOOL pool;
5695 const char *name;
5696 BOOL validate, clear;
5698 resources[] =
5700 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface", TRUE, TRUE},
5701 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture", FALSE, FALSE},
5702 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture", FALSE, FALSE},
5703 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture", FALSE, FALSE},
5704 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture", TRUE, TRUE},
5705 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture", TRUE, TRUE},
5706 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture", TRUE, TRUE},
5709 window = create_window();
5710 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5711 ok(!!d3d8, "Failed to create a D3D object.\n");
5712 if (!(device = create_device(d3d8, window, NULL)))
5714 skip("Failed to create a D3D device, skipping tests.\n");
5715 IDirect3D8_Release(d3d8);
5716 DestroyWindow(window);
5717 return;
5720 for (r = 0; r < ARRAY_SIZE(resources); ++r)
5722 texture = NULL;
5723 cube_texture = NULL;
5724 switch (resources[r].type)
5726 case D3DRTYPE_SURFACE:
5727 hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
5728 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx, type %s.\n", hr, resources[r].name);
5729 break;
5731 case D3DRTYPE_TEXTURE:
5732 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
5733 resources[r].pool, &texture);
5734 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx, type %s.\n", hr, resources[r].name);
5735 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5736 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx, type %s.\n", hr, resources[r].name);
5737 break;
5739 case D3DRTYPE_CUBETEXTURE:
5740 hr = IDirect3DDevice8_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
5741 resources[r].pool, &cube_texture);
5742 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#lx, type %s.\n", hr, resources[r].name);
5743 hr = IDirect3DCubeTexture8_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
5744 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx, type %s.\n", hr, resources[r].name);
5745 break;
5747 default:
5748 break;
5751 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5752 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx, type %s.\n", hr, resources[r].name);
5753 base = locked_rect.pBits;
5754 hr = IDirect3DSurface8_UnlockRect(surface);
5755 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
5756 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
5757 hr = IDirect3DSurface8_UnlockRect(surface);
5758 ok(hr == expected_hr, "Got hr %#lx, expected %#lx, type %s.\n", hr, expected_hr, resources[r].name);
5760 for (i = 0; i < ARRAY_SIZE(valid); ++i)
5762 const RECT *rect = &valid[i];
5764 locked_rect.pBits = (BYTE *)0xdeadbeef;
5765 locked_rect.Pitch = 0xdeadbeef;
5767 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
5768 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#lx, type %s.\n",
5769 wine_dbgstr_rect(rect), hr, resources[r].name);
5771 offset = (BYTE *)locked_rect.pBits - base;
5772 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5773 ok(offset == expected_offset,
5774 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5775 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
5777 hr = IDirect3DSurface8_UnlockRect(surface);
5778 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s\n", hr, resources[r].name);
5780 if (texture)
5782 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, rect, 0);
5783 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#lx, type %s.\n",
5784 wine_dbgstr_rect(rect), hr, resources[r].name);
5786 offset = (BYTE *)locked_rect.pBits - base;
5787 ok(offset == expected_offset,
5788 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5789 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
5791 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5792 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
5794 if (cube_texture)
5796 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0, &locked_rect, rect, 0);
5797 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#lx, type %s.\n",
5798 wine_dbgstr_rect(rect), hr, resources[r].name);
5800 offset = (BYTE *)locked_rect.pBits - base;
5801 ok(offset == expected_offset,
5802 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5803 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
5805 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5806 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
5810 for (i = 0; i < ARRAY_SIZE(invalid); ++i)
5812 const RECT *rect = &invalid[i];
5814 locked_rect.pBits = (void *)0xdeadbeef;
5815 locked_rect.Pitch = 1;
5816 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
5817 if (resources[r].validate)
5818 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect %s, type %s.\n",
5819 hr, wine_dbgstr_rect(rect), resources[r].name);
5820 else
5821 ok(SUCCEEDED(hr), "Got unexpected hr %#lx for rect %s, type %s.\n",
5822 hr, wine_dbgstr_rect(rect), resources[r].name);
5824 if (SUCCEEDED(hr))
5826 offset = (BYTE *)locked_rect.pBits - base;
5827 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
5828 ok(offset == expected_offset,
5829 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
5830 offset, expected_offset,wine_dbgstr_rect(rect), resources[r].name);
5832 hr = IDirect3DSurface8_UnlockRect(surface);
5833 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
5835 else
5837 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5838 locked_rect.pBits, resources[r].name);
5839 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5840 locked_rect.Pitch, resources[r].name);
5844 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5845 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#lx, type %s.\n",
5846 hr, resources[r].name);
5847 locked_rect.pBits = (void *)0xdeadbeef;
5848 locked_rect.Pitch = 1;
5849 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5850 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
5851 if (resources[r].clear)
5853 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5854 locked_rect.pBits, resources[r].name);
5855 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5856 locked_rect.Pitch, resources[r].name);
5858 else
5860 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
5861 locked_rect.pBits, resources[r].name);
5862 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
5863 locked_rect.Pitch, resources[r].name);
5865 hr = IDirect3DSurface8_UnlockRect(surface);
5866 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
5868 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
5869 ok(hr == D3D_OK, "Got unexpected hr %#lx for rect %s, type %s.\n",
5870 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5871 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
5872 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect %s, type %s.\n",
5873 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5874 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[1], 0);
5875 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect %s, type %s.\n",
5876 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5877 hr = IDirect3DSurface8_UnlockRect(surface);
5878 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx, type %s.\n", hr, resources[r].name);
5880 IDirect3DSurface8_Release(surface);
5881 if (texture)
5883 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5884 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#lx, type %s.\n",
5885 hr, resources[r].name);
5886 locked_rect.pBits = (void *)0xdeadbeef;
5887 locked_rect.Pitch = 1;
5888 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5889 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
5890 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
5891 locked_rect.pBits, resources[r].name);
5892 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
5893 locked_rect.Pitch, resources[r].name);
5894 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5895 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
5896 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5897 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#lx, type %s.\n", hr, resources[r].name);
5898 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5899 ok(hr == D3D_OK, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
5901 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5902 ok(hr == D3D_OK, "Got unexpected hr %#lx for rect %s, type %s.\n",
5903 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5904 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5905 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect %s, type %s.\n",
5906 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5907 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[1], 0);
5908 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect %s, type %s.\n",
5909 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5910 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5911 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#lx, type %s.\n", hr, resources[r].name);
5913 IDirect3DTexture8_Release(texture);
5915 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_WRITEONLY,
5916 D3DFMT_A8R8G8B8, resources[r].pool, &texture);
5917 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for type %s.\n",
5918 hr, resources[r].name);
5921 if (cube_texture)
5923 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5924 &locked_rect, NULL, 0);
5925 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#lx, type %s.\n",
5926 hr, resources[r].name);
5927 locked_rect.pBits = (void *)0xdeadbeef;
5928 locked_rect.Pitch = 1;
5929 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5930 &locked_rect, NULL, 0);
5931 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
5932 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5933 locked_rect.pBits, resources[r].name);
5934 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5935 locked_rect.Pitch, resources[r].name);
5936 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5937 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
5938 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5939 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#lx, type %s.\n", hr, resources[r].name);
5940 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5941 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, type %s.\n", hr, resources[r].name);
5943 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5944 &locked_rect, &valid[0], 0);
5945 ok(hr == D3D_OK, "Got unexpected hr %#lx for rect %s, type %s.\n",
5946 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5947 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5948 &locked_rect, &valid[0], 0);
5949 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect %s, type %s.\n",
5950 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5951 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5952 &locked_rect, &valid[1], 0);
5953 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect %s, type %s.\n",
5954 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5955 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5956 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#lx, type %s.\n", hr, resources[r].name);
5958 IDirect3DTexture8_Release(cube_texture);
5960 hr = IDirect3DDevice8_CreateCubeTexture(device, 128, 1, D3DUSAGE_WRITEONLY, D3DFMT_A8R8G8B8,
5961 resources[r].pool, &cube_texture);
5962 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for type %s.\n",
5963 hr, resources[r].name);
5967 refcount = IDirect3DDevice8_Release(device);
5968 ok(!refcount, "Device has %lu references left.\n", refcount);
5969 IDirect3D8_Release(d3d8);
5970 DestroyWindow(window);
5973 static void test_private_data(void)
5975 ULONG refcount, expected_refcount;
5976 IDirect3DTexture8 *texture;
5977 IDirect3DSurface8 *surface, *surface2;
5978 IDirect3DDevice8 *device;
5979 IDirect3D8 *d3d8;
5980 IUnknown *ptr;
5981 HWND window;
5982 HRESULT hr;
5983 DWORD size;
5984 DWORD data[4] = {1, 2, 3, 4};
5985 static const GUID d3d8_private_data_test_guid2 =
5987 0x2e5afac2,
5988 0x87b5,
5989 0x4c10,
5990 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
5993 window = create_window();
5994 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5995 ok(!!d3d8, "Failed to create a D3D object.\n");
5996 if (!(device = create_device(d3d8, window, NULL)))
5998 skip("Failed to create a D3D device, skipping tests.\n");
5999 IDirect3D8_Release(d3d8);
6000 DestroyWindow(window);
6001 return;
6004 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_A8R8G8B8, &surface);
6005 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
6007 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
6008 device, 0, D3DSPD_IUNKNOWN);
6009 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
6010 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
6011 device, 5, D3DSPD_IUNKNOWN);
6012 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
6013 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
6014 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
6015 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
6017 /* A failing SetPrivateData call does not clear the old data with the same tag. */
6018 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
6019 sizeof(device), D3DSPD_IUNKNOWN);
6020 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
6021 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
6022 sizeof(device) * 2, D3DSPD_IUNKNOWN);
6023 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
6024 size = sizeof(ptr);
6025 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
6026 ok(SUCCEEDED(hr), "Failed to get private data, hr %#lx.\n", hr);
6027 IUnknown_Release(ptr);
6028 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
6029 ok(SUCCEEDED(hr), "Failed to free private data, hr %#lx.\n", hr);
6031 refcount = get_refcount((IUnknown *)device);
6032 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
6033 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6034 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6035 expected_refcount = refcount + 1;
6036 refcount = get_refcount((IUnknown *)device);
6037 ok(refcount == expected_refcount, "Got unexpected refcount %lu, expected %lu.\n", refcount, expected_refcount);
6038 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
6039 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6040 expected_refcount = refcount - 1;
6041 refcount = get_refcount((IUnknown *)device);
6042 ok(refcount == expected_refcount, "Got unexpected refcount %lu, expected %lu.\n", refcount, expected_refcount);
6044 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
6045 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6046 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6047 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
6048 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6049 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6050 refcount = get_refcount((IUnknown *)device);
6051 ok(refcount == expected_refcount, "Got unexpected refcount %lu, expected %lu.\n", refcount, expected_refcount);
6053 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
6054 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
6055 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6056 size = 2 * sizeof(ptr);
6057 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
6058 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6059 ok(size == sizeof(device), "Got unexpected size %lu.\n", size);
6060 expected_refcount = refcount + 2;
6061 refcount = get_refcount((IUnknown *)device);
6062 ok(refcount == expected_refcount, "Got unexpected refcount %lu, expected %lu.\n", refcount, expected_refcount);
6063 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
6064 IUnknown_Release(ptr);
6065 expected_refcount--;
6067 ptr = (IUnknown *)0xdeadbeef;
6068 size = 1;
6069 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
6070 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6071 ok(size == sizeof(device), "Got unexpected size %lu.\n", size);
6072 size = 2 * sizeof(ptr);
6073 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
6074 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
6075 ok(size == sizeof(device), "Got unexpected size %lu.\n", size);
6076 refcount = get_refcount((IUnknown *)device);
6077 ok(refcount == expected_refcount, "Got unexpected refcount %lu, expected %lu.\n", refcount, expected_refcount);
6078 size = 1;
6079 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
6080 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#lx.\n", hr);
6081 ok(size == sizeof(device), "Got unexpected size %lu.\n", size);
6082 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6083 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, NULL, NULL);
6084 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
6085 size = 0xdeadbabe;
6086 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, &ptr, &size);
6087 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
6088 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
6089 ok(size == 0xdeadbabe, "Got unexpected size %lu.\n", size);
6090 /* GetPrivateData with size = NULL causes an access violation on Windows if the
6091 * requested data exists. */
6093 /* Destroying the surface frees the held reference. */
6094 IDirect3DSurface8_Release(surface);
6095 expected_refcount = refcount - 2;
6096 refcount = get_refcount((IUnknown *)device);
6097 ok(refcount == expected_refcount, "Got unexpected refcount %lu, expected %lu.\n", refcount, expected_refcount);
6099 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
6100 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
6101 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
6102 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#lx.\n", hr);
6103 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
6104 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#lx.\n", hr);
6106 hr = IDirect3DTexture8_SetPrivateData(texture, &d3d8_private_data_test_guid, data, sizeof(data), 0);
6107 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
6109 memset(data, 0, sizeof(data));
6110 size = sizeof(data);
6111 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, data, &size);
6112 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
6113 hr = IDirect3DTexture8_GetPrivateData(texture, &d3d8_private_data_test_guid, data, &size);
6114 ok(SUCCEEDED(hr), "Failed to get private data, hr %#lx.\n", hr);
6115 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
6116 "Got unexpected private data: %lu, %lu, %lu, %lu.\n", data[0], data[1], data[2], data[3]);
6118 hr = IDirect3DTexture8_FreePrivateData(texture, &d3d8_private_data_test_guid);
6119 ok(SUCCEEDED(hr), "Failed to free private data, hr %#lx.\n", hr);
6121 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, data, sizeof(data), 0);
6122 ok(SUCCEEDED(hr), "Failed to set private data, hr %#lx.\n", hr);
6123 hr = IDirect3DSurface8_GetPrivateData(surface2, &d3d8_private_data_test_guid, data, &size);
6124 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#lx.\n", hr);
6125 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
6126 ok(SUCCEEDED(hr), "Failed to free private data, hr %#lx.\n", hr);
6128 IDirect3DSurface8_Release(surface2);
6129 IDirect3DSurface8_Release(surface);
6130 IDirect3DTexture8_Release(texture);
6132 refcount = IDirect3DDevice8_Release(device);
6133 ok(!refcount, "Device has %lu references left.\n", refcount);
6134 IDirect3D8_Release(d3d8);
6135 DestroyWindow(window);
6138 static void test_surface_dimensions(void)
6140 IDirect3DSurface8 *surface;
6141 IDirect3DDevice8 *device;
6142 IDirect3D8 *d3d8;
6143 ULONG refcount;
6144 HWND window;
6145 HRESULT hr;
6147 window = create_window();
6148 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6149 ok(!!d3d8, "Failed to create a D3D object.\n");
6150 if (!(device = create_device(d3d8, window, NULL)))
6152 skip("Failed to create a D3D device, skipping tests.\n");
6153 IDirect3D8_Release(d3d8);
6154 DestroyWindow(window);
6155 return;
6158 hr = IDirect3DDevice8_CreateImageSurface(device, 0, 1, D3DFMT_A8R8G8B8, &surface);
6159 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
6160 hr = IDirect3DDevice8_CreateImageSurface(device, 1, 0, D3DFMT_A8R8G8B8, &surface);
6161 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
6163 refcount = IDirect3DDevice8_Release(device);
6164 ok(!refcount, "Device has %lu references left.\n", refcount);
6165 IDirect3D8_Release(d3d8);
6166 DestroyWindow(window);
6169 static void test_surface_format_null(void)
6171 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
6172 IDirect3DTexture8 *texture;
6173 IDirect3DSurface8 *surface;
6174 IDirect3DSurface8 *rt, *ds;
6175 D3DLOCKED_RECT locked_rect;
6176 IDirect3DDevice8 *device;
6177 D3DSURFACE_DESC desc;
6178 IDirect3D8 *d3d;
6179 ULONG refcount;
6180 HWND window;
6181 HRESULT hr;
6183 d3d = Direct3DCreate8(D3D_SDK_VERSION);
6184 ok(!!d3d, "Failed to create a D3D object.\n");
6186 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6187 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
6188 if (hr != D3D_OK)
6190 skip("No D3DFMT_NULL support, skipping test.\n");
6191 IDirect3D8_Release(d3d);
6192 return;
6195 window = create_window();
6196 if (!(device = create_device(d3d, window, NULL)))
6198 skip("Failed to create a D3D device, skipping tests.\n");
6199 IDirect3D8_Release(d3d);
6200 DestroyWindow(window);
6201 return;
6204 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6205 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
6206 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#lx.\n", hr);
6208 hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6209 D3DFMT_NULL, D3DFMT_D24S8);
6210 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#lx.\n", hr);
6212 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
6213 D3DMULTISAMPLE_NONE, TRUE, &surface);
6214 ok(SUCCEEDED(hr), "Failed to create render target, hr %#lx.\n", hr);
6216 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
6217 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#lx.\n", hr);
6219 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds);
6220 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#lx.\n", hr);
6222 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
6223 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
6225 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
6226 ok(SUCCEEDED(hr), "Clear failed, hr %#lx.\n", hr);
6228 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
6229 ok(SUCCEEDED(hr), "Failed to set render target, hr %#lx.\n", hr);
6231 IDirect3DSurface8_Release(rt);
6232 IDirect3DSurface8_Release(ds);
6234 hr = IDirect3DSurface8_GetDesc(surface, &desc);
6235 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#lx.\n", hr);
6236 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
6237 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
6239 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
6240 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
6241 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
6242 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
6244 hr = IDirect3DSurface8_UnlockRect(surface);
6245 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6247 IDirect3DSurface8_Release(surface);
6249 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
6250 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture);
6251 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
6252 IDirect3DTexture8_Release(texture);
6254 refcount = IDirect3DDevice8_Release(device);
6255 ok(!refcount, "Device has %lu references left.\n", refcount);
6256 IDirect3D8_Release(d3d);
6257 DestroyWindow(window);
6260 static void test_surface_double_unlock(void)
6262 static const D3DPOOL pools[] =
6264 D3DPOOL_DEFAULT,
6265 D3DPOOL_SYSTEMMEM,
6267 IDirect3DSurface8 *surface;
6268 IDirect3DDevice8 *device;
6269 D3DLOCKED_RECT lr;
6270 IDirect3D8 *d3d;
6271 unsigned int i;
6272 ULONG refcount;
6273 HWND window;
6274 HRESULT hr;
6276 window = create_window();
6277 d3d = Direct3DCreate8(D3D_SDK_VERSION);
6278 ok(!!d3d, "Failed to create a D3D object.\n");
6279 if (!(device = create_device(d3d, window, NULL)))
6281 skip("Failed to create a D3D device, skipping tests.\n");
6282 IDirect3D8_Release(d3d);
6283 DestroyWindow(window);
6284 return;
6287 for (i = 0; i < ARRAY_SIZE(pools); ++i)
6289 switch (pools[i])
6291 case D3DPOOL_DEFAULT:
6292 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6293 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
6294 if (FAILED(hr))
6296 skip("D3DFMT_X8R8G8B8 render targets not supported, skipping double unlock DEFAULT pool test.\n");
6297 continue;
6300 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_X8R8G8B8,
6301 D3DMULTISAMPLE_NONE, TRUE, &surface);
6302 ok(SUCCEEDED(hr), "Failed to create render target, hr %#lx.\n", hr);
6303 break;
6305 case D3DPOOL_SYSTEMMEM:
6306 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64, D3DFMT_X8R8G8B8, &surface);
6307 ok(SUCCEEDED(hr), "Failed to create image surface, hr %#lx.\n", hr);
6308 break;
6310 default:
6311 break;
6314 hr = IDirect3DSurface8_UnlockRect(surface);
6315 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, for surface in pool %#x.\n", hr, pools[i]);
6316 hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
6317 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#lx.\n", pools[i], hr);
6318 hr = IDirect3DSurface8_UnlockRect(surface);
6319 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#lx.\n", pools[i], hr);
6320 hr = IDirect3DSurface8_UnlockRect(surface);
6321 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, for surface in pool %#x.\n", hr, pools[i]);
6323 IDirect3DSurface8_Release(surface);
6326 refcount = IDirect3DDevice8_Release(device);
6327 ok(!refcount, "Device has %lu references left.\n", refcount);
6328 IDirect3D8_Release(d3d);
6329 DestroyWindow(window);
6332 static void test_surface_blocks(void)
6334 static const struct
6336 D3DFORMAT fmt;
6337 const char *name;
6338 unsigned int block_width;
6339 unsigned int block_height;
6340 BOOL broken;
6341 BOOL create_size_checked, core_fmt;
6343 formats[] =
6345 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
6346 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
6347 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
6348 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
6349 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
6350 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
6351 * which doesn't match the format spec. On newer Nvidia cards
6352 * they have the correct 4x4 block size */
6353 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
6354 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
6355 /* Windows drivers generally enforce block-aligned locks for
6356 * YUY2 and UYVY. The notable exception is the AMD r500 driver
6357 * in d3d8. The same driver checks the sizes in d3d9. */
6358 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, TRUE, FALSE, TRUE },
6359 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, TRUE, FALSE, TRUE },
6361 static const struct
6363 D3DPOOL pool;
6364 const char *name;
6365 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
6366 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
6367 BOOL success;
6369 pools[] =
6371 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
6372 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
6373 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
6374 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
6376 static struct
6378 D3DRESOURCETYPE rtype;
6379 const char *type_name;
6380 D3DPOOL pool;
6381 const char *pool_name;
6382 BOOL need_driver_support, need_runtime_support;
6384 create_tests[] =
6386 /* D3d8 only supports sysmem surfaces, which are created via CreateImageSurface. Other tests confirm
6387 * that they are D3DPOOL_SYSTEMMEM surfaces, but their creation restriction behaves like the scratch
6388 * pool in d3d9. */
6389 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE, TRUE },
6391 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
6392 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
6393 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
6394 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6396 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
6397 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
6398 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
6399 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6401 IDirect3DTexture8 *texture;
6402 IDirect3DCubeTexture8 *cube_texture;
6403 IDirect3DSurface8 *surface;
6404 D3DLOCKED_RECT locked_rect;
6405 IDirect3DDevice8 *device;
6406 unsigned int i, j, k, w, h;
6407 IDirect3D8 *d3d;
6408 ULONG refcount;
6409 HWND window;
6410 HRESULT hr;
6411 RECT rect;
6412 BOOL tex_pow2, cube_pow2;
6413 D3DCAPS8 caps;
6414 static const RECT invalid[] =
6416 {60, 60, 60, 68}, /* 0 height */
6417 {60, 60, 68, 60}, /* 0 width */
6418 {68, 60, 60, 68}, /* left > right */
6419 {60, 68, 68, 60}, /* top > bottom */
6420 {-8, 60, 0, 68}, /* left < surface */
6421 {60, -8, 68, 0}, /* top < surface */
6422 {-16, 60, -8, 68}, /* right < surface */
6423 {60, -16, 68, -8}, /* bottom < surface */
6424 {60, 60, 136, 68}, /* right > surface */
6425 {60, 60, 68, 136}, /* bottom > surface */
6426 {136, 60, 144, 68}, /* left > surface */
6427 {60, 136, 68, 144}, /* top > surface */
6430 window = create_window();
6431 d3d = Direct3DCreate8(D3D_SDK_VERSION);
6432 ok(!!d3d, "Failed to create a D3D object.\n");
6433 if (!(device = create_device(d3d, window, NULL)))
6435 skip("Failed to create a D3D device, skipping tests.\n");
6436 IDirect3D8_Release(d3d);
6437 DestroyWindow(window);
6438 return;
6441 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6442 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
6443 tex_pow2 = caps.TextureCaps & D3DPTEXTURECAPS_POW2;
6444 if (tex_pow2)
6445 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
6446 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6448 for (i = 0; i < ARRAY_SIZE(formats); ++i)
6450 BOOL tex_support, cube_support, surface_support, format_known;
6452 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6453 0, D3DRTYPE_TEXTURE, formats[i].fmt);
6454 tex_support = SUCCEEDED(hr);
6455 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6456 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
6457 cube_support = SUCCEEDED(hr);
6458 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6459 0, D3DRTYPE_SURFACE, formats[i].fmt);
6460 surface_support = SUCCEEDED(hr);
6462 /* Scratch pool in general allows texture creation even if the driver does
6463 * not support the format. If the format is an extension format that is not
6464 * known to the runtime, like ATI2N, some driver support is required for
6465 * this to work.
6467 * It is also possible that Windows Vista and Windows 7 d3d8 runtimes know
6468 * about ATI2N. I cannot check this because all my Vista+ machines support
6469 * ATI2N in hardware, but none of my WinXP machines do. */
6470 format_known = tex_support || cube_support || surface_support;
6472 for (w = 1; w <= 8; w++)
6474 for (h = 1; h <= 8; h++)
6476 BOOL block_aligned = TRUE;
6477 BOOL size_is_pow2;
6479 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6480 block_aligned = FALSE;
6482 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
6484 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
6486 BOOL support, pow2;
6487 HRESULT expect_hr;
6488 BOOL may_succeed = FALSE;
6489 IUnknown **check_null;
6491 if (!formats[i].core_fmt)
6493 /* AMD warns against creating ATI2N textures smaller than
6494 * the block size because the runtime cannot calculate the
6495 * correct texture size. Generalize this for all extension
6496 * formats. */
6497 if (w < formats[i].block_width || h < formats[i].block_height)
6498 continue;
6501 texture = (IDirect3DTexture8 *)0xdeadbeef;
6502 cube_texture = (IDirect3DCubeTexture8 *)0xdeadbeef;
6503 surface = (IDirect3DSurface8 *)0xdeadbeef;
6505 switch (create_tests[j].rtype)
6507 case D3DRTYPE_TEXTURE:
6508 check_null = (IUnknown **)&texture;
6509 hr = IDirect3DDevice8_CreateTexture(device, w, h, 1, 0,
6510 formats[i].fmt, create_tests[j].pool, &texture);
6511 support = tex_support;
6512 pow2 = tex_pow2;
6513 break;
6515 case D3DRTYPE_CUBETEXTURE:
6516 if (w != h)
6517 continue;
6518 check_null = (IUnknown **)&cube_texture;
6519 hr = IDirect3DDevice8_CreateCubeTexture(device, w, 1, 0,
6520 formats[i].fmt, create_tests[j].pool, &cube_texture);
6521 support = cube_support;
6522 pow2 = cube_pow2;
6523 break;
6525 case D3DRTYPE_SURFACE:
6526 check_null = (IUnknown **)&surface;
6527 hr = IDirect3DDevice8_CreateImageSurface(device, w, h,
6528 formats[i].fmt, &surface);
6529 support = surface_support;
6530 pow2 = FALSE;
6531 break;
6533 default:
6534 pow2 = FALSE;
6535 support = FALSE;
6536 check_null = NULL;
6537 break;
6540 if (create_tests[j].need_driver_support && !support)
6541 expect_hr = D3DERR_INVALIDCALL;
6542 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
6543 expect_hr = D3DERR_INVALIDCALL;
6544 else if (formats[i].create_size_checked && !block_aligned)
6545 expect_hr = D3DERR_INVALIDCALL;
6546 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6547 expect_hr = D3DERR_INVALIDCALL;
6548 else
6549 expect_hr = D3D_OK;
6551 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
6552 may_succeed = TRUE;
6554 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6555 * does not support it. Accept scratch creation of extension formats on
6556 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6557 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6558 * support it. */
6559 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6560 "Got unexpected hr %#lx for format %s, pool %s, type %s, size %ux%u.\n",
6561 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
6563 if (FAILED(hr))
6564 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
6565 else
6566 IUnknown_Release(*check_null);
6571 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6572 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
6573 if (FAILED(hr))
6575 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
6576 continue;
6579 for (j = 0; j < ARRAY_SIZE(pools); ++j)
6581 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1,
6582 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
6583 formats[i].fmt, pools[j].pool, &texture);
6584 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
6585 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
6586 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
6587 IDirect3DTexture8_Release(texture);
6589 if (formats[i].block_width > 1)
6591 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
6592 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
6593 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6594 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6595 SUCCEEDED(hr) ? "succeeded" : "failed",
6596 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6597 if (SUCCEEDED(hr))
6599 hr = IDirect3DSurface8_UnlockRect(surface);
6600 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6603 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
6604 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
6605 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6606 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6607 SUCCEEDED(hr) ? "succeeded" : "failed",
6608 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6609 if (SUCCEEDED(hr))
6611 hr = IDirect3DSurface8_UnlockRect(surface);
6612 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6616 if (formats[i].block_height > 1)
6618 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
6619 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
6620 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6621 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6622 SUCCEEDED(hr) ? "succeeded" : "failed",
6623 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6624 if (SUCCEEDED(hr))
6626 hr = IDirect3DSurface8_UnlockRect(surface);
6627 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6630 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
6631 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
6632 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
6633 "Partial block lock %s, expected %s, format %s, pool %s.\n",
6634 SUCCEEDED(hr) ? "succeeded" : "failed",
6635 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
6636 if (SUCCEEDED(hr))
6638 hr = IDirect3DSurface8_UnlockRect(surface);
6639 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6643 for (k = 0; k < ARRAY_SIZE(invalid); ++k)
6645 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &invalid[k], 0);
6646 ok(FAILED(hr) == !pools[j].success, "Got hr %#lx, format %s, pool %s, case %u.\n",
6647 hr, formats[i].name, pools[j].name, k);
6648 if (SUCCEEDED(hr))
6650 hr = IDirect3DSurface8_UnlockRect(surface);
6651 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6655 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
6656 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
6657 ok(hr == D3D_OK, "Got unexpected hr %#lx for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
6658 hr = IDirect3DSurface8_UnlockRect(surface);
6659 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
6661 IDirect3DSurface8_Release(surface);
6664 if (formats[i].block_width == 1 && formats[i].block_height == 1)
6665 continue;
6666 if (!formats[i].core_fmt)
6667 continue;
6669 hr = IDirect3DDevice8_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
6670 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture);
6671 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx, format %s.\n", hr, formats[i].name);
6673 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, NULL, 0);
6674 ok(SUCCEEDED(hr), "Failed lock texture, hr %#lx.\n", hr);
6675 hr = IDirect3DTexture8_UnlockRect(texture, 1);
6676 ok(SUCCEEDED(hr), "Failed lock texture, hr %#lx.\n", hr);
6678 rect.left = 0;
6679 rect.top = 0;
6680 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
6681 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
6682 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
6683 ok(SUCCEEDED(hr), "Failed lock texture, hr %#lx.\n", hr);
6684 hr = IDirect3DTexture8_UnlockRect(texture, 1);
6685 ok(SUCCEEDED(hr), "Failed lock texture, hr %#lx.\n", hr);
6687 rect.right = formats[i].block_width;
6688 rect.bottom = formats[i].block_height;
6689 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
6690 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
6691 if (SUCCEEDED(hr))
6692 IDirect3DTexture8_UnlockRect(texture, 1);
6694 IDirect3DTexture8_Release(texture);
6697 refcount = IDirect3DDevice8_Release(device);
6698 ok(!refcount, "Device has %lu references left.\n", refcount);
6699 IDirect3D8_Release(d3d);
6700 DestroyWindow(window);
6703 static void test_set_palette(void)
6705 IDirect3DDevice8 *device;
6706 IDirect3D8 *d3d8;
6707 UINT refcount;
6708 HWND window;
6709 HRESULT hr;
6710 PALETTEENTRY pal[256];
6711 unsigned int i;
6712 D3DCAPS8 caps;
6714 window = create_window();
6715 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6716 ok(!!d3d8, "Failed to create a D3D object.\n");
6717 if (!(device = create_device(d3d8, window, NULL)))
6719 skip("Failed to create a D3D device, skipping tests.\n");
6720 IDirect3D8_Release(d3d8);
6721 DestroyWindow(window);
6722 return;
6725 for (i = 0; i < ARRAY_SIZE(pal); i++)
6727 pal[i].peRed = i;
6728 pal[i].peGreen = i;
6729 pal[i].peBlue = i;
6730 pal[i].peFlags = 0xff;
6732 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
6733 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#lx.\n", hr);
6735 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6736 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
6737 for (i = 0; i < ARRAY_SIZE(pal); i++)
6739 pal[i].peRed = i;
6740 pal[i].peGreen = i;
6741 pal[i].peBlue = i;
6742 pal[i].peFlags = i;
6744 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
6746 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
6747 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#lx.\n", hr);
6749 else
6751 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
6752 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
6755 refcount = IDirect3DDevice8_Release(device);
6756 ok(!refcount, "Device has %u references left.\n", refcount);
6757 IDirect3D8_Release(d3d8);
6758 DestroyWindow(window);
6761 static void test_pinned_buffers(void)
6763 static const struct
6765 DWORD device_flags;
6766 DWORD usage;
6767 D3DPOOL pool;
6769 tests[] =
6771 {CREATE_DEVICE_SWVP_ONLY, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DPOOL_DEFAULT},
6772 {0, 0, D3DPOOL_MANAGED},
6773 {0, 0, D3DPOOL_SYSTEMMEM},
6775 static const unsigned int vertex_count = 1024;
6776 struct device_desc device_desc;
6777 IDirect3DVertexBuffer8 *buffer;
6778 D3DVERTEXBUFFER_DESC desc;
6779 IDirect3DDevice8 *device;
6780 struct vec3 *ptr, *ptr2;
6781 unsigned int i, test;
6782 IDirect3D8 *d3d;
6783 UINT refcount;
6784 HWND window;
6785 HRESULT hr;
6787 window = create_window();
6788 d3d = Direct3DCreate8(D3D_SDK_VERSION);
6789 ok(!!d3d, "Failed to create a D3D object.\n");
6791 for (test = 0; test < ARRAY_SIZE(tests); ++test)
6793 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
6794 device_desc.device_window = window;
6795 device_desc.width = 640;
6796 device_desc.height = 480;
6797 device_desc.flags = tests[test].device_flags;
6798 if (!(device = create_device(d3d, window, &device_desc)))
6800 skip("Test %u: failed to create a D3D device.\n", test);
6801 continue;
6804 hr = IDirect3DDevice8_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
6805 tests[test].usage, 0, tests[test].pool, &buffer);
6806 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6807 hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
6808 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6809 ok(desc.Pool == tests[test].pool, "Test %u: got unexpected pool %#x.\n", test, desc.Pool);
6810 ok(desc.Usage == tests[test].usage, "Test %u: got unexpected usage %#lx.\n", test, desc.Usage);
6812 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
6813 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6814 for (i = 0; i < vertex_count; ++i)
6816 ptr[i].x = i * 1.0f;
6817 ptr[i].y = i * 2.0f;
6818 ptr[i].z = i * 3.0f;
6820 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6821 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6823 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
6824 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6825 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
6826 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6827 hr = IDirect3DDevice8_BeginScene(device);
6828 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6829 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6830 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6831 hr = IDirect3DDevice8_EndScene(device);
6832 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6834 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
6835 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6836 ok(ptr2 == ptr, "Test %u: got unexpected ptr2 %p, expected %p.\n", test, ptr2, ptr);
6837 for (i = 0; i < vertex_count; ++i)
6839 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6841 ok(FALSE, "Test %u: got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
6842 test, i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6843 break;
6846 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6847 ok(hr == D3D_OK, "Test %u: got unexpected hr %#lx.\n", test, hr);
6849 IDirect3DVertexBuffer8_Release(buffer);
6850 refcount = IDirect3DDevice8_Release(device);
6851 ok(!refcount, "Test %u: device has %u references left.\n", test, refcount);
6853 IDirect3D8_Release(d3d);
6854 DestroyWindow(window);
6857 static void test_npot_textures(void)
6859 IDirect3DDevice8 *device = NULL;
6860 IDirect3D8 *d3d8;
6861 ULONG refcount;
6862 HWND window = NULL;
6863 HRESULT hr;
6864 D3DCAPS8 caps;
6865 IDirect3DTexture8 *texture;
6866 IDirect3DCubeTexture8 *cube_texture;
6867 IDirect3DVolumeTexture8 *volume_texture;
6868 struct
6870 D3DPOOL pool;
6871 const char *pool_name;
6872 HRESULT hr;
6874 pools[] =
6876 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
6877 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
6878 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
6879 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
6881 unsigned int i, levels;
6882 BOOL tex_pow2, cube_pow2, vol_pow2;
6884 window = create_window();
6885 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6886 ok(!!d3d8, "Failed to create a D3D object.\n");
6887 if (!(device = create_device(d3d8, window, NULL)))
6889 skip("Failed to create a D3D device, skipping tests.\n");
6890 goto done;
6893 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6894 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
6895 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
6896 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6897 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6898 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
6899 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
6901 for (i = 0; i < ARRAY_SIZE(pools); i++)
6903 for (levels = 0; levels <= 2; levels++)
6905 HRESULT expected;
6907 hr = IDirect3DDevice8_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
6908 pools[i].pool, &texture);
6909 if (!tex_pow2)
6911 expected = D3D_OK;
6913 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
6915 if (levels == 1)
6916 expected = D3D_OK;
6917 else
6918 expected = pools[i].hr;
6920 else
6922 expected = pools[i].hr;
6924 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#lx, expected %#lx.\n",
6925 pools[i].pool_name, levels, hr, expected);
6927 if (SUCCEEDED(hr))
6928 IDirect3DTexture8_Release(texture);
6931 hr = IDirect3DDevice8_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8,
6932 pools[i].pool, &cube_texture);
6933 if (tex_pow2)
6935 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#lx.\n", pools[i].pool_name, hr);
6937 else
6939 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#lx.\n", pools[i].pool_name, hr);
6942 if (SUCCEEDED(hr))
6943 IDirect3DCubeTexture8_Release(cube_texture);
6945 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8,
6946 pools[i].pool, &volume_texture);
6947 if (tex_pow2)
6949 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#lx.\n", pools[i].pool_name, hr);
6951 else
6953 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#lx.\n", pools[i].pool_name, hr);
6956 if (SUCCEEDED(hr))
6957 IDirect3DVolumeTexture8_Release(volume_texture);
6960 done:
6961 if (device)
6963 refcount = IDirect3DDevice8_Release(device);
6964 ok(!refcount, "Device has %lu references left.\n", refcount);
6966 IDirect3D8_Release(d3d8);
6967 DestroyWindow(window);
6971 static void test_volume_locking(void)
6973 IDirect3DDevice8 *device;
6974 IDirect3D8 *d3d8;
6975 HWND window;
6976 HRESULT hr;
6977 IDirect3DVolumeTexture8 *texture;
6978 unsigned int i;
6979 D3DLOCKED_BOX locked_box;
6980 ULONG refcount;
6981 D3DCAPS8 caps;
6982 static const struct
6984 D3DPOOL pool;
6985 DWORD usage;
6986 HRESULT create_hr, lock_hr;
6988 tests[] =
6990 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
6991 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6992 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
6993 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6994 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
6995 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6996 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
6997 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
7000 window = create_window();
7001 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7002 ok(!!d3d8, "Failed to create a D3D object.\n");
7003 if (!(device = create_device(d3d8, window, NULL)))
7005 skip("Failed to create a D3D device, skipping tests.\n");
7006 IDirect3D8_Release(d3d8);
7007 DestroyWindow(window);
7008 return;
7011 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7012 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
7013 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
7015 skip("Volume textures not supported, skipping test.\n");
7016 goto out;
7019 for (i = 0; i < ARRAY_SIZE(tests); i++)
7021 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
7022 D3DFMT_A8R8G8B8, tests[i].pool, &texture);
7023 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#lx returned %#lx, expected %#lx.\n",
7024 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
7025 if (FAILED(hr))
7026 continue;
7028 locked_box.pBits = (void *)0xdeadbeef;
7029 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
7030 ok(hr == tests[i].lock_hr, "Lock returned %#lx, expected %#lx.\n", hr, tests[i].lock_hr);
7031 if (SUCCEEDED(hr))
7033 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7034 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7036 else
7038 ok (locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
7040 IDirect3DVolumeTexture8_Release(texture);
7043 out:
7044 refcount = IDirect3DDevice8_Release(device);
7045 ok(!refcount, "Device has %lu references left.\n", refcount);
7046 IDirect3D8_Release(d3d8);
7047 DestroyWindow(window);
7050 static void test_update_texture_pool(void)
7052 static const struct
7054 D3DPOOL pool;
7055 DWORD usage;
7057 tests[] =
7059 {D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC},
7060 {D3DPOOL_MANAGED, 0},
7061 {D3DPOOL_SYSTEMMEM, 0},
7062 {D3DPOOL_SCRATCH, 0},
7065 unsigned int expect_colour, colour, i, j;
7066 IDirect3DVolumeTexture8 *src_3d, *dst_3d;
7067 IDirect3DTexture8 *src_2d, *dst_2d;
7068 D3DLOCKED_RECT locked_rect;
7069 IDirect3DDevice8 *device;
7070 D3DLOCKED_BOX locked_box;
7071 IDirect3D8 *d3d8;
7072 ULONG refcount;
7073 D3DCAPS8 caps;
7074 HWND window;
7075 HRESULT hr;
7077 window = create_window();
7078 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7079 ok(!!d3d8, "Failed to create a D3D object.\n");
7080 if (!(device = create_device(d3d8, window, NULL)))
7082 skip("Failed to create a D3D device, skipping tests.\n");
7083 IDirect3D8_Release(d3d8);
7084 DestroyWindow(window);
7085 return;
7088 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7089 ok(hr == S_OK, "Failed to get caps, hr %#lx.\n", hr);
7091 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7093 for (j = 0; j < ARRAY_SIZE(tests); ++j)
7095 winetest_push_context("Source test %u, destination test %u", i, j);
7097 hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1,
7098 tests[i].usage, D3DFMT_A8R8G8B8, tests[i].pool, &src_2d);
7099 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7100 hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1,
7101 tests[j].usage, D3DFMT_A8R8G8B8, tests[j].pool, &dst_2d);
7102 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7104 hr = IDirect3DTexture8_LockRect(src_2d, 0, &locked_rect, NULL, 0);
7105 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7106 *((DWORD *)locked_rect.pBits) = 0x11223344;
7107 hr = IDirect3DTexture8_UnlockRect(src_2d, 0);
7108 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7110 hr = IDirect3DTexture8_LockRect(dst_2d, 0, &locked_rect, NULL, 0);
7111 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7112 *((DWORD *)locked_rect.pBits) = 0x44332211;
7113 hr = IDirect3DTexture8_UnlockRect(dst_2d, 0);
7114 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7116 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src_2d,
7117 (IDirect3DBaseTexture8 *)dst_2d);
7118 if (tests[i].pool == D3DPOOL_SYSTEMMEM && tests[j].pool == D3DPOOL_DEFAULT)
7120 expect_colour = 0x11223344;
7121 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7123 else
7125 expect_colour = 0x44332211;
7126 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
7129 hr = IDirect3DTexture8_LockRect(dst_2d, 0, &locked_rect, NULL, 0);
7130 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7131 colour = *((DWORD *)locked_rect.pBits);
7132 ok(colour == expect_colour, "Expected colour %08x, got %08x.\n", expect_colour, colour);
7133 hr = IDirect3DTexture8_UnlockRect(dst_2d, 0);
7134 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7136 IDirect3DTexture8_Release(src_2d);
7137 IDirect3DTexture8_Release(dst_2d);
7139 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
7140 continue;
7142 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1,
7143 tests[i].usage, D3DFMT_A8R8G8B8, tests[i].pool, &src_3d);
7144 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7145 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1,
7146 tests[j].usage, D3DFMT_A8R8G8B8, tests[j].pool, &dst_3d);
7147 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7149 hr = IDirect3DVolumeTexture8_LockBox(src_3d, 0, &locked_box, NULL, 0);
7150 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7151 *((DWORD *)locked_box.pBits) = 0x11223344;
7152 hr = IDirect3DVolumeTexture8_UnlockBox(src_3d, 0);
7153 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7155 hr = IDirect3DVolumeTexture8_LockBox(dst_3d, 0, &locked_box, NULL, 0);
7156 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7157 *((DWORD *)locked_box.pBits) = 0x44332211;
7158 hr = IDirect3DVolumeTexture8_UnlockBox(dst_3d, 0);
7159 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7161 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src_3d,
7162 (IDirect3DBaseTexture8 *)dst_3d);
7163 if (tests[i].pool == D3DPOOL_SYSTEMMEM && tests[j].pool == D3DPOOL_DEFAULT)
7165 expect_colour = 0x11223344;
7166 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7168 else
7170 expect_colour = 0x44332211;
7171 ok(hr == D3DERR_INVALIDCALL, "Got hr %#lx.\n", hr);
7174 hr = IDirect3DVolumeTexture8_LockBox(dst_3d, 0, &locked_box, NULL, 0);
7175 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7176 colour = *((DWORD *)locked_box.pBits);
7177 ok(colour == expect_colour, "Expected colour %08x, got %08x.\n", expect_colour, colour);
7178 hr = IDirect3DVolumeTexture8_UnlockBox(dst_3d, 0);
7179 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7181 IDirect3DVolumeTexture8_Release(src_3d);
7182 IDirect3DVolumeTexture8_Release(dst_3d);
7184 winetest_pop_context();
7188 refcount = IDirect3DDevice8_Release(device);
7189 ok(!refcount, "Device has %lu references left.\n", refcount);
7190 IDirect3D8_Release(d3d8);
7191 DestroyWindow(window);
7194 static void test_update_volumetexture(void)
7196 D3DADAPTER_IDENTIFIER8 identifier;
7197 IDirect3DDevice8 *device;
7198 IDirect3D8 *d3d8;
7199 HWND window;
7200 HRESULT hr;
7201 IDirect3DVolumeTexture8 *src, *dst;
7202 unsigned int i;
7203 ULONG refcount;
7204 D3DCAPS8 caps;
7205 BOOL is_warp;
7207 static const struct
7209 UINT src_size, dst_size;
7210 UINT src_lvl, dst_lvl;
7211 D3DFORMAT src_fmt, dst_fmt;
7213 tests[] =
7215 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7216 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7217 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7218 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7219 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
7220 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
7221 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
7222 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
7225 window = create_window();
7226 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7227 ok(!!d3d8, "Failed to create a D3D object.\n");
7228 hr = IDirect3D8_GetAdapterIdentifier(d3d8, D3DADAPTER_DEFAULT, 0, &identifier);
7229 ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#lx.\n", hr);
7230 is_warp = adapter_is_warp(&identifier);
7231 if (!(device = create_device(d3d8, window, NULL)))
7233 skip("Failed to create a D3D device, skipping tests.\n");
7234 IDirect3D8_Release(d3d8);
7235 DestroyWindow(window);
7236 return;
7239 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7240 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
7241 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP) || !(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
7243 skip("Mipmapped volume maps not supported.\n");
7244 goto out;
7247 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7249 hr = IDirect3DDevice8_CreateVolumeTexture(device,
7250 tests[i].src_size, tests[i].src_size, tests[i].src_size,
7251 tests[i].src_lvl, 0, tests[i].src_fmt, D3DPOOL_SYSTEMMEM, &src);
7252 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#lx, case %u.\n", hr, i);
7253 hr = IDirect3DDevice8_CreateVolumeTexture(device,
7254 tests[i].dst_size, tests[i].dst_size, tests[i].dst_size,
7255 tests[i].dst_lvl, 0, tests[i].dst_fmt, D3DPOOL_DEFAULT, &dst);
7256 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#lx, case %u.\n", hr, i);
7258 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src, (IDirect3DBaseTexture8 *)dst);
7259 todo_wine_if (FAILED(hr))
7260 ok(SUCCEEDED(hr) || (is_warp && (i == 6 || i == 7)), /* Fails with Win10 WARP driver */
7261 "Failed to update texture, hr %#lx, case %u.\n", hr, i);
7263 IDirect3DVolumeTexture8_Release(src);
7264 IDirect3DVolumeTexture8_Release(dst);
7267 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
7268 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
7269 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
7270 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
7271 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
7273 * I'm not adding tests for this behavior until an application needs it. */
7275 out:
7276 refcount = IDirect3DDevice8_Release(device);
7277 ok(!refcount, "Device has %lu references left.\n", refcount);
7278 IDirect3D8_Release(d3d8);
7279 DestroyWindow(window);
7282 static void test_create_rt_ds_fail(void)
7284 IDirect3DDevice8 *device;
7285 HWND window;
7286 HRESULT hr;
7287 ULONG refcount;
7288 IDirect3D8 *d3d8;
7289 IDirect3DSurface8 *surface;
7291 window = create_window();
7292 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7293 ok(!!d3d8, "Failed to create a D3D object.\n");
7294 if (!(device = create_device(d3d8, window, NULL)))
7296 skip("Failed to create a D3D device, skipping tests.\n");
7297 IDirect3D8_Release(d3d8);
7298 DestroyWindow(window);
7299 return;
7302 /* Output pointer == NULL segfaults on Windows. */
7304 surface = (IDirect3DSurface8 *)0xdeadbeef;
7305 hr = IDirect3DDevice8_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
7306 D3DMULTISAMPLE_NONE, FALSE, &surface);
7307 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#lx.\n", hr);
7308 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
7309 if (SUCCEEDED(hr))
7310 IDirect3DSurface8_Release(surface);
7312 surface = (IDirect3DSurface8 *)0xdeadbeef;
7313 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
7314 D3DMULTISAMPLE_NONE, &surface);
7315 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#lx.\n", hr);
7316 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
7317 if (SUCCEEDED(hr))
7318 IDirect3DSurface8_Release(surface);
7320 refcount = IDirect3DDevice8_Release(device);
7321 ok(!refcount, "Device has %lu references left.\n", refcount);
7322 IDirect3D8_Release(d3d8);
7323 DestroyWindow(window);
7326 static void test_volume_blocks(void)
7328 IDirect3DDevice8 *device;
7329 IDirect3D8 *d3d8;
7330 UINT refcount;
7331 HWND window;
7332 HRESULT hr;
7333 D3DCAPS8 caps;
7334 IDirect3DVolumeTexture8 *texture;
7335 unsigned int w, h, d, i, j;
7336 static const struct
7338 D3DFORMAT fmt;
7339 const char *name;
7340 unsigned int block_width;
7341 unsigned int block_height;
7342 unsigned int block_depth;
7343 unsigned int block_size;
7344 unsigned int broken;
7345 BOOL create_size_checked, core_fmt;
7347 formats[] =
7349 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
7350 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
7351 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
7352 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
7353 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
7354 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
7355 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
7356 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
7357 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
7358 * which doesn't match the format spec. On newer Nvidia cards
7359 * it has the correct 4x4 block size.
7360 * ATI1N volume textures are only supported by AMD GPUs right
7361 * now and locking offsets seem just wrong. */
7362 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
7363 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
7364 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
7365 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
7367 static const struct
7369 D3DPOOL pool;
7370 const char *name;
7371 BOOL need_driver_support, need_runtime_support;
7373 create_tests[] =
7375 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7376 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7377 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
7378 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
7380 static const struct
7382 unsigned int x, y, z, x2, y2, z2;
7384 offset_tests[] =
7386 {0, 0, 0, 8, 8, 8},
7387 {0, 0, 3, 8, 8, 8},
7388 {0, 4, 0, 8, 8, 8},
7389 {0, 4, 3, 8, 8, 8},
7390 {4, 0, 0, 8, 8, 8},
7391 {4, 0, 3, 8, 8, 8},
7392 {4, 4, 0, 8, 8, 8},
7393 {4, 4, 3, 8, 8, 8},
7395 D3DBOX box;
7396 D3DLOCKED_BOX locked_box;
7397 BYTE *base;
7398 INT expected_row_pitch, expected_slice_pitch;
7399 BOOL support;
7400 BOOL pow2;
7401 unsigned int offset, expected_offset;
7403 window = create_window();
7404 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7405 ok(!!d3d8, "Failed to create a D3D object.\n");
7406 if (!(device = create_device(d3d8, window, NULL)))
7408 skip("Failed to create a D3D device, skipping tests.\n");
7409 IDirect3D8_Release(d3d8);
7410 DestroyWindow(window);
7411 return;
7413 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7414 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
7415 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
7417 for (i = 0; i < ARRAY_SIZE(formats); i++)
7419 hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7420 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
7421 support = SUCCEEDED(hr);
7423 /* Test creation restrictions */
7424 for (w = 1; w <= 8; w++)
7426 for (h = 1; h <= 8; h++)
7428 for (d = 1; d <= 8; d++)
7430 HRESULT expect_hr;
7431 BOOL size_is_pow2;
7432 BOOL block_aligned = TRUE;
7434 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
7435 block_aligned = FALSE;
7437 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
7439 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
7441 BOOL may_succeed = FALSE;
7443 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
7444 expect_hr = D3DERR_INVALIDCALL;
7445 else if (formats[i].create_size_checked && !block_aligned)
7446 expect_hr = D3DERR_INVALIDCALL;
7447 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
7448 expect_hr = D3DERR_INVALIDCALL;
7449 else if (create_tests[j].need_driver_support && !support)
7450 expect_hr = D3DERR_INVALIDCALL;
7451 else
7452 expect_hr = D3D_OK;
7454 texture = (IDirect3DVolumeTexture8 *)0xdeadbeef;
7455 hr = IDirect3DDevice8_CreateVolumeTexture(device, w, h, d, 1, 0,
7456 formats[i].fmt, create_tests[j].pool, &texture);
7458 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
7459 * does not support it. Accept scratch creation of extension formats on
7460 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
7461 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
7462 * support it. */
7463 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
7464 may_succeed = TRUE;
7466 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
7467 "Got unexpected hr %#lx for format %s, pool %s, size %ux%ux%u.\n",
7468 hr, formats[i].name, create_tests[j].name, w, h, d);
7470 if (FAILED(hr))
7471 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
7472 else
7473 IDirect3DVolumeTexture8_Release(texture);
7479 if (!support && !formats[i].core_fmt)
7480 continue;
7482 hr = IDirect3DDevice8_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
7483 formats[i].fmt, D3DPOOL_SCRATCH, &texture);
7484 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#lx.\n", hr);
7486 /* Test lockrect offset */
7487 for (j = 0; j < ARRAY_SIZE(offset_tests); j++)
7489 unsigned int bytes_per_pixel;
7490 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
7492 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
7493 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7495 base = locked_box.pBits;
7496 if (formats[i].broken == 1)
7498 expected_row_pitch = bytes_per_pixel * 24;
7500 else if (formats[i].broken == 2)
7502 expected_row_pitch = 24;
7504 else
7506 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
7507 * formats[i].block_size;
7509 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
7510 locked_box.RowPitch, formats[i].name, expected_row_pitch);
7512 if (formats[i].broken)
7514 expected_slice_pitch = expected_row_pitch * 8;
7516 else
7518 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
7519 * expected_row_pitch;
7521 ok(locked_box.SlicePitch == expected_slice_pitch,
7522 "Got unexpected slice pitch %d for format %s, expected %d.\n",
7523 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
7525 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7526 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx, j %u.\n", hr, j);
7528 box.Left = offset_tests[j].x;
7529 box.Top = offset_tests[j].y;
7530 box.Front = offset_tests[j].z;
7531 box.Right = offset_tests[j].x2;
7532 box.Bottom = offset_tests[j].y2;
7533 box.Back = offset_tests[j].z2;
7534 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
7535 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#lx, j %u.\n", hr, j);
7537 offset = (BYTE *)locked_box.pBits - base;
7538 if (formats[i].broken == 1)
7540 expected_offset = box.Front * expected_slice_pitch
7541 + box.Top * expected_row_pitch
7542 + box.Left * bytes_per_pixel;
7544 else if (formats[i].broken == 2)
7546 expected_offset = box.Front * expected_slice_pitch
7547 + box.Top * expected_row_pitch
7548 + box.Left;
7550 else
7552 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
7553 + (box.Top / formats[i].block_height) * expected_row_pitch
7554 + (box.Left / formats[i].block_width) * formats[i].block_size;
7556 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
7557 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
7559 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7560 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7563 /* Test partial block locks */
7564 box.Front = 0;
7565 box.Back = 1;
7566 if (formats[i].block_width > 1)
7568 box.Left = formats[i].block_width >> 1;
7569 box.Top = 0;
7570 box.Right = formats[i].block_width;
7571 box.Bottom = formats[i].block_height;
7572 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
7573 ok(FAILED(hr) || broken(formats[i].broken),
7574 "Partial block lock succeeded, expected failure, format %s.\n",
7575 formats[i].name);
7576 if (SUCCEEDED(hr))
7578 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7579 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7582 box.Left = 0;
7583 box.Top = 0;
7584 box.Right = formats[i].block_width >> 1;
7585 box.Bottom = formats[i].block_height;
7586 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
7587 ok(FAILED(hr) || broken(formats[i].broken),
7588 "Partial block lock succeeded, expected failure, format %s.\n",
7589 formats[i].name);
7590 if (SUCCEEDED(hr))
7592 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7593 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7597 if (formats[i].block_height > 1)
7599 box.Left = 0;
7600 box.Top = formats[i].block_height >> 1;
7601 box.Right = formats[i].block_width;
7602 box.Bottom = formats[i].block_height;
7603 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
7604 ok(FAILED(hr) || broken(formats[i].broken),
7605 "Partial block lock succeeded, expected failure, format %s.\n",
7606 formats[i].name);
7607 if (SUCCEEDED(hr))
7609 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7610 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7613 box.Left = 0;
7614 box.Top = 0;
7615 box.Right = formats[i].block_width;
7616 box.Bottom = formats[i].block_height >> 1;
7617 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
7618 ok(FAILED(hr) || broken(formats[i].broken),
7619 "Partial block lock succeeded, expected failure, format %s.\n",
7620 formats[i].name);
7621 if (SUCCEEDED(hr))
7623 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7624 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7628 /* Test full block lock */
7629 box.Left = 0;
7630 box.Top = 0;
7631 box.Right = formats[i].block_width;
7632 box.Bottom = formats[i].block_height;
7633 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
7634 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#lx.\n", hr);
7635 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7636 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7638 IDirect3DVolumeTexture8_Release(texture);
7640 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
7641 * does not allocate surfaces smaller than the blocksize properly. */
7642 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
7644 hr = IDirect3DDevice8_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
7645 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture);
7647 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#lx.\n", hr);
7648 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, NULL, 0);
7649 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#lx.\n", hr);
7650 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
7651 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7653 box.Left = box.Top = box.Front = 0;
7654 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
7655 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
7656 box.Back = 1;
7657 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
7658 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#lx.\n", hr);
7659 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
7660 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7662 box.Right = formats[i].block_width;
7663 box.Bottom = formats[i].block_height;
7664 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
7665 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
7666 if (SUCCEEDED(hr))
7667 IDirect3DVolumeTexture8_UnlockBox(texture, 1);
7669 IDirect3DVolumeTexture8_Release(texture);
7673 refcount = IDirect3DDevice8_Release(device);
7674 ok(!refcount, "Device has %u references left.\n", refcount);
7675 IDirect3D8_Release(d3d8);
7676 DestroyWindow(window);
7679 static void test_lockbox_invalid(void)
7681 static const struct
7683 D3DBOX box;
7684 HRESULT result;
7686 test_data[] =
7688 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
7689 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
7690 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
7691 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
7692 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
7693 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
7694 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
7695 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
7696 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
7697 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
7698 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
7699 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
7700 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
7701 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
7703 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
7704 IDirect3DVolumeTexture8 *texture = NULL;
7705 D3DLOCKED_BOX locked_box;
7706 IDirect3DDevice8 *device;
7707 IDirect3D8 *d3d;
7708 unsigned int i;
7709 ULONG refcount;
7710 HWND window;
7711 BYTE *base;
7712 HRESULT hr;
7714 window = create_window();
7715 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7716 ok(!!d3d, "Failed to create a D3D object.\n");
7717 if (!(device = create_device(d3d, window, NULL)))
7719 skip("Failed to create a D3D device, skipping tests.\n");
7720 IDirect3D8_Release(d3d);
7721 DestroyWindow(window);
7722 return;
7725 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
7726 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
7727 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#lx.\n", hr);
7728 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
7729 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#lx.\n", hr);
7730 base = locked_box.pBits;
7731 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7732 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7734 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7736 unsigned int offset, expected_offset;
7737 const D3DBOX *box = &test_data[i].box;
7739 locked_box.pBits = (BYTE *)0xdeadbeef;
7740 locked_box.RowPitch = 0xdeadbeef;
7741 locked_box.SlicePitch = 0xdeadbeef;
7743 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, box, 0);
7744 /* Unlike surfaces, volumes properly check the box even in Windows XP */
7745 ok(hr == test_data[i].result,
7746 "Got unexpected hr %#lx with box [%u, %u, %u]->[%u, %u, %u], expected %#lx.\n",
7747 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
7748 test_data[i].result);
7749 if (FAILED(hr))
7750 continue;
7752 offset = (BYTE *)locked_box.pBits - base;
7753 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
7754 ok(offset == expected_offset,
7755 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
7756 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
7758 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7759 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7762 /* locked_box = NULL throws an exception on Windows */
7763 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
7764 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#lx.\n", hr);
7765 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
7766 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
7767 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7768 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7769 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7770 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
7772 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7773 ok(hr == D3D_OK, "Got unexpected hr %#lx for rect [%u, %u, %u]->[%u, %u, %u].\n",
7774 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7775 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7776 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
7777 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect [%u, %u, %u]->[%u, %u, %u].\n",
7778 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
7779 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
7780 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
7781 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx for rect [%u, %u, %u]->[%u, %u, %u].\n",
7782 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
7783 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
7784 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
7785 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#lx.\n", hr);
7787 IDirect3DVolumeTexture8_Release(texture);
7789 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 2, 1, D3DUSAGE_WRITEONLY,
7790 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
7791 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
7793 refcount = IDirect3DDevice8_Release(device);
7794 ok(!refcount, "Device has %lu references left.\n", refcount);
7795 IDirect3D8_Release(d3d);
7796 DestroyWindow(window);
7799 static void test_pixel_format(void)
7801 int format, test_format;
7802 PIXELFORMATDESCRIPTOR pfd;
7803 IDirect3D8 *d3d8 = NULL;
7804 IDirect3DDevice8 *device = NULL;
7805 HWND hwnd, hwnd2, hwnd3;
7806 HDC hdc, hdc2, hdc3;
7807 ULONG refcount;
7808 HMODULE gl;
7809 HRESULT hr;
7810 BOOL ret;
7812 static const float point[] = {0.0f, 0.0f, 0.0f};
7814 hwnd = create_window();
7815 ok(!!hwnd, "Failed to create window.\n");
7816 hwnd2 = create_window();
7817 ok(!!hwnd2, "Failed to create window.\n");
7819 hdc = GetDC(hwnd);
7820 ok(!!hdc, "Failed to get DC.\n");
7821 hdc2 = GetDC(hwnd2);
7822 ok(!!hdc2, "Failed to get DC.\n");
7824 gl = LoadLibraryA("opengl32.dll");
7825 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
7827 format = GetPixelFormat(hdc);
7828 ok(format == 0, "new window has pixel format %d\n", format);
7830 ZeroMemory(&pfd, sizeof(pfd));
7831 pfd.nSize = sizeof(pfd);
7832 pfd.nVersion = 1;
7833 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
7834 pfd.iPixelType = PFD_TYPE_RGBA;
7835 pfd.iLayerType = PFD_MAIN_PLANE;
7836 format = ChoosePixelFormat(hdc, &pfd);
7837 if (format <= 0)
7839 skip("no pixel format available\n");
7840 goto cleanup;
7843 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
7845 skip("failed to set pixel format\n");
7846 goto cleanup;
7849 if (!SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
7851 skip("failed to set pixel format on second window\n");
7852 goto cleanup;
7855 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7856 ok(!!d3d8, "Failed to create a D3D object.\n");
7858 test_format = GetPixelFormat(hdc);
7859 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7861 if (!(device = create_device(d3d8, hwnd, NULL)))
7863 skip("Failed to create device\n");
7864 goto cleanup;
7867 test_format = GetPixelFormat(hdc);
7868 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7870 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
7871 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#lx.\n", hr);
7873 test_format = GetPixelFormat(hdc);
7874 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7876 hr = IDirect3DDevice8_BeginScene(device);
7877 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
7879 test_format = GetPixelFormat(hdc);
7880 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7882 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
7883 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
7885 test_format = GetPixelFormat(hdc);
7886 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7888 hr = IDirect3DDevice8_EndScene(device);
7889 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
7891 test_format = GetPixelFormat(hdc);
7892 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7894 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7895 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
7897 test_format = GetPixelFormat(hdc);
7898 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7900 hr = IDirect3DDevice8_Present(device, NULL, NULL, hwnd2, NULL);
7901 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
7903 test_format = GetPixelFormat(hdc);
7904 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7906 test_format = GetPixelFormat(hdc2);
7907 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7909 refcount = IDirect3DDevice8_Release(device);
7910 ok(!refcount, "Device has %lu references left.\n", refcount);
7911 IDirect3D8_Release(d3d8);
7913 test_format = GetPixelFormat(hdc);
7914 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7916 test_format = GetPixelFormat(hdc2);
7917 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7919 /* Test that creating a device doesn't set a pixel format on a window which
7920 * never had one. */
7922 hwnd3 = create_window();
7923 hdc3 = GetDC(hwnd3);
7925 test_format = GetPixelFormat(hdc3);
7926 ok(!test_format, "Expected no format, got %d.\n", test_format);
7928 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
7929 ok(!!d3d8, "Failed to create a D3D object.\n");
7930 if (!(device = create_device(d3d8, hwnd3, NULL)))
7932 skip("Failed to create device\n");
7933 goto cleanup;
7936 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
7937 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7938 hr = IDirect3DDevice8_BeginScene(device);
7939 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7940 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
7941 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7942 hr = IDirect3DDevice8_EndScene(device);
7943 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7945 test_format = GetPixelFormat(hdc3);
7946 ok(!test_format, "Expected no format, got %d.\n", test_format);
7948 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7949 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7951 test_format = GetPixelFormat(hdc3);
7952 ok(!test_format, "Expected no format, got %d.\n", test_format);
7954 refcount = IDirect3DDevice8_Release(device);
7955 ok(!refcount, "Device has %lu references left.\n", refcount);
7956 IDirect3D8_Release(d3d8);
7958 test_format = GetPixelFormat(hdc3);
7959 ok(!test_format, "Expected no format, got %d.\n", test_format);
7961 ret = SetPixelFormat(hdc3, format, &pfd);
7962 ok(ret, "Failed to set pixel format %d.\n", format);
7964 test_format = GetPixelFormat(hdc3);
7965 ok(test_format == format, "Expected pixel format %d, got %d.\n", format, test_format);
7967 ReleaseDC(hwnd3, hdc3);
7968 DestroyWindow(hwnd3);
7970 cleanup:
7971 FreeLibrary(gl);
7972 ReleaseDC(hwnd2, hdc2);
7973 ReleaseDC(hwnd, hdc);
7974 DestroyWindow(hwnd2);
7975 DestroyWindow(hwnd);
7978 static void test_begin_end_state_block(void)
7980 DWORD stateblock, stateblock2;
7981 IDirect3DDevice8 *device;
7982 IDirect3D8 *d3d;
7983 ULONG refcount;
7984 DWORD value;
7985 HWND window;
7986 HRESULT hr;
7988 window = create_window();
7989 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7990 ok(!!d3d, "Failed to create a D3D object.\n");
7991 if (!(device = create_device(d3d, window, NULL)))
7993 skip("Failed to create a D3D device, skipping tests.\n");
7994 IDirect3D8_Release(d3d);
7995 DestroyWindow(window);
7996 return;
7999 hr = IDirect3DDevice8_BeginStateBlock(device);
8000 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8002 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
8003 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8005 stateblock = 0xdeadbeef;
8006 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
8007 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8008 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#lx.\n", stateblock);
8010 stateblock2 = 0xdeadbeef;
8011 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock2);
8012 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8013 ok(stateblock2 == 0xdeadbeef, "Got unexpected stateblock %#lx.\n", stateblock2);
8015 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_LIGHTING, &value);
8016 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8017 ok(value == TRUE, "Got unexpected value %#lx.\n", value);
8019 hr = IDirect3DDevice8_BeginStateBlock(device);
8020 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8022 hr = IDirect3DDevice8_BeginStateBlock(device);
8023 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8025 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
8026 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8028 hr = IDirect3DDevice8_CaptureStateBlock(device, stateblock);
8029 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8031 hr = IDirect3DDevice8_CreateStateBlock(device, D3DSBT_ALL, &stateblock2);
8032 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8034 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_LIGHTING, &value);
8035 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8036 ok(value == TRUE, "Got unexpected value %#lx.\n", value);
8038 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock2);
8039 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8041 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock2);
8042 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8044 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_LIGHTING, &value);
8045 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8046 ok(value == TRUE, "Got unexpected value %#lx.\n", value);
8048 refcount = IDirect3DDevice8_Release(device);
8049 ok(!refcount, "Device has %lu references left.\n", refcount);
8050 IDirect3D8_Release(d3d);
8051 DestroyWindow(window);
8054 static void test_shader_constant_apply(void)
8056 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
8057 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
8058 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
8059 DWORD vs_version, ps_version;
8060 IDirect3DDevice8 *device;
8061 DWORD stateblock;
8062 IDirect3D8 *d3d;
8063 ULONG refcount;
8064 D3DCAPS8 caps;
8065 float ret[4];
8066 HWND window;
8067 HRESULT hr;
8069 window = create_window();
8070 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8071 ok(!!d3d, "Failed to create a D3D object.\n");
8072 if (!(device = create_device(d3d, window, NULL)))
8074 skip("Failed to create a D3D device, skipping tests.\n");
8075 IDirect3D8_Release(d3d);
8076 DestroyWindow(window);
8077 return;
8080 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
8081 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
8082 vs_version = caps.VertexShaderVersion & 0xffff;
8083 ps_version = caps.PixelShaderVersion & 0xffff;
8085 if (vs_version)
8087 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, initial, 1);
8088 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#lx.\n", hr);
8089 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, initial, 1);
8090 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#lx.\n", hr);
8092 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
8093 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#lx.\n", hr);
8094 ok(!memcmp(ret, initial, sizeof(initial)),
8095 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8096 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8097 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
8098 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#lx.\n", hr);
8099 ok(!memcmp(ret, initial, sizeof(initial)),
8100 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8101 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8103 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, vs_const, 1);
8104 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#lx.\n", hr);
8106 if (ps_version)
8108 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, initial, 1);
8109 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#lx.\n", hr);
8110 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, initial, 1);
8111 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#lx.\n", hr);
8113 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
8114 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#lx.\n", hr);
8115 ok(!memcmp(ret, initial, sizeof(initial)),
8116 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8117 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8118 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
8119 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#lx.\n", hr);
8120 ok(!memcmp(ret, initial, sizeof(initial)),
8121 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8122 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8124 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, ps_const, 1);
8125 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#lx.\n", hr);
8128 hr = IDirect3DDevice8_BeginStateBlock(device);
8129 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#lx.\n", hr);
8131 if (vs_version)
8133 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, vs_const, 1);
8134 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#lx.\n", hr);
8136 if (ps_version)
8138 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, ps_const, 1);
8139 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#lx.\n", hr);
8142 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
8143 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#lx.\n", hr);
8145 if (vs_version)
8147 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
8148 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#lx.\n", hr);
8149 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
8150 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8151 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
8152 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
8153 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#lx.\n", hr);
8154 ok(!memcmp(ret, initial, sizeof(initial)),
8155 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8156 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8158 if (ps_version)
8160 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
8161 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#lx.\n", hr);
8162 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
8163 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8164 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
8165 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
8166 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#lx.\n", hr);
8167 ok(!memcmp(ret, initial, sizeof(initial)),
8168 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8169 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
8172 /* Apply doesn't overwrite constants that aren't explicitly set on the
8173 * source stateblock. */
8174 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
8175 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#lx.\n", hr);
8177 if (vs_version)
8179 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
8180 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#lx.\n", hr);
8181 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
8182 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8183 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
8184 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
8185 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#lx.\n", hr);
8186 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
8187 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8188 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
8190 if (ps_version)
8192 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
8193 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#lx.\n", hr);
8194 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
8195 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8196 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
8197 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
8198 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#lx.\n", hr);
8199 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
8200 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
8201 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
8204 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
8205 refcount = IDirect3DDevice8_Release(device);
8206 ok(!refcount, "Device has %lu references left.\n", refcount);
8207 IDirect3D8_Release(d3d);
8208 DestroyWindow(window);
8211 static void test_resource_type(void)
8213 IDirect3DDevice8 *device;
8214 IDirect3DSurface8 *surface;
8215 IDirect3DTexture8 *texture;
8216 IDirect3DCubeTexture8 *cube_texture;
8217 IDirect3DVolume8 *volume;
8218 IDirect3DVolumeTexture8 *volume_texture;
8219 D3DSURFACE_DESC surface_desc;
8220 D3DVOLUME_DESC volume_desc;
8221 D3DRESOURCETYPE type;
8222 IDirect3D8 *d3d;
8223 ULONG refcount;
8224 HWND window;
8225 HRESULT hr;
8226 D3DCAPS8 caps;
8228 window = create_window();
8229 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8230 ok(!!d3d, "Failed to create a D3D object.\n");
8231 if (!(device = create_device(d3d, window, NULL)))
8233 skip("Failed to create a D3D device, skipping tests.\n");
8234 IDirect3D8_Release(d3d);
8235 DestroyWindow(window);
8236 return;
8239 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
8240 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
8242 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_X8R8G8B8, &surface);
8243 ok(SUCCEEDED(hr), "Failed to create surface, hr %#lx.\n", hr);
8244 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
8245 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#lx.\n", hr);
8246 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8247 surface_desc.Type);
8248 IDirect3DSurface8_Release(surface);
8250 hr = IDirect3DDevice8_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
8251 D3DPOOL_SYSTEMMEM, &texture);
8252 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
8253 type = IDirect3DTexture8_GetType(texture);
8254 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
8256 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
8257 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
8258 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
8259 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#lx.\n", hr);
8260 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8261 surface_desc.Type);
8262 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
8263 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
8264 hr = IDirect3DTexture8_GetLevelDesc(texture, 0, &surface_desc);
8265 ok(SUCCEEDED(hr), "Failed to get level description, hr %#lx.\n", hr);
8266 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8267 surface_desc.Type);
8268 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
8269 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
8270 IDirect3DSurface8_Release(surface);
8272 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 2, &surface);
8273 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
8274 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
8275 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#lx.\n", hr);
8276 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8277 surface_desc.Type);
8278 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
8279 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
8280 hr = IDirect3DTexture8_GetLevelDesc(texture, 2, &surface_desc);
8281 ok(SUCCEEDED(hr), "Failed to get level description, hr %#lx.\n", hr);
8282 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8283 surface_desc.Type);
8284 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
8285 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
8286 IDirect3DSurface8_Release(surface);
8287 IDirect3DTexture8_Release(texture);
8289 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
8291 hr = IDirect3DDevice8_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
8292 D3DPOOL_SYSTEMMEM, &cube_texture);
8293 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#lx.\n", hr);
8294 type = IDirect3DCubeTexture8_GetType(cube_texture);
8295 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
8297 hr = IDirect3DCubeTexture8_GetCubeMapSurface(cube_texture,
8298 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
8299 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#lx.\n", hr);
8300 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
8301 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#lx.\n", hr);
8302 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8303 surface_desc.Type);
8304 hr = IDirect3DCubeTexture8_GetLevelDesc(cube_texture, 0, &surface_desc);
8305 ok(SUCCEEDED(hr), "Failed to get level description, hr %#lx.\n", hr);
8306 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
8307 surface_desc.Type);
8308 IDirect3DSurface8_Release(surface);
8309 IDirect3DCubeTexture8_Release(cube_texture);
8311 else
8312 skip("Cube maps not supported.\n");
8314 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
8316 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
8317 D3DPOOL_SYSTEMMEM, &volume_texture);
8318 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#lx.\n", hr);
8319 type = IDirect3DVolumeTexture8_GetType(volume_texture);
8320 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
8322 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 0, &volume);
8323 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#lx.\n", hr);
8324 /* IDirect3DVolume8 is not an IDirect3DResource8 and has no GetType method. */
8325 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
8326 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#lx.\n", hr);
8327 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8328 volume_desc.Type);
8329 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
8330 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
8331 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
8332 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 0, &volume_desc);
8333 ok(SUCCEEDED(hr), "Failed to get level description, hr %#lx.\n", hr);
8334 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8335 volume_desc.Type);
8336 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
8337 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
8338 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
8339 IDirect3DVolume8_Release(volume);
8341 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 2, &volume);
8342 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#lx.\n", hr);
8343 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
8344 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#lx.\n", hr);
8345 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8346 volume_desc.Type);
8347 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
8348 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
8349 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
8350 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 2, &volume_desc);
8351 ok(SUCCEEDED(hr), "Failed to get level description, hr %#lx.\n", hr);
8352 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
8353 volume_desc.Type);
8354 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
8355 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
8356 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
8357 IDirect3DVolume8_Release(volume);
8358 IDirect3DVolumeTexture8_Release(volume_texture);
8360 else
8361 skip("Mipmapped volume maps not supported.\n");
8363 refcount = IDirect3DDevice8_Release(device);
8364 ok(!refcount, "Device has %lu references left.\n", refcount);
8365 IDirect3D8_Release(d3d);
8366 DestroyWindow(window);
8369 static void test_mipmap_lock(void)
8371 IDirect3DDevice8 *device;
8372 IDirect3DSurface8 *surface, *surface2, *surface_dst, *surface_dst2;
8373 IDirect3DTexture8 *texture, *texture_dst;
8374 IDirect3D8 *d3d;
8375 ULONG refcount;
8376 HWND window;
8377 HRESULT hr;
8378 D3DLOCKED_RECT locked_rect;
8380 window = create_window();
8381 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8382 ok(!!d3d, "Failed to create a D3D object.\n");
8383 if (!(device = create_device(d3d, window, NULL)))
8385 skip("Failed to create a D3D device, skipping tests.\n");
8386 IDirect3D8_Release(d3d);
8387 DestroyWindow(window);
8388 return;
8391 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
8392 D3DPOOL_DEFAULT, &texture_dst);
8393 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
8394 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 0, &surface_dst);
8395 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
8396 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
8397 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
8399 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
8400 D3DPOOL_SYSTEMMEM, &texture);
8401 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
8402 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
8403 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
8404 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
8405 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#lx.\n", hr);
8407 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
8408 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
8409 hr = IDirect3DSurface8_LockRect(surface2, &locked_rect, NULL, 0);
8410 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#lx.\n", hr);
8411 hr = IDirect3DSurface8_UnlockRect(surface);
8412 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
8414 hr = IDirect3DDevice8_CopyRects(device, surface, NULL, 0, surface_dst, NULL);
8415 ok(SUCCEEDED(hr), "Failed to update surface, hr %#lx.\n", hr);
8416 hr = IDirect3DDevice8_CopyRects(device, surface2, NULL, 0, surface_dst2, NULL);
8417 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8419 /* Apparently there's no validation on the container. */
8420 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)texture,
8421 (IDirect3DBaseTexture8 *)texture_dst);
8422 ok(SUCCEEDED(hr), "Failed to update texture, hr %#lx.\n", hr);
8424 hr = IDirect3DSurface8_UnlockRect(surface2);
8425 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#lx.\n", hr);
8427 IDirect3DSurface8_Release(surface_dst2);
8428 IDirect3DSurface8_Release(surface_dst);
8429 IDirect3DSurface8_Release(surface2);
8430 IDirect3DSurface8_Release(surface);
8431 IDirect3DTexture8_Release(texture_dst);
8432 IDirect3DTexture8_Release(texture);
8434 refcount = IDirect3DDevice8_Release(device);
8435 ok(!refcount, "Device has %lu references left.\n", refcount);
8436 IDirect3D8_Release(d3d);
8437 DestroyWindow(window);
8440 static void test_writeonly_resource(void)
8442 IDirect3D8 *d3d;
8443 IDirect3DDevice8 *device;
8444 IDirect3DVertexBuffer8 *buffer;
8445 ULONG refcount;
8446 HWND window;
8447 HRESULT hr;
8448 BYTE *ptr;
8449 static const struct
8451 struct vec3 pos;
8453 quad[] =
8455 {{-1.0f, -1.0f, 0.0f}},
8456 {{-1.0f, 1.0f, 0.0f}},
8457 {{ 1.0f, -1.0f, 0.0f}},
8458 {{ 1.0f, 1.0f, 0.0f}}
8461 window = create_window();
8462 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8463 ok(!!d3d, "Failed to create a D3D object.\n");
8464 if (!(device = create_device(d3d, window, NULL)))
8466 skip("Failed to create a D3D device, skipping tests.\n");
8467 IDirect3D8_Release(d3d);
8468 DestroyWindow(window);
8469 return;
8472 hr = IDirect3DDevice8_CreateVertexBuffer(device, sizeof(quad),
8473 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer);
8474 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#lx.\n", hr);
8476 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
8477 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
8478 memcpy(ptr, quad, sizeof(quad));
8479 hr = IDirect3DVertexBuffer8_Unlock(buffer);
8480 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
8481 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*quad));
8482 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#lx.\n", hr);
8483 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
8484 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#lx.\n", hr);
8486 hr = IDirect3DDevice8_BeginScene(device);
8487 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
8488 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
8489 ok(SUCCEEDED(hr), "Failed to draw, hr %#lx.\n", hr);
8490 hr = IDirect3DDevice8_EndScene(device);
8491 ok(SUCCEEDED(hr), "Got hr %#lx.\n", hr);
8493 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, 0);
8494 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
8495 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8496 hr = IDirect3DVertexBuffer8_Unlock(buffer);
8497 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
8499 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
8500 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#lx.\n", hr);
8501 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
8502 hr = IDirect3DVertexBuffer8_Unlock(buffer);
8503 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#lx.\n", hr);
8505 refcount = IDirect3DVertexBuffer8_Release(buffer);
8506 ok(!refcount, "Vertex buffer has %lu references left.\n", refcount);
8507 refcount = IDirect3DDevice8_Release(device);
8508 ok(!refcount, "Device has %lu references left.\n", refcount);
8509 IDirect3D8_Release(d3d);
8510 DestroyWindow(window);
8513 static void test_lost_device(void)
8515 D3DADAPTER_IDENTIFIER8 identifier;
8516 struct device_desc device_desc;
8517 IDirect3DDevice8 *device;
8518 IDirect3D8 *d3d;
8519 ULONG refcount;
8520 HWND window;
8521 HRESULT hr;
8522 BOOL ret;
8524 window = create_window();
8525 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8526 ok(!!d3d, "Failed to create a D3D object.\n");
8527 hr = IDirect3D8_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
8528 ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#lx.\n", hr);
8529 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
8530 device_desc.device_window = window;
8531 device_desc.width = registry_mode.dmPelsWidth;
8532 device_desc.height = registry_mode.dmPelsHeight;
8533 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
8534 if (!(device = create_device(d3d, window, &device_desc)))
8536 skip("Failed to create a D3D device, skipping tests.\n");
8537 goto done;
8540 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8541 if (hr == D3DERR_DEVICELOST)
8543 win_skip("Broken TestCooperativeLevel(), skipping test.\n");
8544 IDirect3DDevice8_Release(device);
8545 goto done;
8547 if (adapter_is_warp(&identifier))
8549 win_skip("Windows 10 WARP crashes during this test.\n");
8550 IDirect3DDevice8_Release(device);
8551 goto done;
8554 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8555 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8556 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8558 ret = SetForegroundWindow(GetDesktopWindow());
8559 ok(ret, "Failed to set foreground window.\n");
8560 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8561 /* The device is not lost on Windows 10. */
8562 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
8563 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8564 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
8566 ret = ShowWindow(window, SW_RESTORE);
8567 ok(ret, "Failed to restore window.\n");
8568 ret = SetForegroundWindow(window);
8569 ok(ret, "Failed to set foreground window.\n");
8570 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8571 ok(hr == D3DERR_DEVICENOTRESET || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
8572 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8573 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
8575 hr = reset_device(device, &device_desc);
8576 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8577 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8578 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8579 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8580 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8582 device_desc.flags = 0;
8583 hr = reset_device(device, &device_desc);
8584 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8585 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8586 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8587 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8588 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8590 ret = SetForegroundWindow(GetDesktopWindow());
8591 ok(ret, "Failed to set foreground window.\n");
8592 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8593 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8594 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8595 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8597 ret = ShowWindow(window, SW_RESTORE);
8598 ok(ret, "Failed to restore window.\n");
8599 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8600 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8601 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8602 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8604 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
8605 hr = reset_device(device, &device_desc);
8606 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8607 hr = IDirect3DDevice8_TestCooperativeLevel(device);
8608 /* The device is not lost on Windows 10. */
8609 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
8610 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
8611 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
8613 ret = SetForegroundWindow(GetDesktopWindow());
8614 ok(ret, "Failed to set foreground window.\n");
8615 hr = reset_device(device, &device_desc);
8616 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#lx.\n", hr);
8617 ret = ShowWindow(window, SW_RESTORE);
8618 ok(ret, "Failed to restore window.\n");
8619 ret = SetForegroundWindow(window);
8620 ok(ret, "Failed to set foreground window.\n");
8621 hr = reset_device(device, &device_desc);
8622 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
8624 refcount = IDirect3DDevice8_Release(device);
8625 ok(!refcount, "Device has %lu references left.\n", refcount);
8626 done:
8627 IDirect3D8_Release(d3d);
8628 DestroyWindow(window);
8631 static void test_resource_priority(void)
8633 IDirect3DDevice8 *device;
8634 IDirect3DTexture8 *texture;
8635 IDirect3DVertexBuffer8 *buffer;
8636 IDirect3D8 *d3d;
8637 ULONG refcount;
8638 HWND window;
8639 HRESULT hr;
8640 static const struct
8642 D3DPOOL pool;
8643 const char *name;
8644 BOOL can_set_priority;
8646 test_data[] =
8648 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8649 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
8650 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8651 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
8653 unsigned int i;
8654 DWORD priority;
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, skipping tests.\n");
8662 IDirect3D8_Release(d3d);
8663 DestroyWindow(window);
8664 return;
8667 for (i = 0; i < ARRAY_SIZE(test_data); i++)
8669 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
8670 test_data[i].pool, &texture);
8671 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx, pool %s.\n", hr, test_data[i].name);
8673 priority = IDirect3DTexture8_GetPriority(texture);
8674 ok(priority == 0, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8675 priority = IDirect3DTexture8_SetPriority(texture, 1);
8676 ok(priority == 0, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8677 priority = IDirect3DTexture8_GetPriority(texture);
8678 if (test_data[i].can_set_priority)
8680 ok(priority == 1, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8681 priority = IDirect3DTexture8_SetPriority(texture, 0);
8682 ok(priority == 1, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8684 else
8685 ok(priority == 0, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8687 IDirect3DTexture8_Release(texture);
8689 if (test_data[i].pool != D3DPOOL_SCRATCH)
8691 hr = IDirect3DDevice8_CreateVertexBuffer(device, 256, 0, 0,
8692 test_data[i].pool, &buffer);
8693 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#lx, pool %s.\n", hr, test_data[i].name);
8695 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
8696 ok(priority == 0, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8697 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 1);
8698 ok(priority == 0, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8699 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
8700 if (test_data[i].can_set_priority)
8702 ok(priority == 1, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8703 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 0);
8704 ok(priority == 1, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8706 else
8707 ok(priority == 0, "Got unexpected priority %lu, pool %s.\n", priority, test_data[i].name);
8709 IDirect3DVertexBuffer8_Release(buffer);
8713 refcount = IDirect3DDevice8_Release(device);
8714 ok(!refcount, "Device has %lu references left.\n", refcount);
8715 IDirect3D8_Release(d3d);
8716 DestroyWindow(window);
8719 static void test_swapchain_parameters(void)
8721 IDirect3DSurface8 *backbuffer;
8722 IDirect3DDevice8 *device;
8723 HRESULT hr, expected_hr;
8724 IDirect3D8 *d3d;
8725 D3DCAPS8 caps;
8726 HWND window;
8727 unsigned int i, j;
8728 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0};
8729 static const struct
8731 BOOL windowed;
8732 UINT backbuffer_count;
8733 D3DSWAPEFFECT swap_effect;
8734 HRESULT hr;
8736 tests[] =
8738 /* Swap effect 0 is not allowed. */
8739 {TRUE, 1, 0, D3DERR_INVALIDCALL},
8740 {FALSE, 1, 0, D3DERR_INVALIDCALL},
8742 /* All (non-ex) swap effects are allowed in
8743 * windowed and fullscreen mode. */
8744 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
8745 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
8746 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
8747 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
8748 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
8750 /* Only one backbuffer in copy mode. Reset allows it for
8751 * some reason. */
8752 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
8753 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
8754 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
8755 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
8756 {TRUE, 0, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
8757 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
8758 {TRUE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
8759 {FALSE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
8761 /* Ok with the others, in fullscreen and windowed mode. */
8762 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
8763 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
8764 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
8765 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
8767 /* Invalid swapeffects. */
8768 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
8769 {FALSE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
8771 /* 3 is the highest allowed backbuffer count. */
8772 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
8773 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
8774 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
8775 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
8776 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
8779 window = create_window();
8780 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8781 ok(!!d3d, "Failed to create a D3D object.\n");
8782 if (!(device = create_device(d3d, window, NULL)))
8784 skip("Failed to create a D3D device, skipping tests.\n");
8785 IDirect3D8_Release(d3d);
8786 DestroyWindow(window);
8787 return;
8789 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
8790 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#lx.\n", hr);
8791 IDirect3DDevice8_Release(device);
8793 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
8794 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
8795 present_parameters_windowed.hDeviceWindow = window;
8796 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
8797 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
8798 present_parameters_windowed.Windowed = TRUE;
8799 present_parameters_windowed.BackBufferCount = 1;
8802 for (i = 0; i < ARRAY_SIZE(tests); ++i)
8804 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
8806 memset(&present_parameters, 0, sizeof(present_parameters));
8807 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
8808 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
8809 present_parameters.hDeviceWindow = NULL;
8810 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
8812 present_parameters.SwapEffect = tests[i].swap_effect;
8813 present_parameters.Windowed = tests[i].windowed;
8814 present_parameters.BackBufferCount = tests[i].backbuffer_count;
8816 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
8817 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
8818 ok(hr == tests[i].hr, "Expected hr %#lx, got %#lx, test %u.\n", tests[i].hr, hr, i);
8819 if (SUCCEEDED(hr))
8821 for (j = 0; j < bb_count; ++j)
8823 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8824 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#lx, test %u.\n", j, hr, i);
8825 IDirect3DSurface8_Release(backbuffer);
8827 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8828 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, test %u.\n", hr, i);
8830 IDirect3DDevice8_Release(device);
8833 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
8834 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
8835 ok(SUCCEEDED(hr), "Failed to create device, hr %#lx, test %u.\n", hr, i);
8837 memset(&present_parameters, 0, sizeof(present_parameters));
8838 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
8839 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
8840 present_parameters.hDeviceWindow = NULL;
8841 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
8843 present_parameters.SwapEffect = tests[i].swap_effect;
8844 present_parameters.Windowed = tests[i].windowed;
8845 present_parameters.BackBufferCount = tests[i].backbuffer_count;
8847 hr = IDirect3DDevice8_Reset(device, &present_parameters);
8848 ok(hr == tests[i].hr, "Expected hr %#lx, got %#lx, test %u.\n", tests[i].hr, hr, i);
8850 if (FAILED(hr))
8852 hr = IDirect3DDevice8_Reset(device, &present_parameters_windowed);
8853 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx, test %u.\n", hr, i);
8855 else
8857 for (j = 0; j < bb_count; ++j)
8859 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8860 todo_wine_if (j)
8861 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#lx, test %u.\n", j, hr, i);
8862 if (SUCCEEDED(hr))
8863 IDirect3DSurface8_Release(backbuffer);
8865 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8866 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, test %u.\n", hr, i);
8868 IDirect3DDevice8_Release(device);
8871 for (i = 0; i < 10; ++i)
8873 memset(&present_parameters, 0, sizeof(present_parameters));
8874 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
8875 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
8876 present_parameters.hDeviceWindow = window;
8877 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
8878 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
8879 present_parameters.Windowed = FALSE;
8880 present_parameters.BackBufferCount = 2;
8882 present_parameters.FullScreen_PresentationInterval = i;
8883 switch (present_parameters.FullScreen_PresentationInterval)
8885 case D3DPRESENT_INTERVAL_ONE:
8886 case D3DPRESENT_INTERVAL_TWO:
8887 case D3DPRESENT_INTERVAL_THREE:
8888 case D3DPRESENT_INTERVAL_FOUR:
8889 if (!(caps.PresentationIntervals & present_parameters.FullScreen_PresentationInterval))
8890 continue;
8891 /* Fall through */
8892 case D3DPRESENT_INTERVAL_DEFAULT:
8893 expected_hr = D3D_OK;
8894 break;
8895 default:
8896 expected_hr = D3DERR_INVALIDCALL;
8897 break;
8900 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
8901 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
8902 ok(hr == expected_hr, "Got unexpected hr %#lx, test %u.\n", hr, i);
8903 if (SUCCEEDED(hr))
8904 IDirect3DDevice8_Release(device);
8907 memset(&present_parameters, 0, sizeof(present_parameters));
8908 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
8909 present_parameters.Windowed = TRUE;
8910 present_parameters.BackBufferWidth = 0;
8911 present_parameters.BackBufferHeight = 0;
8912 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
8914 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8915 window, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
8916 &present_parameters, &device);
8918 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
8919 ok(!present_parameters.BackBufferWidth, "Got unexpected BackBufferWidth %u.\n", present_parameters.BackBufferWidth);
8920 ok(!present_parameters.BackBufferHeight, "Got unexpected BackBufferHeight %u,.\n", present_parameters.BackBufferHeight);
8921 ok(present_parameters.BackBufferFormat == D3DFMT_X8R8G8B8, "Got unexpected BackBufferFormat %#x.\n", present_parameters.BackBufferFormat);
8922 ok(present_parameters.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", present_parameters.BackBufferCount);
8923 ok(!present_parameters.MultiSampleType, "Got unexpected MultiSampleType %u.\n", present_parameters.MultiSampleType);
8924 ok(present_parameters.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", present_parameters.SwapEffect);
8925 ok(!present_parameters.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", present_parameters.hDeviceWindow);
8926 ok(present_parameters.Windowed, "Got unexpected Windowed %#x.\n", present_parameters.Windowed);
8927 ok(!present_parameters.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", present_parameters.EnableAutoDepthStencil);
8928 ok(!present_parameters.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", present_parameters.AutoDepthStencilFormat);
8929 ok(!present_parameters.Flags, "Got unexpected Flags %#lx.\n", present_parameters.Flags);
8930 ok(!present_parameters.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n", present_parameters.FullScreen_RefreshRateInHz);
8931 ok(!present_parameters.FullScreen_PresentationInterval, "Got unexpected FullScreen_PresentationInterval %#x.\n", present_parameters.FullScreen_PresentationInterval);
8933 IDirect3DDevice8_Release(device);
8934 IDirect3D8_Release(d3d);
8935 DestroyWindow(window);
8938 static void test_check_device_format(void)
8940 D3DDEVTYPE device_type;
8941 IDirect3D8 *d3d;
8942 HRESULT hr;
8944 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8945 ok(!!d3d, "Failed to create a D3D object.\n");
8947 for (device_type = D3DDEVTYPE_HAL; device_type <= D3DDEVTYPE_SW; ++device_type)
8949 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8950 0, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
8951 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, device type %#x.\n", hr, device_type);
8952 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8953 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
8954 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, device type %#x.\n", hr, device_type);
8955 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8956 0, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
8957 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, device type %#x.\n", hr, device_type);
8958 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
8959 0, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
8960 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx, device type %#x.\n", hr, device_type);
8963 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8,
8964 0, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
8965 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
8966 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8967 0, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
8968 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#lx.\n", hr);
8970 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8971 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
8972 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8973 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8974 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
8975 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8976 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8977 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
8978 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8980 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8981 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
8982 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8983 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8984 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
8985 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8986 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8987 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
8988 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
8990 hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT,
8991 D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_D32);
8992 ok(hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL /* Windows 10 */),
8993 "Got unexpected hr %#lx.\n", hr);
8995 hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT,
8996 D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DFMT_R5G6B5, D3DFMT_D32);
8997 ok(hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL /* Windows 10 */),
8998 "Got unexpected hr %#lx.\n", hr);
9000 IDirect3D8_Release(d3d);
9003 static void test_miptree_layout(void)
9005 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
9006 IDirect3DCubeTexture8 *texture_cube;
9007 IDirect3DTexture8 *texture_2d;
9008 IDirect3DDevice8 *device;
9009 D3DLOCKED_RECT map_desc;
9010 BYTE *base = NULL;
9011 IDirect3D8 *d3d;
9012 D3DCAPS8 caps;
9013 UINT refcount;
9014 HWND window;
9015 HRESULT hr;
9017 static const struct
9019 D3DFORMAT format;
9020 const char *name;
9022 formats[] =
9024 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
9025 {D3DFMT_A8, "D3DFMT_A8"},
9026 {D3DFMT_L8, "D3DFMT_L8"},
9027 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
9028 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
9030 static const struct
9032 D3DPOOL pool;
9033 const char *name;
9035 pools[] =
9037 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
9038 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
9039 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
9042 window = create_window();
9043 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9044 ok(!!d3d, "Failed to create a D3D object.\n");
9045 if (!(device = create_device(d3d, window, NULL)))
9047 skip("Failed to create a D3D device, skipping tests.\n");
9048 goto done;
9051 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
9052 ok(SUCCEEDED(hr), "Failed to get caps, hr %#lx.\n", hr);
9054 base_dimension = 257;
9055 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
9057 skip("Using power of two base dimension.\n");
9058 base_dimension = 256;
9061 for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx)
9063 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
9064 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
9066 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
9067 continue;
9070 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
9072 hr = IDirect3DDevice8_CreateTexture(device, base_dimension, base_dimension, 0, 0,
9073 formats[format_idx].format, pools[pool_idx].pool, &texture_2d);
9074 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#lx.\n",
9075 pools[pool_idx].name, formats[format_idx].name, hr);
9077 level_count = IDirect3DTexture8_GetLevelCount(texture_2d);
9078 for (i = 0, offset = 0; i < level_count; ++i)
9080 hr = IDirect3DTexture8_LockRect(texture_2d, i, &map_desc, NULL, 0);
9081 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#lx.\n",
9082 pools[pool_idx].name, formats[format_idx].name, i, hr);
9084 if (!i)
9085 base = map_desc.pBits;
9086 else
9087 ok(map_desc.pBits == base + offset,
9088 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
9089 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
9090 offset += (base_dimension >> i) * map_desc.Pitch;
9092 hr = IDirect3DTexture8_UnlockRect(texture_2d, i);
9093 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#lx.\n",
9094 pools[pool_idx].name, formats[format_idx].name, i, hr);
9097 IDirect3DTexture8_Release(texture_2d);
9100 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
9101 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
9103 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
9104 continue;
9107 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
9109 hr = IDirect3DDevice8_CreateCubeTexture(device, base_dimension, 0, 0,
9110 formats[format_idx].format, pools[pool_idx].pool, &texture_cube);
9111 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#lx.\n",
9112 pools[pool_idx].name, formats[format_idx].name, hr);
9114 level_count = IDirect3DCubeTexture8_GetLevelCount(texture_cube);
9115 for (i = 0, offset = 0; i < 6; ++i)
9117 for (j = 0; j < level_count; ++j)
9119 hr = IDirect3DCubeTexture8_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
9120 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#lx.\n",
9121 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
9123 if (!i && !j)
9124 base = map_desc.pBits;
9125 else
9126 ok(map_desc.pBits == base + offset,
9127 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
9128 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
9129 offset += (base_dimension >> j) * map_desc.Pitch;
9131 hr = IDirect3DCubeTexture8_UnlockRect(texture_cube, i, j);
9132 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#lx.\n",
9133 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
9135 offset = (offset + 15) & ~15;
9138 IDirect3DCubeTexture8_Release(texture_cube);
9142 refcount = IDirect3DDevice8_Release(device);
9143 ok(!refcount, "Device has %u references left.\n", refcount);
9144 done:
9145 IDirect3D8_Release(d3d);
9146 DestroyWindow(window);
9149 static void test_render_target_device_mismatch(void)
9151 IDirect3DDevice8 *device, *device2;
9152 IDirect3DSurface8 *surface, *rt;
9153 IDirect3D8 *d3d;
9154 UINT refcount;
9155 HWND window;
9156 HRESULT hr;
9158 window = create_window();
9159 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9160 ok(!!d3d, "Failed to create a D3D object.\n");
9161 if (!(device = create_device(d3d, window, NULL)))
9163 skip("Failed to create a D3D device.\n");
9164 IDirect3D8_Release(d3d);
9165 DestroyWindow(window);
9166 return;
9169 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
9170 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9172 device2 = create_device(d3d, window, NULL);
9173 ok(!!device2, "Failed to create a D3D device.\n");
9175 hr = IDirect3DDevice8_CreateRenderTarget(device2, 640, 480,
9176 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &surface);
9177 ok(SUCCEEDED(hr), "Failed to create render target, hr %#lx.\n", hr);
9179 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
9180 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9182 IDirect3DSurface8_Release(surface);
9184 hr = IDirect3DDevice8_GetRenderTarget(device2, &surface);
9185 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9187 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
9188 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9190 IDirect3DSurface8_Release(surface);
9192 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
9193 ok(SUCCEEDED(hr), "Failed to get render target, hr %#lx.\n", hr);
9194 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
9195 IDirect3DSurface8_Release(surface);
9196 IDirect3DSurface8_Release(rt);
9198 refcount = IDirect3DDevice8_Release(device);
9199 ok(!refcount, "Device has %u references left.\n", refcount);
9200 refcount = IDirect3DDevice8_Release(device2);
9201 ok(!refcount, "Device has %u references left.\n", refcount);
9202 IDirect3D8_Release(d3d);
9203 DestroyWindow(window);
9206 static void test_format_unknown(void)
9208 IDirect3DDevice8 *device;
9209 IDirect3D8 *d3d;
9210 UINT refcount;
9211 HWND window;
9212 void *iface;
9213 HRESULT hr;
9215 window = create_window();
9216 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9217 ok(!!d3d, "Failed to create a D3D object.\n");
9218 if (!(device = create_device(d3d, window, NULL)))
9220 skip("Failed to create a D3D device.\n");
9221 IDirect3D8_Release(d3d);
9222 DestroyWindow(window);
9223 return;
9226 if (SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
9227 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_P8)))
9229 skip("P8 textures are supported, skipping some tests.\n");
9231 else
9233 iface = (void *)0xdeadbeef;
9234 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64,
9235 D3DFMT_P8, D3DMULTISAMPLE_NONE, FALSE, (IDirect3DSurface8 **)&iface);
9236 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9237 ok(!iface, "Got unexpected iface %p.\n", iface);
9239 iface = (void *)0xdeadbeef;
9240 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 64, 64,
9241 D3DFMT_P8, D3DMULTISAMPLE_NONE, (IDirect3DSurface8 **)&iface);
9242 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9243 ok(!iface, "Got unexpected iface %p.\n", iface);
9245 iface = (void *)0xdeadbeef;
9246 hr = IDirect3DDevice8_CreateTexture(device, 64, 64, 1, 0,
9247 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DTexture8 **)&iface);
9248 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9249 ok(!iface, "Got unexpected iface %p.\n", iface);
9251 iface = (void *)0xdeadbeef;
9252 hr = IDirect3DDevice8_CreateCubeTexture(device, 64, 1, 0,
9253 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DCubeTexture8 **)&iface);
9254 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9255 ok(!iface, "Got unexpected iface %p.\n", iface);
9257 iface = (void *)0xdeadbeef;
9258 hr = IDirect3DDevice8_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
9259 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture8 **)&iface);
9260 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9261 ok(!iface, "Got unexpected iface %p.\n", iface);
9264 iface = (void *)0xdeadbeef;
9265 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64,
9266 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, FALSE, (IDirect3DSurface8 **)&iface);
9267 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9268 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
9270 iface = (void *)0xdeadbeef;
9271 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 64, 64,
9272 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, (IDirect3DSurface8 **)&iface);
9273 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9274 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
9276 iface = (void *)0xdeadbeef;
9277 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64,
9278 D3DFMT_UNKNOWN, (IDirect3DSurface8 **)&iface);
9279 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9280 ok(!iface, "Got unexpected iface %p.\n", iface);
9282 iface = (void *)0xdeadbeef;
9283 hr = IDirect3DDevice8_CreateTexture(device, 64, 64, 1, 0,
9284 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture8 **)&iface);
9285 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9286 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
9288 iface = (void *)0xdeadbeef;
9289 hr = IDirect3DDevice8_CreateCubeTexture(device, 64, 1, 0,
9290 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture8 **)&iface);
9291 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9292 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
9294 iface = (void *)0xdeadbeef;
9295 hr = IDirect3DDevice8_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
9296 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture8 **)&iface);
9297 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9298 ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
9300 refcount = IDirect3DDevice8_Release(device);
9301 ok(!refcount, "Device has %u references left.\n", refcount);
9302 IDirect3D8_Release(d3d);
9303 DestroyWindow(window);
9306 static void test_destroyed_window(void)
9308 IDirect3DDevice8 *device;
9309 IDirect3D8 *d3d8;
9310 ULONG refcount;
9311 HWND window;
9312 HRESULT hr;
9314 /* No WS_VISIBLE. */
9315 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
9316 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9317 ok(!!window, "Failed to create a window.\n");
9319 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
9320 ok(!!d3d8, "Failed to create a D3D object.\n");
9321 device = create_device(d3d8, window, NULL);
9322 IDirect3D8_Release(d3d8);
9323 DestroyWindow(window);
9324 if (!device)
9326 skip("Failed to create a 3D device, skipping test.\n");
9327 return;
9330 hr = IDirect3DDevice8_BeginScene(device);
9331 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#lx.\n", hr);
9332 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
9333 ok(SUCCEEDED(hr), "Failed to clear, hr %#lx.\n", hr);
9334 hr = IDirect3DDevice8_EndScene(device);
9335 ok(SUCCEEDED(hr), "Failed to end scene, hr %#lx.\n", hr);
9336 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
9337 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9339 refcount = IDirect3DDevice8_Release(device);
9340 ok(!refcount, "Device has %lu references left.\n", refcount);
9343 static void test_lockable_backbuffer(void)
9345 D3DPRESENT_PARAMETERS present_parameters = {0};
9346 struct device_desc device_desc;
9347 IDirect3DSurface8 *surface;
9348 IDirect3DDevice8 *device;
9349 D3DLOCKED_RECT lockrect;
9350 IDirect3D8 *d3d;
9351 ULONG refcount;
9352 HWND window;
9353 HRESULT hr;
9355 window = create_window();
9356 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9357 ok(!!d3d, "Failed to create a D3D object.\n");
9359 if (!(device = create_device(d3d, window, NULL)))
9361 skip("Failed to create a D3D device, skipping tests.\n");
9362 IDirect3D8_Release(d3d);
9363 DestroyWindow(window);
9364 return;
9367 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
9368 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#lx.\n", hr);
9370 hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY);
9371 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#lx.\n", hr);
9373 IDirect3DSurface8_Release(surface);
9375 /* Reset with D3DPRESENTFLAG_LOCKABLE_BACKBUFFER. */
9376 present_parameters.BackBufferWidth = 640;
9377 present_parameters.BackBufferHeight = 480;
9378 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
9379 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
9380 present_parameters.hDeviceWindow = window;
9381 present_parameters.Windowed = TRUE;
9382 present_parameters.EnableAutoDepthStencil = TRUE;
9383 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
9384 present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
9386 hr = IDirect3DDevice8_Reset(device, &present_parameters);
9387 ok(SUCCEEDED(hr), "Failed to reset device, hr %#lx.\n", hr);
9389 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
9390 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#lx.\n", hr);
9392 hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY);
9393 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#lx.\n", hr);
9394 hr = IDirect3DSurface8_UnlockRect(surface);
9395 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#lx.\n", hr);
9397 IDirect3DSurface8_Release(surface);
9398 refcount = IDirect3DDevice8_Release(device);
9399 ok(!refcount, "Device has %lu references left.\n", refcount);
9401 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
9402 device_desc.width = 640;
9403 device_desc.height = 480;
9404 device_desc.device_window = window;
9405 device_desc.flags = CREATE_DEVICE_LOCKABLE_BACKBUFFER;
9407 device = create_device(d3d, window, &device_desc);
9408 ok(!!device, "Failed to create device.\n");
9410 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
9411 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#lx.\n", hr);
9413 hr = IDirect3DSurface8_LockRect(surface, &lockrect, NULL, D3DLOCK_READONLY);
9414 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#lx.\n", hr);
9415 hr = IDirect3DSurface8_UnlockRect(surface);
9416 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#lx.\n", hr);
9418 IDirect3DSurface8_Release(surface);
9419 refcount = IDirect3DDevice8_Release(device);
9420 ok(!refcount, "Device has %lu references left.\n", refcount);
9421 IDirect3D8_Release(d3d);
9422 DestroyWindow(window);
9425 static void test_clip_planes_limits(void)
9427 static const DWORD device_flags[] = {0, CREATE_DEVICE_SWVP_ONLY};
9428 IDirect3DDevice8 *device;
9429 struct device_desc desc;
9430 unsigned int i, j;
9431 IDirect3D8 *d3d;
9432 ULONG refcount;
9433 float plane[4];
9434 D3DCAPS8 caps;
9435 DWORD state;
9436 HWND window;
9437 HRESULT hr;
9439 window = create_window();
9440 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9441 ok(!!d3d, "Failed to create a D3D object.\n");
9443 for (i = 0; i < ARRAY_SIZE(device_flags); ++i)
9445 desc.adapter_ordinal = D3DADAPTER_DEFAULT;
9446 desc.device_window = window;
9447 desc.width = 640;
9448 desc.height = 480;
9449 desc.flags = device_flags[i];
9450 if (!(device = create_device(d3d, window, &desc)))
9452 skip("Failed to create D3D device, flags %#lx.\n", desc.flags);
9453 continue;
9456 memset(&caps, 0, sizeof(caps));
9457 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
9458 ok(hr == D3D_OK, "Failed to get caps, hr %#lx.\n", hr);
9460 trace("Max user clip planes: %lu.\n", caps.MaxUserClipPlanes);
9462 for (j = 0; j < caps.MaxUserClipPlanes; ++j)
9464 memset(plane, 0xff, sizeof(plane));
9465 hr = IDirect3DDevice8_GetClipPlane(device, j, plane);
9466 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#lx.\n", j, hr);
9467 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
9468 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
9469 j, plane[0], plane[1], plane[2], plane[3]);
9472 plane[0] = 2.0f;
9473 plane[1] = 8.0f;
9474 plane[2] = 5.0f;
9475 for (j = 0; j < caps.MaxUserClipPlanes; ++j)
9477 plane[3] = j;
9478 hr = IDirect3DDevice8_SetClipPlane(device, j, plane);
9479 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#lx.\n", j, hr);
9481 for (j = 0; j < caps.MaxUserClipPlanes; ++j)
9483 memset(plane, 0xff, sizeof(plane));
9484 hr = IDirect3DDevice8_GetClipPlane(device, j, plane);
9485 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#lx.\n", j, hr);
9486 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == j,
9487 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
9488 j, plane[0], plane[1], plane[2], plane[3]);
9491 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0xffffffff);
9492 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9493 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
9494 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
9495 ok(state == 0xffffffff, "Got unexpected state %#lx.\n", state);
9496 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x80000000);
9497 ok(SUCCEEDED(hr), "Failed to set render state, hr %#lx.\n", hr);
9498 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
9499 ok(SUCCEEDED(hr), "Failed to get render state, hr %#lx.\n", hr);
9500 ok(state == 0x80000000, "Got unexpected state %#lx.\n", state);
9502 refcount = IDirect3DDevice8_Release(device);
9503 ok(!refcount, "Device has %lu references left.\n", refcount);
9506 IDirect3D8_Release(d3d);
9507 DestroyWindow(window);
9510 static void test_swapchain_multisample_reset(void)
9512 D3DPRESENT_PARAMETERS present_parameters;
9513 IDirect3DDevice8 *device;
9514 IDirect3D8 *d3d;
9515 ULONG refcount;
9516 HWND window;
9517 HRESULT hr;
9519 window = create_window();
9520 ok(!!window, "Failed to create a window.\n");
9521 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9522 ok(!!d3d, "Failed to create D3D object.\n");
9524 if (IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
9525 D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES) == D3DERR_NOTAVAILABLE)
9527 skip("Multisampling not supported for D3DFMT_A8R8G8B8.\n");
9528 IDirect3D8_Release(d3d);
9529 DestroyWindow(window);
9530 return;
9533 if (!(device = create_device(d3d, window, NULL)))
9535 skip("Failed to create 3D device.\n");
9536 IDirect3D8_Release(d3d);
9537 DestroyWindow(window);
9538 return;
9541 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
9542 ok(hr == D3D_OK, "Failed to clear, hr %#lx.\n", hr);
9544 memset(&present_parameters, 0, sizeof(present_parameters));
9545 present_parameters.BackBufferWidth = 640;
9546 present_parameters.BackBufferHeight = 480;
9547 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
9548 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
9549 present_parameters.hDeviceWindow = NULL;
9550 present_parameters.Windowed = TRUE;
9551 present_parameters.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
9552 hr = IDirect3DDevice8_Reset(device, &present_parameters);
9553 ok(hr == D3D_OK, "Failed to reset device, hr %#lx.\n", hr);
9555 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
9556 ok(hr == D3D_OK, "Failed to clear, hr %#lx.\n", hr);
9558 refcount = IDirect3DDevice8_Release(device);
9559 ok(!refcount, "Device has %lu references left.\n", refcount);
9560 IDirect3D8_Release(d3d);
9561 DestroyWindow(window);
9564 static void test_device_caps(void)
9566 unsigned int adapter_idx, adapter_count;
9567 struct device_desc device_desc;
9568 IDirect3DDevice8 *device;
9569 IDirect3D8 *d3d;
9570 ULONG refcount;
9571 D3DCAPS8 caps;
9572 HWND window;
9573 HRESULT hr;
9575 window = create_window();
9576 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9577 ok(!!d3d, "Failed to create a D3D object.\n");
9579 device_desc.device_window = window;
9580 device_desc.width = 640;
9581 device_desc.height = 480;
9582 device_desc.flags = 0;
9584 adapter_count = IDirect3D8_GetAdapterCount(d3d);
9585 for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
9587 /* Test IDirect3D8_GetDeviceCaps */
9588 hr = IDirect3D8_GetDeviceCaps(d3d, adapter_idx, D3DDEVTYPE_HAL, &caps);
9589 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Adapter %u: GetDeviceCaps failed, hr %#lx.\n",
9590 adapter_idx, hr);
9591 if (hr == D3DERR_NOTAVAILABLE)
9593 skip("Adapter %u: No Direct3D support, skipping test.\n", adapter_idx);
9594 break;
9596 ok(caps.AdapterOrdinal == adapter_idx, "Adapter %u: Got unexpected adapter ordinal %u.\n",
9597 adapter_idx, caps.AdapterOrdinal);
9599 /* Test IDirect3DDevice8_GetDeviceCaps */
9600 device_desc.adapter_ordinal = adapter_idx;
9601 device = create_device(d3d, window, &device_desc);
9602 if (!device)
9604 skip("Adapter %u: Failed to create a D3D device, skipping test.\n", adapter_idx);
9605 break;
9607 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
9608 ok(SUCCEEDED(hr), "Adapter %u: Failed to get caps, hr %#lx.\n", adapter_idx, hr);
9610 ok(caps.AdapterOrdinal == adapter_idx, "Adapter %u: Got unexpected adapter ordinal %u.\n",
9611 adapter_idx, caps.AdapterOrdinal);
9612 ok(!(caps.Caps & ~D3DCAPS_READ_SCANLINE),
9613 "Adapter %u: Caps field has unexpected flags %#lx.\n", adapter_idx, caps.Caps);
9614 ok(!(caps.Caps2 & ~(D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_CANRENDERWINDOWED
9615 | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_FULLSCREENGAMMA
9616 | D3DCAPS2_NO2DDURING3DSCENE | D3DCAPS2_RESERVED)),
9617 "Adapter %u: Caps2 field has unexpected flags %#lx.\n", adapter_idx, caps.Caps2);
9618 /* Nvidia returns that 0x400 flag, which is probably Vista+
9619 * D3DCAPS3_DXVAHD from d3d9caps.h */
9620 /* AMD doesn't filter all the ddraw / d3d9 caps. Consider that behavior
9621 * broken. */
9622 ok(!(caps.Caps3 & ~(D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | D3DCAPS3_RESERVED | 0x400))
9623 || broken(!(caps.Caps3 & ~(D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | 0x80))),
9624 "Adapter %u: Caps3 field has unexpected flags %#lx.\n", adapter_idx, caps.Caps3);
9625 ok(!(caps.PrimitiveMiscCaps & ~(D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP
9626 | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW
9627 | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
9628 | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP
9629 | D3DPMISCCAPS_NULLREFERENCE))
9630 || broken(!(caps.PrimitiveMiscCaps & ~0x003fdff6)),
9631 "Adapter %u: PrimitiveMiscCaps field has unexpected flags %#lx.\n", adapter_idx,
9632 caps.PrimitiveMiscCaps);
9633 /* AMD includes an unknown 0x2 flag. */
9634 ok(!(caps.RasterCaps & ~(D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST
9635 | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_ANTIALIASEDGES
9636 | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR
9637 | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER
9638 | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE
9639 | D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE))
9640 || broken(!(caps.RasterCaps & ~0x0ff7f19b)),
9641 "Adapter %u: RasterCaps field has unexpected flags %#lx.\n", adapter_idx,
9642 caps.RasterCaps);
9643 ok(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
9644 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
9645 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
9646 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
9647 | D3DPBLENDCAPS_BOTHINVSRCALPHA)),
9648 "Adapter %u: SrcBlendCaps field has unexpected flags %#lx.\n", adapter_idx,
9649 caps.SrcBlendCaps);
9650 ok(!(caps.DestBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
9651 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
9652 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
9653 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
9654 | D3DPBLENDCAPS_BOTHINVSRCALPHA)),
9655 "Adapter %u: DestBlendCaps field has unexpected flags %#lx.\n", adapter_idx,
9656 caps.DestBlendCaps);
9657 ok(!(caps.TextureCaps & ~(D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2
9658 | D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_SQUAREONLY
9659 | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE
9660 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED
9661 | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP | D3DPTEXTURECAPS_MIPMAP
9662 | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP
9663 | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2)),
9664 "Adapter %u: TextureCaps field has unexpected flags %#lx.\n", adapter_idx,
9665 caps.TextureCaps);
9666 ok(!(caps.TextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
9667 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
9668 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
9669 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
9670 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC))
9671 || broken(!(caps.TextureFilterCaps & ~0x0703073f)),
9672 "Adapter %u: TextureFilterCaps field has unexpected flags %#lx.\n", adapter_idx,
9673 caps.TextureFilterCaps);
9674 ok(!(caps.CubeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
9675 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
9676 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
9677 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
9678 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC)),
9679 "Adapter %u: CubeTextureFilterCaps field has unexpected flags %#lx.\n", adapter_idx,
9680 caps.CubeTextureFilterCaps);
9681 ok(!(caps.VolumeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
9682 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MIPFPOINT
9683 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
9684 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFAFLATCUBIC
9685 | D3DPTFILTERCAPS_MAGFGAUSSIANCUBIC)),
9686 "Adapter %u: VolumeTextureFilterCaps field has unexpected flags %#lx.\n",
9687 adapter_idx, caps.VolumeTextureFilterCaps);
9688 ok(!(caps.LineCaps & ~(D3DLINECAPS_TEXTURE | D3DLINECAPS_ZTEST | D3DLINECAPS_BLEND
9689 | D3DLINECAPS_ALPHACMP | D3DLINECAPS_FOG)),
9690 "Adapter %u: LineCaps field has unexpected flags %#lx.\n", adapter_idx,
9691 caps.LineCaps);
9692 ok(!(caps.StencilCaps & ~(D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE
9693 | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT
9694 | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR)),
9695 "Adapter %u: StencilCaps field has unexpected flags %#lx.\n", adapter_idx,
9696 caps.StencilCaps);
9697 ok(!(caps.VertexProcessingCaps & ~(D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7
9698 | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER
9699 | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_NO_VSDT_UBYTE4)),
9700 "Adapter %u: VertexProcessingCaps field has unexpected flags %#lx.\n", adapter_idx,
9701 caps.VertexProcessingCaps);
9702 /* Both Nvidia and AMD give 10 here. */
9703 ok(caps.MaxActiveLights <= 10,
9704 "Adapter %u: MaxActiveLights field has unexpected value %lu.\n", adapter_idx,
9705 caps.MaxActiveLights);
9706 /* AMD gives 6, Nvidia returns 8. */
9707 ok(caps.MaxUserClipPlanes <= 8,
9708 "Adapter %u: MaxUserClipPlanes field has unexpected value %lu.\n", adapter_idx,
9709 caps.MaxUserClipPlanes);
9710 ok(caps.MaxVertexW == 0.0f || caps.MaxVertexW >= 1e10f,
9711 "Adapter %u: MaxVertexW field has unexpected value %.8e.\n", adapter_idx,
9712 caps.MaxVertexW);
9714 refcount = IDirect3DDevice8_Release(device);
9715 ok(!refcount, "Adapter %u: Device has %lu references left.\n", adapter_idx, refcount);
9717 IDirect3D8_Release(d3d);
9718 DestroyWindow(window);
9721 static void test_get_info(void)
9723 IDirect3DDevice8 *device;
9724 IDirect3D8 *d3d;
9725 BYTE info[1024];
9726 ULONG refcount;
9727 unsigned int i;
9728 HWND window;
9729 HRESULT hr;
9731 window = create_window();
9732 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9733 ok(!!d3d, "Failed to create a D3D object.\n");
9734 if (!(device = create_device(d3d, window, NULL)))
9736 skip("Failed to create a D3D device.\n");
9737 IDirect3D8_Release(d3d);
9738 DestroyWindow(window);
9739 return;
9742 /* As called by Chessmaster 9000 (bug 42118). */
9743 hr = IDirect3DDevice8_GetInfo(device, 4, info, 16);
9744 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr);
9746 for (i = 0; i < 256; ++i)
9748 hr = IDirect3DDevice8_GetInfo(device, i, info, sizeof(info));
9749 if (i <= 4)
9750 ok(hr == (i < 4 ? E_FAIL : S_FALSE), "info_id %u, unexpected hr %#lx.\n", i, hr);
9751 else
9752 ok(hr == E_FAIL || hr == S_FALSE, "info_id %u, unexpected hr %#lx.\n", i, hr);
9755 refcount = IDirect3DDevice8_Release(device);
9756 ok(!refcount, "Device has %lu references left.\n", refcount);
9757 IDirect3D8_Release(d3d);
9758 DestroyWindow(window);
9761 static void test_resource_access(void)
9763 IDirect3DSurface8 *backbuffer, *depth_stencil;
9764 D3DFORMAT colour_format, depth_format, format;
9765 BOOL depth_2d, depth_cube, depth_plain;
9766 D3DADAPTER_IDENTIFIER8 identifier;
9767 struct device_desc device_desc;
9768 D3DSURFACE_DESC surface_desc;
9769 BOOL skip_ati2n_once = FALSE;
9770 IDirect3DDevice8 *device;
9771 unsigned int i, j;
9772 IDirect3D8 *d3d;
9773 ULONG refcount;
9774 HWND window;
9775 HRESULT hr;
9776 BOOL warp;
9778 enum surface_type
9780 SURFACE_2D,
9781 SURFACE_CUBE,
9782 SURFACE_RT,
9783 SURFACE_DS,
9784 SURFACE_IMAGE,
9787 enum resource_format
9789 FORMAT_COLOUR,
9790 FORMAT_ATI2,
9791 FORMAT_DEPTH,
9794 static const struct
9796 D3DPOOL pool;
9797 enum resource_format format;
9798 DWORD usage;
9799 BOOL valid;
9801 tests[] =
9803 /* 0 */
9804 {D3DPOOL_DEFAULT, FORMAT_COLOUR, 0, TRUE},
9805 {D3DPOOL_DEFAULT, FORMAT_ATI2, 0, TRUE},
9806 {D3DPOOL_DEFAULT, FORMAT_DEPTH, 0, TRUE},
9807 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, TRUE},
9808 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
9809 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
9810 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, TRUE},
9811 /* 7 */
9812 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC, TRUE},
9813 {D3DPOOL_DEFAULT, FORMAT_ATI2, D3DUSAGE_DYNAMIC, TRUE},
9814 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC, TRUE},
9815 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
9816 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
9817 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
9818 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
9819 /* 14 */
9820 {D3DPOOL_MANAGED, FORMAT_COLOUR, 0, TRUE},
9821 {D3DPOOL_MANAGED, FORMAT_ATI2, 0, TRUE},
9822 {D3DPOOL_MANAGED, FORMAT_DEPTH, 0, FALSE},
9823 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
9824 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
9825 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
9826 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
9827 /* 21 */
9828 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, 0, TRUE},
9829 {D3DPOOL_SYSTEMMEM, FORMAT_ATI2, 0, TRUE},
9830 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, 0, FALSE},
9831 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
9832 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
9833 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
9834 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
9835 /* 28 */
9836 {D3DPOOL_SCRATCH, FORMAT_COLOUR, 0, TRUE},
9837 {D3DPOOL_SCRATCH, FORMAT_ATI2, 0, TRUE},
9838 {D3DPOOL_SCRATCH, FORMAT_DEPTH, 0, FALSE},
9839 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
9840 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
9841 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
9842 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
9844 static const struct
9846 const char *name;
9847 enum surface_type type;
9849 surface_types[] =
9851 {"2D", SURFACE_2D},
9852 {"CUBE", SURFACE_CUBE},
9853 {"RT", SURFACE_RT},
9854 {"DS", SURFACE_DS},
9855 {"IMAGE", SURFACE_IMAGE},
9858 window = create_window();
9859 d3d = Direct3DCreate8(D3D_SDK_VERSION);
9860 ok(!!d3d, "Failed to create a D3D object.\n");
9861 hr = IDirect3D8_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
9862 ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#lx.\n", hr);
9863 warp = adapter_is_warp(&identifier);
9865 device_desc.adapter_ordinal = D3DADAPTER_DEFAULT;
9866 device_desc.device_window = window;
9867 device_desc.width = 16;
9868 device_desc.height = 16;
9869 device_desc.flags = 0;
9870 if (!(device = create_device(d3d, window, &device_desc)))
9872 skip("Failed to create a D3D device.\n");
9873 IDirect3D8_Release(d3d);
9874 DestroyWindow(window);
9875 return;
9878 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9879 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
9880 hr = IDirect3DSurface8_GetDesc(backbuffer, &surface_desc);
9881 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
9882 colour_format = surface_desc.Format;
9884 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depth_stencil);
9885 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
9886 hr = IDirect3DSurface8_GetDesc(depth_stencil, &surface_desc);
9887 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
9888 depth_format = surface_desc.Format;
9890 depth_2d = SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
9891 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, depth_format));
9892 depth_cube = SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
9893 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, depth_format));
9894 depth_plain = SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
9895 D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, depth_format));
9897 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW);
9898 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
9900 for (i = 0; i < ARRAY_SIZE(surface_types); ++i)
9902 for (j = 0; j < ARRAY_SIZE(tests); ++j)
9904 IDirect3DCubeTexture8 *texture_cube;
9905 IDirect3DBaseTexture8 *texture;
9906 IDirect3DTexture8 *texture_2d;
9907 IDirect3DSurface8 *surface;
9908 HRESULT expected_hr;
9909 D3DLOCKED_RECT lr;
9911 if (tests[j].format == FORMAT_ATI2)
9912 format = MAKEFOURCC('A','T','I','2');
9913 else if (tests[j].format == FORMAT_DEPTH)
9914 format = depth_format;
9915 else
9916 format = colour_format;
9918 if (tests[j].format == FORMAT_ATI2 && FAILED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
9919 D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, format)))
9921 if (!skip_ati2n_once)
9923 skip("ATI2N texture not supported.\n");
9924 skip_ati2n_once = TRUE;
9926 continue;
9929 switch (surface_types[i].type)
9931 case SURFACE_2D:
9932 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1,
9933 tests[j].usage, format, tests[j].pool, &texture_2d);
9934 todo_wine_if(!tests[j].valid && tests[j].format == FORMAT_DEPTH && !tests[j].usage)
9935 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_2d)
9936 ? D3D_OK : D3DERR_INVALIDCALL),
9937 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9938 if (FAILED(hr))
9939 continue;
9941 hr = IDirect3DTexture8_GetSurfaceLevel(texture_2d, 0, &surface);
9942 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9943 IDirect3DTexture8_Release(texture_2d);
9944 break;
9946 case SURFACE_CUBE:
9947 hr = IDirect3DDevice8_CreateCubeTexture(device, 16, 1,
9948 tests[j].usage, format, tests[j].pool, &texture_cube);
9949 todo_wine_if(!tests[j].valid && tests[j].format == FORMAT_DEPTH && !tests[j].usage)
9950 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_cube)
9951 ? D3D_OK : D3DERR_INVALIDCALL),
9952 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9953 if (FAILED(hr))
9954 continue;
9956 hr = IDirect3DCubeTexture8_GetCubeMapSurface(texture_cube,
9957 D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
9958 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9959 IDirect3DCubeTexture8_Release(texture_cube);
9960 break;
9962 case SURFACE_RT:
9963 hr = IDirect3DDevice8_CreateRenderTarget(device, 16, 16, format,
9964 D3DMULTISAMPLE_NONE, tests[j].usage & D3DUSAGE_DYNAMIC, &surface);
9965 ok(hr == (tests[j].format == FORMAT_COLOUR ? D3D_OK : D3DERR_INVALIDCALL),
9966 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9967 if (FAILED(hr))
9968 continue;
9969 break;
9971 case SURFACE_DS:
9972 hr = IDirect3DDevice8_CreateDepthStencilSurface(device,
9973 16, 16, format, D3DMULTISAMPLE_NONE, &surface);
9974 todo_wine_if(tests[j].format == FORMAT_ATI2)
9975 ok(hr == (tests[j].format == FORMAT_DEPTH ? D3D_OK
9976 : tests[j].format == FORMAT_COLOUR ? D3DERR_INVALIDCALL : E_INVALIDARG)
9977 || (tests[j].format == FORMAT_ATI2 && hr == D3D_OK),
9978 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9979 if (FAILED(hr))
9980 continue;
9981 break;
9983 case SURFACE_IMAGE:
9984 hr = IDirect3DDevice8_CreateImageSurface(device, 16, 16, format, &surface);
9985 ok(hr == ((tests[j].format != FORMAT_DEPTH || depth_plain) ? D3D_OK : D3DERR_INVALIDCALL),
9986 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9987 if (FAILED(hr))
9988 continue;
9989 break;
9991 default:
9992 ok(0, "Invalid surface type %#x.\n", surface_types[i].type);
9993 continue;
9996 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
9997 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
9998 if (surface_types[i].type == SURFACE_RT)
10000 ok(surface_desc.Usage == D3DUSAGE_RENDERTARGET, "Test %s %u: Got unexpected usage %#lx.\n",
10001 surface_types[i].name, j, surface_desc.Usage);
10002 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
10003 surface_types[i].name, j, surface_desc.Pool);
10005 else if (surface_types[i].type == SURFACE_DS)
10007 ok(surface_desc.Usage == D3DUSAGE_DEPTHSTENCIL, "Test %s %u: Got unexpected usage %#lx.\n",
10008 surface_types[i].name, j, surface_desc.Usage);
10009 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
10010 surface_types[i].name, j, surface_desc.Pool);
10012 else if (surface_types[i].type == SURFACE_IMAGE)
10014 ok(!surface_desc.Usage, "Test %s %u: Got unexpected usage %#lx.\n",
10015 surface_types[i].name, j, surface_desc.Usage);
10016 ok(surface_desc.Pool == D3DPOOL_SYSTEMMEM, "Test %s %u: Got unexpected pool %#x.\n",
10017 surface_types[i].name, j, surface_desc.Pool);
10019 else
10021 ok(surface_desc.Usage == tests[j].usage, "Test %s %u: Got unexpected usage %#lx.\n",
10022 surface_types[i].name, j, surface_desc.Usage);
10023 ok(surface_desc.Pool == tests[j].pool, "Test %s %u: Got unexpected pool %#x.\n",
10024 surface_types[i].name, j, surface_desc.Pool);
10027 hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
10028 if (surface_desc.Pool != D3DPOOL_DEFAULT || surface_desc.Usage & D3DUSAGE_DYNAMIC
10029 || (surface_types[i].type == SURFACE_RT && tests[j].usage & D3DUSAGE_DYNAMIC)
10030 || surface_types[i].type == SURFACE_IMAGE
10031 || tests[j].format == FORMAT_ATI2)
10032 expected_hr = D3D_OK;
10033 else
10034 expected_hr = D3DERR_INVALIDCALL;
10035 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10036 hr = IDirect3DSurface8_UnlockRect(surface);
10037 todo_wine_if(expected_hr != D3D_OK && surface_types[i].type == SURFACE_2D)
10038 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10040 if (SUCCEEDED(IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DBaseTexture8, (void **)&texture)))
10042 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
10043 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10044 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
10045 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10046 IDirect3DBaseTexture8_Release(texture);
10049 hr = IDirect3DDevice8_SetRenderTarget(device, surface, depth_stencil);
10050 ok(hr == (surface_desc.Usage & D3DUSAGE_RENDERTARGET ? D3D_OK : D3DERR_INVALIDCALL),
10051 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10052 hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
10053 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10055 hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, surface);
10056 ok(hr == (surface_desc.Usage & D3DUSAGE_DEPTHSTENCIL ? D3D_OK : D3DERR_INVALIDCALL),
10057 "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10058 hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
10059 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#lx.\n", surface_types[i].name, j, hr);
10061 IDirect3DSurface8_Release(surface);
10065 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10067 IDirect3DVolumeTexture8 *texture;
10068 D3DVOLUME_DESC volume_desc;
10069 IDirect3DVolume8 *volume;
10070 HRESULT expected_hr;
10071 D3DLOCKED_BOX lb;
10073 if (tests[i].format == FORMAT_DEPTH)
10074 continue;
10076 if (tests[i].format == FORMAT_ATI2)
10077 format = MAKEFOURCC('A','T','I','2');
10078 else
10079 format = colour_format;
10081 if (tests[i].format == FORMAT_ATI2 && FAILED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
10082 D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_VOLUMETEXTURE, format)))
10084 if (!skip_ati2n_once)
10086 skip("ATI2N texture not supported.\n");
10087 skip_ati2n_once = TRUE;
10089 continue;
10092 hr = IDirect3DDevice8_CreateVolumeTexture(device, 16, 16, 1, 1,
10093 tests[i].usage, format, tests[i].pool, &texture);
10094 ok((hr == ((!(tests[i].usage & ~D3DUSAGE_DYNAMIC) && tests[i].format != FORMAT_ATI2)
10095 || (tests[i].pool == D3DPOOL_SCRATCH && !tests[i].usage)
10096 ? D3D_OK : D3DERR_INVALIDCALL))
10097 || (tests[i].format == FORMAT_ATI2 && (hr == D3D_OK || warp)),
10098 "Test %u: Got unexpected hr %#lx.\n", i, hr);
10099 if (FAILED(hr))
10100 continue;
10102 hr = IDirect3DVolumeTexture8_GetVolumeLevel(texture, 0, &volume);
10103 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10105 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
10106 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10107 ok(volume_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#lx.\n", i, volume_desc.Usage);
10108 ok(volume_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, volume_desc.Pool);
10110 hr = IDirect3DVolume8_LockBox(volume, &lb, NULL, 0);
10111 if (volume_desc.Pool != D3DPOOL_DEFAULT || volume_desc.Usage & D3DUSAGE_DYNAMIC)
10112 expected_hr = D3D_OK;
10113 else
10114 expected_hr = D3DERR_INVALIDCALL;
10115 ok(hr == expected_hr || (volume_desc.Pool == D3DPOOL_DEFAULT && hr == D3D_OK),
10116 "Test %u: Got unexpected hr %#lx.\n", i, hr);
10117 hr = IDirect3DVolume8_UnlockBox(volume);
10118 ok(hr == expected_hr || (volume_desc.Pool == D3DPOOL_DEFAULT && hr == D3D_OK),
10119 "Test %u: Got unexpected hr %#lx.\n", i, hr);
10121 hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
10122 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10123 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
10124 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10126 IDirect3DVolume8_Release(volume);
10127 IDirect3DVolumeTexture8_Release(texture);
10130 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10132 D3DINDEXBUFFER_DESC ib_desc;
10133 IDirect3DIndexBuffer8 *ib;
10134 BYTE *data;
10136 hr = IDirect3DDevice8_CreateIndexBuffer(device, 16, tests[i].usage,
10137 tests[i].format == FORMAT_COLOUR ? D3DFMT_INDEX32 : D3DFMT_INDEX16, tests[i].pool, &ib);
10138 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || (tests[i].usage & ~D3DUSAGE_DYNAMIC)
10139 ? D3DERR_INVALIDCALL : D3D_OK), "Test %u: Got unexpected hr %#lx.\n", i, hr);
10140 if (FAILED(hr))
10141 continue;
10143 hr = IDirect3DIndexBuffer8_GetDesc(ib, &ib_desc);
10144 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10145 ok(ib_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#lx.\n", i, ib_desc.Usage);
10146 ok(ib_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, ib_desc.Pool);
10148 hr = IDirect3DIndexBuffer8_Lock(ib, 0, 0, &data, 0);
10149 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10150 hr = IDirect3DIndexBuffer8_Unlock(ib);
10151 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10153 hr = IDirect3DDevice8_SetIndices(device, ib, 0);
10154 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10155 hr = IDirect3DDevice8_SetIndices(device, NULL, 0);
10156 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10158 IDirect3DIndexBuffer8_Release(ib);
10161 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10163 D3DVERTEXBUFFER_DESC vb_desc;
10164 IDirect3DVertexBuffer8 *vb;
10165 BYTE *data;
10167 hr = IDirect3DDevice8_CreateVertexBuffer(device, 16, tests[i].usage,
10168 tests[i].format == FORMAT_COLOUR ? 0 : D3DFVF_XYZRHW, tests[i].pool, &vb);
10169 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || (tests[i].usage & ~D3DUSAGE_DYNAMIC)
10170 ? D3DERR_INVALIDCALL : D3D_OK), "Test %u: Got unexpected hr %#lx.\n", i, hr);
10171 if (FAILED(hr))
10172 continue;
10174 hr = IDirect3DVertexBuffer8_GetDesc(vb, &vb_desc);
10175 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10176 ok(vb_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#lx.\n", i, vb_desc.Usage);
10177 ok(vb_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, vb_desc.Pool);
10179 hr = IDirect3DVertexBuffer8_Lock(vb, 0, 0, &data, 0);
10180 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10181 hr = IDirect3DVertexBuffer8_Unlock(vb);
10182 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10184 hr = IDirect3DDevice8_SetStreamSource(device, 0, vb, 16);
10185 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10186 hr = IDirect3DDevice8_SetStreamSource(device, 0, NULL, 0);
10187 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10189 IDirect3DVertexBuffer8_Release(vb);
10192 IDirect3DSurface8_Release(depth_stencil);
10193 IDirect3DSurface8_Release(backbuffer);
10194 refcount = IDirect3DDevice8_Release(device);
10195 ok(!refcount, "Device has %lu references left.\n", refcount);
10196 IDirect3D8_Release(d3d);
10197 DestroyWindow(window);
10200 static void test_multiply_transform(void)
10202 IDirect3DDevice8 *device;
10203 D3DMATRIX ret_mat;
10204 DWORD stateblock;
10205 IDirect3D8 *d3d;
10206 unsigned int i;
10207 ULONG refcount;
10208 HWND window;
10209 HRESULT hr;
10211 static const D3DTRANSFORMSTATETYPE tests[] =
10213 D3DTS_VIEW,
10214 D3DTS_PROJECTION,
10215 D3DTS_TEXTURE0,
10216 D3DTS_TEXTURE1,
10217 D3DTS_TEXTURE2,
10218 D3DTS_TEXTURE3,
10219 D3DTS_TEXTURE4,
10220 D3DTS_TEXTURE5,
10221 D3DTS_TEXTURE6,
10222 D3DTS_TEXTURE7,
10223 D3DTS_WORLDMATRIX(0),
10224 D3DTS_WORLDMATRIX(1),
10225 D3DTS_WORLDMATRIX(2),
10226 D3DTS_WORLDMATRIX(3),
10227 D3DTS_WORLDMATRIX(255),
10230 static const D3DMATRIX mat1 =
10232 1.0f, 0.0f, 0.0f, 0.0f,
10233 0.0f, 1.0f, 0.0f, 0.0f,
10234 0.0f, 0.0f, 1.0f, 0.0f,
10235 0.0f, 0.0f, 0.0f, 1.0f,
10236 }}},
10237 mat2 =
10239 2.0f, 0.0f, 0.0f, 0.0f,
10240 0.0f, 2.0f, 0.0f, 0.0f,
10241 0.0f, 0.0f, 2.0f, 0.0f,
10242 0.0f, 0.0f, 0.0f, 2.0f,
10243 }}};
10245 window = create_window();
10246 ok(!!window, "Failed to create a window.\n");
10247 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10248 ok(!!d3d, "Failed to create D3D object.\n");
10250 if (!(device = create_device(d3d, window, NULL)))
10252 skip("Failed to create 3D device.\n");
10253 IDirect3D8_Release(d3d);
10254 DestroyWindow(window);
10255 return;
10258 for (i = 0; i < ARRAY_SIZE(tests); ++i)
10260 hr = IDirect3DDevice8_GetTransform(device, tests[i], &ret_mat);
10261 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10262 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
10264 hr = IDirect3DDevice8_MultiplyTransform(device, tests[i], &mat2);
10265 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10267 hr = IDirect3DDevice8_GetTransform(device, tests[i], &ret_mat);
10268 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10269 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
10271 /* MultiplyTransform() goes directly into the primary stateblock. */
10273 hr = IDirect3DDevice8_SetTransform(device, tests[i], &mat1);
10274 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10276 hr = IDirect3DDevice8_BeginStateBlock(device);
10277 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10279 hr = IDirect3DDevice8_MultiplyTransform(device, tests[i], &mat2);
10280 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10282 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
10283 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10285 hr = IDirect3DDevice8_GetTransform(device, tests[i], &ret_mat);
10286 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10287 ok(!memcmp(&ret_mat, &mat2, sizeof(mat2)), "Test %u: Got unexpected transform matrix.\n", i);
10289 hr = IDirect3DDevice8_CaptureStateBlock(device, stateblock);
10290 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10292 hr = IDirect3DDevice8_SetTransform(device, tests[i], &mat1);
10293 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10295 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
10296 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10298 hr = IDirect3DDevice8_GetTransform(device, tests[i], &ret_mat);
10299 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#lx.\n", i, hr);
10300 ok(!memcmp(&ret_mat, &mat1, sizeof(mat1)), "Test %u: Got unexpected transform matrix.\n", i);
10302 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
10305 refcount = IDirect3DDevice8_Release(device);
10306 ok(!refcount, "Device has %lu references left.\n", refcount);
10307 IDirect3D8_Release(d3d);
10308 DestroyWindow(window);
10311 static void test_draw_primitive(void)
10313 static const struct
10315 float position[3];
10316 DWORD color;
10318 quad[] =
10320 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10321 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
10322 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
10323 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
10324 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
10326 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
10328 IDirect3DVertexBuffer8 *vertex_buffer, *current_vb;
10329 IDirect3DIndexBuffer8 *index_buffer, *current_ib;
10330 UINT stride, base_vertex_index;
10331 IDirect3DDevice8 *device;
10332 DWORD stateblock;
10333 IDirect3D8 *d3d;
10334 ULONG refcount;
10335 HWND window;
10336 HRESULT hr;
10337 BYTE *ptr;
10339 window = create_window();
10340 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10341 ok(!!d3d, "Failed to create a D3D object.\n");
10342 if (!(device = create_device(d3d, window, NULL)))
10344 skip("Failed to create a D3D device.\n");
10345 IDirect3D8_Release(d3d);
10346 DestroyWindow(window);
10347 return;
10350 hr = IDirect3DDevice8_CreateVertexBuffer(device, sizeof(quad), 0, 0,
10351 D3DPOOL_DEFAULT, &vertex_buffer);
10352 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#lx.\n", hr);
10353 hr = IDirect3DVertexBuffer8_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10354 ok(SUCCEEDED(hr), "Lock failed, hr %#lx.\n", hr);
10355 memcpy(ptr, quad, sizeof(quad));
10356 hr = IDirect3DVertexBuffer8_Unlock(vertex_buffer);
10357 ok(SUCCEEDED(hr), "Unlock failed, hr %#lx.\n", hr);
10358 hr = IDirect3DDevice8_SetStreamSource(device, 0, vertex_buffer, sizeof(*quad));
10359 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#lx.\n", hr);
10360 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10361 ok(SUCCEEDED(hr), "Got unexpected hr %#lx.\n", hr);
10363 hr = IDirect3DDevice8_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
10364 D3DPOOL_DEFAULT, &index_buffer);
10365 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#lx.\n", hr);
10366 hr = IDirect3DIndexBuffer8_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10367 ok(SUCCEEDED(hr), "Lock failed, hr %#lx.\n", hr);
10368 memcpy(ptr, indices, sizeof(indices));
10369 hr = IDirect3DIndexBuffer8_Unlock(index_buffer);
10370 ok(SUCCEEDED(hr), "Unlock failed, hr %#lx.\n", hr);
10372 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
10373 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#lx.\n", hr);
10375 hr = IDirect3DDevice8_BeginScene(device);
10376 ok(SUCCEEDED(hr), "BeginScene failed, hr %#lx.\n", hr);
10378 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
10379 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#lx.\n", hr);
10381 hr = IDirect3DDevice8_GetStreamSource(device, 0, &current_vb, &stride);
10382 ok(SUCCEEDED(hr), "GetStreamSource failed, hr %#lx.\n", hr);
10383 ok(current_vb == vertex_buffer, "Unexpected vb %p.\n", current_vb);
10384 ok(stride == sizeof(*quad), "Unexpected stride %u.\n", stride);
10385 IDirect3DVertexBuffer8_Release(current_vb);
10387 /* Crashes on r200, Windows XP with STATUS_INTEGER_DIVIDE_BY_ZERO. */
10388 if (0)
10390 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, quad, 0);
10391 ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr %#lx.\n", hr);
10393 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, quad, sizeof(*quad));
10394 ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr %#lx.\n", hr);
10396 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
10397 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#lx.\n", hr);
10399 hr = IDirect3DDevice8_GetStreamSource(device, 0, &current_vb, &stride);
10400 ok(SUCCEEDED(hr), "GetStreamSource failed, hr %#lx.\n", hr);
10401 ok(!current_vb, "Unexpected vb %p.\n", current_vb);
10402 ok(!stride, "Unexpected stride %u.\n", stride);
10404 /* NULL index buffer, NULL stream source. */
10405 hr = IDirect3DDevice8_SetIndices(device, NULL, 0);
10406 ok(SUCCEEDED(hr), "SetIndices failed, hr %#lx.\n", hr);
10407 hr = IDirect3DDevice8_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 4, 0, 2);
10408 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10410 /* Valid index buffer, NULL stream source. */
10411 hr = IDirect3DDevice8_SetIndices(device, index_buffer, 1);
10412 ok(SUCCEEDED(hr), "SetIndices failed, hr %#lx.\n", hr);
10413 hr = IDirect3DDevice8_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 4, 0, 2);
10414 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#lx.\n", hr);
10416 hr = IDirect3DDevice8_GetIndices(device, &current_ib, &base_vertex_index);
10417 ok(SUCCEEDED(hr), "GetIndices failed, hr %#lx.\n", hr);
10418 ok(current_ib == index_buffer, "Unexpected index buffer %p.\n", current_ib);
10419 ok(base_vertex_index == 1, "Unexpected base vertex index %u.\n", base_vertex_index);
10420 IDirect3DIndexBuffer8_Release(current_ib);
10422 /* Crashes on r200, Windows XP with STATUS_INTEGER_DIVIDE_BY_ZERO. */
10423 if (0)
10425 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 0,
10426 indices, D3DFMT_INDEX16, quad, 0);
10427 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#lx.\n", hr);
10428 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
10429 indices, D3DFMT_INDEX16, quad, 0);
10430 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#lx.\n", hr);
10433 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
10434 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
10435 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#lx.\n", hr);
10437 hr = IDirect3DDevice8_GetIndices(device, &current_ib, &base_vertex_index);
10438 ok(SUCCEEDED(hr), "GetIndices failed, hr %#lx.\n", hr);
10439 ok(!current_ib, "Unexpected index buffer %p.\n", current_ib);
10440 ok(!base_vertex_index, "Unexpected base vertex index %u.\n", base_vertex_index);
10442 /* Resetting of stream source and index buffer is not recorded in stateblocks. */
10444 hr = IDirect3DDevice8_SetStreamSource(device, 0, vertex_buffer, sizeof(*quad));
10445 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#lx.\n", hr);
10446 hr = IDirect3DDevice8_SetIndices(device, index_buffer, 1);
10447 ok(SUCCEEDED(hr), "SetIndices failed, hr %#lx.\n", hr);
10449 hr = IDirect3DDevice8_BeginStateBlock(device);
10450 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#lx.\n", hr);
10452 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
10453 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
10454 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#lx.\n", hr);
10456 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
10457 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#lx.\n", hr);
10459 hr = IDirect3DDevice8_GetStreamSource(device, 0, &current_vb, &stride);
10460 ok(SUCCEEDED(hr), "GetStreamSource failed, hr %#lx.\n", hr);
10461 ok(!current_vb, "Unexpected vb %p.\n", current_vb);
10462 ok(!stride, "Unexpected stride %u.\n", stride);
10463 hr = IDirect3DDevice8_GetIndices(device, &current_ib, &base_vertex_index);
10464 ok(SUCCEEDED(hr), "GetIndices failed, hr %#lx.\n", hr);
10465 ok(!current_ib, "Unexpected index buffer %p.\n", current_ib);
10466 ok(!base_vertex_index, "Unexpected base vertex index %u.\n", base_vertex_index);
10468 hr = IDirect3DDevice8_CaptureStateBlock(device, stateblock);
10469 ok(SUCCEEDED(hr), "Capture failed, hr %#lx.\n", hr);
10471 hr = IDirect3DDevice8_SetStreamSource(device, 0, vertex_buffer, sizeof(*quad));
10472 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#lx.\n", hr);
10473 hr = IDirect3DDevice8_SetIndices(device, index_buffer, 1);
10474 ok(SUCCEEDED(hr), "SetIndices failed, hr %#lx.\n", hr);
10476 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
10477 ok(SUCCEEDED(hr), "Apply failed, hr %#lx.\n", hr);
10479 hr = IDirect3DDevice8_GetStreamSource(device, 0, &current_vb, &stride);
10480 ok(SUCCEEDED(hr), "GetStreamSource failed, hr %#lx.\n", hr);
10481 ok(current_vb == vertex_buffer, "Unexpected vb %p.\n", current_vb);
10482 ok(stride == sizeof(*quad), "Unexpected stride %u.\n", stride);
10483 IDirect3DVertexBuffer8_Release(current_vb);
10484 hr = IDirect3DDevice8_GetIndices(device, &current_ib, &base_vertex_index);
10485 ok(SUCCEEDED(hr), "GetIndices failed, hr %#lx.\n", hr);
10486 ok(current_ib == index_buffer, "Unexpected index buffer %p.\n", current_ib);
10487 ok(base_vertex_index == 1, "Unexpected base vertex index %u.\n", base_vertex_index);
10488 IDirect3DIndexBuffer8_Release(current_ib);
10490 hr = IDirect3DDevice8_EndScene(device);
10491 ok(SUCCEEDED(hr), "EndScene failed, hr %#lx.\n", hr);
10493 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
10494 ok(SUCCEEDED(hr), "Present failed, hr %#lx.\n", hr);
10496 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
10497 IDirect3DVertexBuffer8_Release(vertex_buffer);
10498 IDirect3DIndexBuffer8_Release(index_buffer);
10499 refcount = IDirect3DDevice8_Release(device);
10500 ok(!refcount, "Device has %lu references left.\n", refcount);
10501 IDirect3D8_Release(d3d);
10502 DestroyWindow(window);
10505 static void test_get_display_mode(void)
10507 static const DWORD creation_flags[] = {0, CREATE_DEVICE_FULLSCREEN};
10508 unsigned int adapter_idx, adapter_count, mode_idx, test_idx;
10509 RECT previous_monitor_rect;
10510 unsigned int width, height;
10511 IDirect3DDevice8 *device;
10512 MONITORINFO monitor_info;
10513 struct device_desc desc;
10514 D3DDISPLAYMODE mode;
10515 HMONITOR monitor;
10516 IDirect3D8 *d3d;
10517 ULONG refcount;
10518 HWND window;
10519 HRESULT hr;
10520 BOOL ret;
10522 window = create_window();
10523 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10524 ok(!!d3d, "Failed to create a D3D object.\n");
10526 if (!(device = create_device(d3d, window, NULL)))
10528 skip("Failed to create a D3D device.\n");
10529 IDirect3D8_Release(d3d);
10530 DestroyWindow(window);
10531 return;
10534 hr = IDirect3DDevice8_GetDisplayMode(device, &mode);
10535 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10536 ok(mode.Format == D3DFMT_X8R8G8B8, "Unexpected format %#x.\n", mode.Format);
10537 hr = IDirect3D8_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &mode);
10538 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10539 ok(mode.Format == D3DFMT_X8R8G8B8, "Unexpected format %#x.\n", mode.Format);
10541 refcount = IDirect3DDevice8_Release(device);
10542 ok(!refcount, "Device has %lu references left.\n", refcount);
10544 desc.adapter_ordinal = D3DADAPTER_DEFAULT;
10545 desc.device_window = window;
10546 desc.width = 640;
10547 desc.height = 480;
10548 desc.flags = CREATE_DEVICE_FULLSCREEN;
10549 if (!(device = create_device(d3d, window, &desc)))
10551 skip("Failed to create a D3D device.\n");
10552 IDirect3D8_Release(d3d);
10553 DestroyWindow(window);
10554 return;
10557 hr = IDirect3DDevice8_GetDisplayMode(device, &mode);
10558 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10559 ok(mode.Width == 640, "Unexpected width %u.\n", mode.Width);
10560 ok(mode.Height == 480, "Unexpected width %u.\n", mode.Height);
10561 ok(mode.Format == D3DFMT_X8R8G8B8, "Unexpected format %#x.\n", mode.Format);
10562 hr = IDirect3D8_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &mode);
10563 ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
10564 ok(mode.Width == 640, "Unexpected width %u.\n", mode.Width);
10565 ok(mode.Height == 480, "Unexpected width %u.\n", mode.Height);
10566 ok(mode.Format == D3DFMT_X8R8G8B8, "Unexpected format %#x.\n", mode.Format);
10568 refcount = IDirect3DDevice8_Release(device);
10569 ok(!refcount, "Device has %lu references left.\n", refcount);
10570 DestroyWindow(window);
10572 /* D3D8 uses adapter indices to determine which adapter to use to get the display mode */
10573 adapter_count = IDirect3D8_GetAdapterCount(d3d);
10574 for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
10576 if (!adapter_idx)
10578 desc.width = 640;
10579 desc.height = 480;
10581 else
10583 /* Find a mode different than that of the previous adapter, so that tests can be sure
10584 * that they are comparing to the current adapter display mode */
10585 monitor = IDirect3D8_GetAdapterMonitor(d3d, adapter_idx - 1);
10586 ok(!!monitor, "Adapter %u: GetAdapterMonitor failed.\n", adapter_idx - 1);
10587 monitor_info.cbSize = sizeof(monitor_info);
10588 ret = GetMonitorInfoW(monitor, &monitor_info);
10589 ok(ret, "Adapter %u: GetMonitorInfoW failed, error %#lx.\n", adapter_idx - 1,
10590 GetLastError());
10591 previous_monitor_rect = monitor_info.rcMonitor;
10593 desc.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
10594 desc.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
10595 for (mode_idx = 0; SUCCEEDED(IDirect3D8_EnumAdapterModes(d3d, adapter_idx, mode_idx,
10596 &mode)); ++mode_idx)
10598 if (mode.Format != D3DFMT_X8R8G8B8)
10599 continue;
10600 if (mode.Width < 640 || mode.Height < 480)
10601 continue;
10602 if (mode.Width != desc.width && mode.Height != desc.height)
10603 break;
10605 ok(mode.Width != desc.width && mode.Height != desc.height,
10606 "Adapter %u: Failed to find a different mode than %ux%u.\n", adapter_idx,
10607 desc.width, desc.height);
10608 desc.width = mode.Width;
10609 desc.height = mode.Height;
10612 for (test_idx = 0; test_idx < ARRAY_SIZE(creation_flags); ++test_idx)
10614 window = create_window();
10615 desc.adapter_ordinal = adapter_idx;
10616 desc.device_window = window;
10617 desc.flags = creation_flags[test_idx];
10618 if (!(device = create_device(d3d, window, &desc)))
10620 skip("Adapter %u test %u: Failed to create a D3D device.\n", adapter_idx, test_idx);
10621 DestroyWindow(window);
10622 continue;
10625 monitor = IDirect3D8_GetAdapterMonitor(d3d, adapter_idx);
10626 ok(!!monitor, "Adapter %u test %u: GetAdapterMonitor failed.\n", adapter_idx, test_idx);
10627 monitor_info.cbSize = sizeof(monitor_info);
10628 ret = GetMonitorInfoW(monitor, &monitor_info);
10629 ok(ret, "Adapter %u test %u: GetMonitorInfoW failed, error %#lx.\n", adapter_idx,
10630 test_idx, GetLastError());
10631 width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
10632 height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
10634 if (adapter_idx)
10636 /* Move the device window to the previous monitor to test that the device window
10637 * position doesn't affect which adapter to use to get the display mode */
10638 ret = SetWindowPos(window, 0, previous_monitor_rect.left, previous_monitor_rect.top,
10639 0, 0, SWP_NOZORDER | SWP_NOSIZE);
10640 ok(ret, "Adapter %u test %u: SetWindowPos failed, error %#lx.\n", adapter_idx,
10641 test_idx, GetLastError());
10644 hr = IDirect3D8_GetAdapterDisplayMode(d3d, adapter_idx, &mode);
10645 ok(hr == D3D_OK, "Adapter %u test %u: GetAdapterDisplayMode failed, hr %#lx.\n",
10646 adapter_idx, test_idx, hr);
10647 ok(mode.Width == width, "Adapter %u test %u: Expect width %u, got %u.\n", adapter_idx,
10648 test_idx, width, mode.Width);
10649 ok(mode.Height == height, "Adapter %u test %u: Expect height %u, got %u.\n",
10650 adapter_idx, test_idx, height, mode.Height);
10652 hr = IDirect3DDevice8_GetDisplayMode(device, &mode);
10653 ok(hr == D3D_OK, "Adapter %u test %u: GetDisplayMode failed, hr %#lx.\n", adapter_idx,
10654 test_idx, hr);
10655 ok(mode.Width == width, "Adapter %u test %u: Expect width %u, got %u.\n", adapter_idx,
10656 test_idx, width, mode.Width);
10657 ok(mode.Height == height, "Adapter %u test %u: Expect height %u, got %u.\n",
10658 adapter_idx, test_idx, height, mode.Height);
10660 refcount = IDirect3DDevice8_Release(device);
10661 ok(!refcount, "Adapter %u test %u: Device has %lu references left.\n", adapter_idx,
10662 test_idx, refcount);
10663 DestroyWindow(window);
10667 IDirect3D8_Release(d3d);
10670 static void test_multi_adapter(void)
10672 unsigned int i, adapter_count, expected_adapter_count = 0;
10673 DISPLAY_DEVICEA display_device;
10674 MONITORINFOEXA monitor_info;
10675 DEVMODEA old_mode, mode;
10676 HMONITOR monitor;
10677 IDirect3D8 *d3d;
10678 LONG ret;
10680 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10681 ok(!!d3d, "Failed to create a D3D object.\n");
10683 display_device.cb = sizeof(display_device);
10684 for (i = 0; EnumDisplayDevicesA(NULL, i, &display_device, 0); ++i)
10686 if (display_device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
10687 ++expected_adapter_count;
10690 adapter_count = IDirect3D8_GetAdapterCount(d3d);
10691 ok(adapter_count == expected_adapter_count, "Got unexpected adapter count %u, expected %u.\n",
10692 adapter_count, expected_adapter_count);
10694 for (i = 0; i < adapter_count; ++i)
10696 monitor = IDirect3D8_GetAdapterMonitor(d3d, i);
10697 ok(!!monitor, "Adapter %u: Failed to get monitor.\n", i);
10699 monitor_info.cbSize = sizeof(monitor_info);
10700 ret = GetMonitorInfoA(monitor, (MONITORINFO *)&monitor_info);
10701 ok(ret, "Adapter %u: Failed to get monitor info, error %#lx.\n", i, GetLastError());
10703 if (!i)
10704 ok(monitor_info.dwFlags == MONITORINFOF_PRIMARY,
10705 "Adapter %u: Got unexpected monitor flags %#lx.\n", i, monitor_info.dwFlags);
10706 else
10707 ok(!monitor_info.dwFlags, "Adapter %u: Got unexpected monitor flags %#lx.\n", i,
10708 monitor_info.dwFlags);
10710 /* Test D3D adapters after they got detached */
10711 if (monitor_info.dwFlags == MONITORINFOF_PRIMARY)
10712 continue;
10714 /* Save current display settings */
10715 memset(&old_mode, 0, sizeof(old_mode));
10716 old_mode.dmSize = sizeof(old_mode);
10717 ret = EnumDisplaySettingsA(monitor_info.szDevice, ENUM_CURRENT_SETTINGS, &old_mode);
10718 /* Win10 TestBots may return FALSE but it's actually successful */
10719 ok(ret || broken(!ret), "Adapter %u: EnumDisplaySettingsA failed for %s, error %#lx.\n", i,
10720 monitor_info.szDevice, GetLastError());
10722 /* Detach */
10723 memset(&mode, 0, sizeof(mode));
10724 mode.dmSize = sizeof(mode);
10725 mode.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT;
10726 mode.dmPosition = old_mode.dmPosition;
10727 ret = ChangeDisplaySettingsExA(monitor_info.szDevice, &mode, NULL,
10728 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
10729 ok(ret == DISP_CHANGE_SUCCESSFUL,
10730 "Adapter %u: ChangeDisplaySettingsExA %s returned unexpected %ld.\n", i,
10731 monitor_info.szDevice, ret);
10732 ret = ChangeDisplaySettingsExA(monitor_info.szDevice, NULL, NULL, 0, NULL);
10733 ok(ret == DISP_CHANGE_SUCCESSFUL,
10734 "Adapter %u: ChangeDisplaySettingsExA %s returned unexpected %ld.\n", i,
10735 monitor_info.szDevice, ret);
10737 /* Check if it is really detached */
10738 memset(&mode, 0, sizeof(mode));
10739 mode.dmSize = sizeof(mode);
10740 ret = EnumDisplaySettingsA(monitor_info.szDevice, ENUM_CURRENT_SETTINGS, &mode);
10741 /* Win10 TestBots may return FALSE but it's actually successful */
10742 ok(ret || broken(!ret) , "Adapter %u: EnumDisplaySettingsA failed for %s, error %#lx.\n", i,
10743 monitor_info.szDevice, GetLastError());
10744 if (mode.dmPelsWidth && mode.dmPelsHeight)
10746 skip("Adapter %u: Failed to detach device %s.\n", i, monitor_info.szDevice);
10747 continue;
10750 /* Detaching adapter shouldn't reduce the adapter count */
10751 expected_adapter_count = adapter_count;
10752 adapter_count = IDirect3D8_GetAdapterCount(d3d);
10753 ok(adapter_count == expected_adapter_count,
10754 "Adapter %u: Got unexpected adapter count %u, expected %u.\n", i, adapter_count,
10755 expected_adapter_count);
10757 monitor = IDirect3D8_GetAdapterMonitor(d3d, i);
10758 ok(!monitor, "Adapter %u: Expect monitor to be NULL.\n", i);
10760 /* Restore settings */
10761 ret = ChangeDisplaySettingsExA(monitor_info.szDevice, &old_mode, NULL,
10762 CDS_UPDATEREGISTRY | CDS_NORESET, NULL);
10763 ok(ret == DISP_CHANGE_SUCCESSFUL,
10764 "Adapter %u: ChangeDisplaySettingsExA %s returned unexpected %ld.\n", i,
10765 monitor_info.szDevice, ret);
10766 ret = ChangeDisplaySettingsExA(monitor_info.szDevice, NULL, NULL, 0, NULL);
10767 ok(ret == DISP_CHANGE_SUCCESSFUL,
10768 "Adapter %u: ChangeDisplaySettingsExA %s returned unexpected %ld.\n", i,
10769 monitor_info.szDevice, ret);
10772 IDirect3D8_Release(d3d);
10775 static void test_creation_parameters(void)
10777 unsigned int adapter_idx, adapter_count;
10778 D3DDEVICE_CREATION_PARAMETERS params;
10779 struct device_desc device_desc;
10780 IDirect3DDevice8 *device;
10781 IDirect3D8 *d3d;
10782 HWND window;
10783 HRESULT hr;
10785 window = create_window();
10786 ok(!!window, "Failed to create a window.\n");
10787 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10788 ok(!!d3d, "Failed to create a D3D object.\n");
10790 device_desc.device_window = window;
10791 device_desc.width = 640;
10792 device_desc.height = 480;
10793 device_desc.flags = 0;
10795 adapter_count = IDirect3D8_GetAdapterCount(d3d);
10796 for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
10798 device_desc.adapter_ordinal = adapter_idx;
10799 if (!(device = create_device(d3d, window, &device_desc)))
10801 skip("Adapter %u: Failed to create a D3D device.\n", adapter_idx);
10802 break;
10805 memset(&params, 0, sizeof(params));
10806 hr = IDirect3DDevice8_GetCreationParameters(device, &params);
10807 ok(hr == D3D_OK, "Adapter %u: GetCreationParameters failed, hr %#lx.\n", adapter_idx, hr);
10808 ok(params.AdapterOrdinal == adapter_idx, "Adapter %u: Got unexpected adapter ordinal %u.\n",
10809 adapter_idx, params.AdapterOrdinal);
10810 ok(params.DeviceType == D3DDEVTYPE_HAL, "Adapter %u: Expect device type %#x, got %#x.\n",
10811 adapter_idx, D3DDEVTYPE_HAL, params.DeviceType);
10812 ok(params.hFocusWindow == window, "Adapter %u: Expect focus window %p, got %p.\n",
10813 adapter_idx, window, params.hFocusWindow);
10815 IDirect3DDevice8_Release(device);
10818 IDirect3D8_Release(d3d);
10819 DestroyWindow(window);
10822 static void test_cursor_clipping(void)
10824 unsigned int adapter_idx, adapter_count, mode_idx;
10825 D3DDISPLAYMODE mode, current_mode;
10826 struct device_desc device_desc;
10827 RECT virtual_rect, clip_rect;
10828 IDirect3DDevice8 *device;
10829 IDirect3D8 *d3d;
10830 HWND window;
10831 HRESULT hr;
10832 BOOL ret;
10834 window = create_window();
10835 ok(!!window, "Failed to create a window.\n");
10836 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10837 ok(!!d3d, "Failed to create a D3D object.\n");
10839 device_desc.device_window = window;
10840 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10842 adapter_count = IDirect3D8_GetAdapterCount(d3d);
10843 for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
10845 hr = IDirect3D8_GetAdapterDisplayMode(d3d, adapter_idx, &current_mode);
10846 ok(hr == D3D_OK, "Adapter %u: GetAdapterDisplayMode failed, hr %#lx.\n", adapter_idx, hr);
10847 for (mode_idx = 0; SUCCEEDED(IDirect3D8_EnumAdapterModes(d3d, adapter_idx, mode_idx, &mode));
10848 ++mode_idx)
10850 if (mode.Format != D3DFMT_X8R8G8B8)
10851 continue;
10852 if (mode.Width < 640 || mode.Height < 480)
10853 continue;
10854 if (mode.Width != current_mode.Width && mode.Height != current_mode.Height)
10855 break;
10857 ok(mode.Width != current_mode.Width && mode.Height != current_mode.Height,
10858 "Adapter %u: Failed to find a different mode than %ux%u.\n", adapter_idx,
10859 current_mode.Width, current_mode.Height);
10861 ret = ClipCursor(NULL);
10862 ok(ret, "Adapter %u: ClipCursor failed, error %#lx.\n", adapter_idx,
10863 GetLastError());
10864 get_virtual_rect(&virtual_rect);
10865 ret = GetClipCursor(&clip_rect);
10866 ok(ret, "Adapter %u: GetClipCursor failed, error %#lx.\n", adapter_idx,
10867 GetLastError());
10868 ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u: Expect clip rect %s, got %s.\n",
10869 adapter_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect));
10871 device_desc.adapter_ordinal = adapter_idx;
10872 device_desc.width = mode.Width;
10873 device_desc.height = mode.Height;
10874 if (!(device = create_device(d3d, window, &device_desc)))
10876 skip("Adapter %u: Failed to create a D3D device.\n", adapter_idx);
10877 break;
10879 flush_events();
10880 get_virtual_rect(&virtual_rect);
10881 ret = GetClipCursor(&clip_rect);
10882 ok(ret, "Adapter %u: GetClipCursor failed, error %#lx.\n", adapter_idx,
10883 GetLastError());
10884 ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u: Expect clip rect %s, got %s.\n",
10885 adapter_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect));
10887 IDirect3DDevice8_Release(device);
10888 flush_events();
10889 get_virtual_rect(&virtual_rect);
10890 ret = GetClipCursor(&clip_rect);
10891 ok(ret, "Adapter %u: GetClipCursor failed, error %#lx.\n", adapter_idx,
10892 GetLastError());
10893 ok(EqualRect(&clip_rect, &virtual_rect), "Adapter %u: Expect clip rect %s, got %s.\n",
10894 adapter_idx, wine_dbgstr_rect(&virtual_rect), wine_dbgstr_rect(&clip_rect));
10897 IDirect3D8_Release(d3d);
10898 DestroyWindow(window);
10901 static void test_window_position(void)
10903 unsigned int adapter_idx, adapter_count;
10904 struct device_desc device_desc;
10905 IDirect3DDevice8 *device;
10906 MONITORINFO monitor_info;
10907 HMONITOR monitor;
10908 RECT window_rect;
10909 IDirect3D8 *d3d;
10910 HWND window;
10911 HRESULT hr;
10912 BOOL ret;
10914 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10915 ok(!!d3d, "Failed to create a D3D object.\n");
10917 adapter_count = IDirect3D8_GetAdapterCount(d3d);
10918 for (adapter_idx = 0; adapter_idx < adapter_count; ++adapter_idx)
10920 monitor = IDirect3D8_GetAdapterMonitor(d3d, adapter_idx);
10921 ok(!!monitor, "Adapter %u: GetAdapterMonitor failed.\n", adapter_idx);
10922 monitor_info.cbSize = sizeof(monitor_info);
10923 ret = GetMonitorInfoW(monitor, &monitor_info);
10924 ok(ret, "Adapter %u: GetMonitorInfoW failed, error %#lx.\n", adapter_idx, GetLastError());
10926 window = create_window();
10927 device_desc.adapter_ordinal = adapter_idx;
10928 device_desc.device_window = window;
10929 device_desc.width = monitor_info.rcMonitor.right - monitor_info.rcMonitor.left;
10930 device_desc.height = monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top;
10931 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10932 if (!(device = create_device(d3d, window, &device_desc)))
10934 skip("Adapter %u: Failed to create a D3D device, skipping tests.\n", adapter_idx);
10935 DestroyWindow(window);
10936 continue;
10938 flush_events();
10939 ret = GetWindowRect(window, &window_rect);
10940 ok(ret, "Adapter %u: GetWindowRect failed, error %#lx.\n", adapter_idx, GetLastError());
10941 ok(EqualRect(&window_rect, &monitor_info.rcMonitor),
10942 "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx,
10943 wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect));
10945 /* Device resets should restore the window rectangle to fit the whole monitor */
10946 ret = SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
10947 ok(ret, "Adapter %u: SetWindowPos failed, error %#lx.\n", adapter_idx, GetLastError());
10948 hr = reset_device(device, &device_desc);
10949 ok(hr == D3D_OK, "Adapter %u: Failed to reset device, hr %#lx.\n", adapter_idx, hr);
10950 flush_events();
10951 ret = GetWindowRect(window, &window_rect);
10952 ok(ret, "Adapter %u: GetWindowRect failed, error %#lx.\n", adapter_idx, GetLastError());
10953 ok(EqualRect(&window_rect, &monitor_info.rcMonitor),
10954 "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx,
10955 wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect));
10957 /* Window activation should restore the window rectangle to fit the whole monitor */
10958 ret = SetWindowPos(window, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
10959 ok(ret, "Adapter %u: SetWindowPos failed, error %#lx.\n", adapter_idx, GetLastError());
10960 ret = SetForegroundWindow(GetDesktopWindow());
10961 ok(ret, "Adapter %u: SetForegroundWindow failed, error %#lx.\n", adapter_idx, GetLastError());
10962 flush_events();
10963 ret = ShowWindow(window, SW_RESTORE);
10964 ok(ret, "Adapter %u: Failed to restore window, error %#lx.\n", adapter_idx, GetLastError());
10965 flush_events();
10966 ret = SetForegroundWindow(window);
10967 ok(ret, "Adapter %u: SetForegroundWindow failed, error %#lx.\n", adapter_idx, GetLastError());
10968 flush_events();
10969 ret = GetWindowRect(window, &window_rect);
10970 ok(ret, "Adapter %u: GetWindowRect failed, error %#lx.\n", adapter_idx, GetLastError());
10971 ok(EqualRect(&window_rect, &monitor_info.rcMonitor),
10972 "Adapter %u: Expect window rect %s, got %s.\n", adapter_idx,
10973 wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&window_rect));
10975 IDirect3DDevice8_Release(device);
10976 DestroyWindow(window);
10979 IDirect3D8_Release(d3d);
10982 static void test_filter(void)
10984 unsigned int mag, min, mip;
10985 IDirect3DTexture8 *texture;
10986 IDirect3DDevice8 *device;
10987 BOOL has_texture;
10988 IDirect3D8 *d3d;
10989 ULONG refcount;
10990 DWORD passes;
10991 HWND window;
10992 HRESULT hr;
10994 d3d = Direct3DCreate8(D3D_SDK_VERSION);
10995 ok(!!d3d, "Failed to create a D3D object.\n");
10997 window = create_window();
10998 if (!(device = create_device(d3d, window, NULL)))
11000 skip("Failed to create a D3D device, skipping tests.\n");
11001 IDirect3D8_Release(d3d);
11002 DestroyWindow(window);
11003 return;
11006 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
11007 ok(SUCCEEDED(hr), "Failed to create texture, hr %#lx.\n", hr);
11009 for (has_texture = FALSE; has_texture <= TRUE; ++has_texture)
11010 for (mag = 0; mag <= D3DTEXF_GAUSSIANCUBIC + 1; ++mag)
11011 for (min = 0; min <= D3DTEXF_GAUSSIANCUBIC + 1; ++min)
11012 for (mip = 0; mip <= D3DTEXF_GAUSSIANCUBIC + 1; ++mip)
11014 if (has_texture)
11016 hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
11017 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11019 else
11021 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
11022 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11025 hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, mag);
11026 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#lx.\n", hr);
11027 hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, min);
11028 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#lx.\n", hr);
11029 hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MIPFILTER, mip);
11030 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#lx.\n", hr);
11032 passes = 0xdeadbeef;
11033 hr = IDirect3DDevice8_ValidateDevice(device, &passes);
11034 ok(SUCCEEDED(hr), "Failed to validate device, hr %#lx.\n", hr);
11035 ok(passes && passes != 0xdeadbeef, "Got unexpected passes %#lx.\n", passes);
11038 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
11039 ok(SUCCEEDED(hr), "Failed to set texture, hr %#lx.\n", hr);
11040 IDirect3DTexture8_Release(texture);
11042 refcount = IDirect3DDevice8_Release(device);
11043 ok(!refcount, "Device has %lu references left.\n", refcount);
11044 IDirect3D8_Release(d3d);
11045 DestroyWindow(window);
11048 START_TEST(device)
11050 HMODULE d3d8_handle = GetModuleHandleA("d3d8.dll");
11051 WNDCLASSA wc = {0};
11052 IDirect3D8 *d3d8;
11053 DEVMODEW current_mode;
11055 if (!d3d8_handle)
11057 skip("Could not load d3d8.dll\n");
11058 return;
11061 memset(&current_mode, 0, sizeof(current_mode));
11062 current_mode.dmSize = sizeof(current_mode);
11063 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
11064 registry_mode.dmSize = sizeof(registry_mode);
11065 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
11066 if (current_mode.dmPelsWidth != registry_mode.dmPelsWidth
11067 || current_mode.dmPelsHeight != registry_mode.dmPelsHeight)
11069 skip("Current mode does not match registry mode, skipping test.\n");
11070 return;
11073 wc.lpfnWndProc = DefWindowProcA;
11074 wc.lpszClassName = "d3d8_test_wc";
11075 RegisterClassA(&wc);
11077 ValidateVertexShader = (void *)GetProcAddress(d3d8_handle, "ValidateVertexShader");
11078 ValidatePixelShader = (void *)GetProcAddress(d3d8_handle, "ValidatePixelShader");
11080 if (!(d3d8 = Direct3DCreate8(D3D_SDK_VERSION)))
11082 skip("could not create D3D8\n");
11083 return;
11085 IDirect3D8_Release(d3d8);
11087 test_fpu_setup();
11088 test_display_formats();
11089 test_display_modes();
11090 test_shader_versions();
11091 test_swapchain();
11092 test_refcount();
11093 test_mipmap_levels();
11094 test_checkdevicemultisampletype();
11095 test_invalid_multisample();
11096 test_cursor();
11097 test_cursor_pos();
11098 test_states();
11099 test_reset();
11100 test_scene();
11101 test_shader();
11102 test_limits();
11103 test_lights();
11104 test_set_stream_source();
11105 test_ApplyStateBlock();
11106 test_render_zero_triangles();
11107 test_depth_stencil_reset();
11108 test_wndproc();
11109 test_wndproc_windowed();
11110 test_depth_stencil_size();
11111 test_window_style();
11112 test_unsupported_shaders();
11113 test_mode_change();
11114 test_device_window_reset();
11115 test_reset_resources();
11116 depth_blit_test();
11117 test_set_rt_vp_scissor();
11118 test_validate_vs();
11119 test_validate_ps();
11120 test_volume_get_container();
11121 test_vb_lock_flags();
11122 test_texture_stage_states();
11123 test_cube_textures();
11124 test_get_set_texture();
11125 test_image_surface_pool();
11126 test_surface_get_container();
11127 test_lockrect_invalid();
11128 test_private_data();
11129 test_surface_dimensions();
11130 test_surface_format_null();
11131 test_surface_double_unlock();
11132 test_surface_blocks();
11133 test_set_palette();
11134 test_pinned_buffers();
11135 test_npot_textures();
11136 test_volume_locking();
11137 test_update_texture_pool();
11138 test_update_volumetexture();
11139 test_create_rt_ds_fail();
11140 test_volume_blocks();
11141 test_lockbox_invalid();
11142 test_pixel_format();
11143 test_begin_end_state_block();
11144 test_shader_constant_apply();
11145 test_resource_type();
11146 test_mipmap_lock();
11147 test_writeonly_resource();
11148 test_lost_device();
11149 test_resource_priority();
11150 test_swapchain_parameters();
11151 test_check_device_format();
11152 test_miptree_layout();
11153 test_render_target_device_mismatch();
11154 test_format_unknown();
11155 test_destroyed_window();
11156 test_lockable_backbuffer();
11157 test_clip_planes_limits();
11158 test_swapchain_multisample_reset();
11159 test_device_caps();
11160 test_get_info();
11161 test_resource_access();
11162 test_multiply_transform();
11163 test_draw_primitive();
11164 test_get_display_mode();
11165 test_multi_adapter();
11166 test_creation_parameters();
11167 test_cursor_clipping();
11168 test_window_position();
11169 test_filter();
11171 UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));