d3d8/tests: Add test for render target device mismatch.
[wine.git] / dlls / d3d8 / tests / device.c
blob2dbf9d8020ab29da6827a15a176808f86257172b
1 /*
2 * Copyright (C) 2006 Vitaliy Margolen
3 * Copyright (C) 2006 Chris Robinson
4 * Copyright (C) 2006 Louis Lenders
5 * Copyright 2006-2007 Henri Verbeet
6 * Copyright 2006-2007, 2011-2013 Stefan Dösinger for CodeWeavers
7 * Copyright 2013 Henri Verbeet for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define WINVER 0x0602 /* for CURSOR_SUPPRESSED */
25 #include <stdlib.h>
26 #define COBJMACROS
27 #include <initguid.h>
28 #include <d3d8.h>
29 #include "wine/test.h"
31 struct vec3
33 float x, y, z;
36 #define CREATE_DEVICE_FULLSCREEN 0x01
37 #define CREATE_DEVICE_FPU_PRESERVE 0x02
38 #define CREATE_DEVICE_SWVP_ONLY 0x04
40 struct device_desc
42 HWND device_window;
43 unsigned int width;
44 unsigned int height;
45 DWORD flags;
48 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
49 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
51 static DEVMODEW registry_mode;
53 static HRESULT (WINAPI *ValidateVertexShader)(DWORD *, DWORD *, DWORD *, int, DWORD *);
54 static HRESULT (WINAPI *ValidatePixelShader)(DWORD *, DWORD *, int, DWORD *);
56 static BOOL (WINAPI *pGetCursorInfo)(PCURSORINFO);
58 static const DWORD simple_vs[] = {0xFFFE0101, /* vs_1_1 */
59 0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0 */
60 0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1 */
61 0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2 */
62 0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3 */
63 0x0000FFFF}; /* END */
64 static const DWORD simple_ps[] = {0xFFFF0101, /* ps_1_1 */
65 0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
66 0x00000042, 0xB00F0000, /* tex t0 */
67 0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000, /* dp3 r0, c1, c0 */
68 0x00000005, 0x800F0000, 0x90E40000, 0x80E40000, /* mul r0, v0, r0 */
69 0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000, /* mul r0, t0, r0 */
70 0x0000FFFF}; /* END */
72 static int get_refcount(IUnknown *object)
74 IUnknown_AddRef( object );
75 return IUnknown_Release( object );
78 /* try to make sure pending X events have been processed before continuing */
79 static void flush_events(void)
81 MSG msg;
82 int diff = 200;
83 int min_timeout = 100;
84 DWORD time = GetTickCount() + diff;
86 while (diff > 0)
88 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
89 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
90 diff = time - GetTickCount();
94 static IDirect3DDevice8 *create_device(IDirect3D8 *d3d8, HWND focus_window, const struct device_desc *desc)
96 D3DPRESENT_PARAMETERS present_parameters = {0};
97 IDirect3DDevice8 *device;
98 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
100 present_parameters.BackBufferWidth = 640;
101 present_parameters.BackBufferHeight = 480;
102 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
103 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
104 present_parameters.hDeviceWindow = focus_window;
105 present_parameters.Windowed = TRUE;
106 present_parameters.EnableAutoDepthStencil = TRUE;
107 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
109 if (desc)
111 present_parameters.BackBufferWidth = desc->width;
112 present_parameters.BackBufferHeight = desc->height;
113 present_parameters.hDeviceWindow = desc->device_window;
114 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
115 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
116 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
117 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
118 behavior_flags |= D3DCREATE_FPU_PRESERVE;
121 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
122 behavior_flags, &present_parameters, &device)))
123 return device;
125 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
126 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
127 behavior_flags, &present_parameters, &device)))
128 return device;
130 if (desc && desc->flags & CREATE_DEVICE_SWVP_ONLY)
131 return NULL;
132 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
134 if (SUCCEEDED(IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
135 behavior_flags, &present_parameters, &device)))
136 return device;
138 return NULL;
141 static HRESULT reset_device(IDirect3DDevice8 *device, const struct device_desc *desc)
143 D3DPRESENT_PARAMETERS present_parameters = {0};
145 present_parameters.BackBufferWidth = 640;
146 present_parameters.BackBufferHeight = 480;
147 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
148 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
149 present_parameters.hDeviceWindow = NULL;
150 present_parameters.Windowed = TRUE;
151 present_parameters.EnableAutoDepthStencil = TRUE;
152 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
154 if (desc)
156 present_parameters.BackBufferWidth = desc->width;
157 present_parameters.BackBufferHeight = desc->height;
158 present_parameters.hDeviceWindow = desc->device_window;
159 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
162 return IDirect3DDevice8_Reset(device, &present_parameters);
165 #define CHECK_CALL(r,c,d,rc) \
166 if (SUCCEEDED(r)) {\
167 int tmp1 = get_refcount( (IUnknown *)d ); \
168 int rc_new = rc; \
169 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
170 } else {\
171 trace("%s failed: %#08x\n", c, r); \
174 #define CHECK_RELEASE(obj,d,rc) \
175 if (obj) { \
176 int tmp1, rc_new = rc; \
177 IUnknown_Release( (IUnknown*)obj ); \
178 tmp1 = get_refcount( (IUnknown *)d ); \
179 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
182 #define CHECK_REFCOUNT(obj,rc) \
184 int rc_new = rc; \
185 int count = get_refcount( (IUnknown *)obj ); \
186 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
189 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
191 int rc_new = rc; \
192 int count = IUnknown_Release( (IUnknown *)obj ); \
193 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
196 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
198 int rc_new = rc; \
199 int count = IUnknown_AddRef( (IUnknown *)obj ); \
200 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
203 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
205 void *container_ptr = (void *)0x1337c0d3; \
206 hr = IDirect3DSurface8_GetContainer(obj, &iid, &container_ptr); \
207 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#08x, container_ptr %p. " \
208 "Expected hr %#08x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
209 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
212 static void check_mipmap_levels(IDirect3DDevice8 *device, UINT width, UINT height, UINT count)
214 IDirect3DBaseTexture8* texture = NULL;
215 HRESULT hr = IDirect3DDevice8_CreateTexture( device, width, height, 0, 0,
216 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture8**) &texture );
218 if (SUCCEEDED(hr)) {
219 DWORD levels = IDirect3DBaseTexture8_GetLevelCount(texture);
220 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
221 } else
222 trace("CreateTexture failed: %#08x\n", hr);
224 if (texture) IDirect3DBaseTexture8_Release( texture );
227 static void test_mipmap_levels(void)
229 IDirect3DDevice8 *device;
230 IDirect3D8 *d3d;
231 ULONG refcount;
232 HWND window;
234 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
235 0, 0, 640, 480, NULL, NULL, NULL, NULL);
236 ok(!!window, "Failed to create a window.\n");
237 d3d = Direct3DCreate8(D3D_SDK_VERSION);
238 ok(!!d3d, "Failed to create a D3D object.\n");
239 if (!(device = create_device(d3d, window, NULL)))
241 skip("Failed to create a 3D device, skipping test.\n");
242 goto cleanup;
245 check_mipmap_levels(device, 32, 32, 6);
246 check_mipmap_levels(device, 256, 1, 9);
247 check_mipmap_levels(device, 1, 256, 9);
248 check_mipmap_levels(device, 1, 1, 1);
250 refcount = IDirect3DDevice8_Release(device);
251 ok(!refcount, "Device has %u references left.\n", refcount);
252 cleanup:
253 IDirect3D8_Release(d3d);
254 DestroyWindow(window);
257 static void test_swapchain(void)
259 IDirect3DSwapChain8 *swapchain1;
260 IDirect3DSwapChain8 *swapchain2;
261 IDirect3DSwapChain8 *swapchain3;
262 IDirect3DSurface8 *backbuffer, *stereo_buffer;
263 D3DPRESENT_PARAMETERS d3dpp;
264 IDirect3DDevice8 *device;
265 IDirect3D8 *d3d;
266 ULONG refcount;
267 HWND window, window2;
268 HRESULT hr;
269 struct device_desc device_desc;
271 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
272 0, 0, 640, 480, NULL, NULL, NULL, NULL);
273 ok(!!window, "Failed to create a window.\n");
274 window2 = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
275 0, 0, 640, 480, NULL, NULL, NULL, NULL);
276 ok(!!window2, "Failed to create a window.\n");
277 d3d = Direct3DCreate8(D3D_SDK_VERSION);
278 ok(!!d3d, "Failed to create a D3D object.\n");
279 if (!(device = create_device(d3d, window, NULL)))
281 skip("Failed to create a 3D device, skipping test.\n");
282 goto cleanup;
285 backbuffer = (void *)0xdeadbeef;
286 /* IDirect3DDevice8::GetBackBuffer crashes if a NULL output pointer is passed. */
287 hr = IDirect3DDevice8_GetBackBuffer(device, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
288 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
289 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
291 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
292 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
293 IDirect3DSurface8_Release(backbuffer);
295 /* The back buffer type value is ignored. */
296 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
297 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
298 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
299 IDirect3DSurface8_Release(stereo_buffer);
300 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
301 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
302 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
303 IDirect3DSurface8_Release(stereo_buffer);
304 hr = IDirect3DDevice8_GetBackBuffer(device, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
305 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
306 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
307 IDirect3DSurface8_Release(stereo_buffer);
309 memset(&d3dpp, 0, sizeof(d3dpp));
310 d3dpp.Windowed = TRUE;
311 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
312 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
314 /* Create a bunch of swapchains */
315 d3dpp.BackBufferCount = 0;
316 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
317 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
318 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
320 d3dpp.BackBufferCount = 1;
321 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
322 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
324 d3dpp.BackBufferCount = 2;
325 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
326 ok(SUCCEEDED(hr), "Failed to create a swapchain (%#08x)\n", hr);
327 if(SUCCEEDED(hr)) {
328 /* Swapchain 3, created with backbuffercount 2 */
329 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, NULL);
330 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
332 backbuffer = (void *) 0xdeadbeef;
333 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
334 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%#08x)\n", hr);
335 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
336 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
338 /* The back buffer type value is ignored. */
339 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
340 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
341 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
342 IDirect3DSurface8_Release(stereo_buffer);
343 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
344 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
345 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
346 IDirect3DSurface8_Release(stereo_buffer);
347 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
348 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
349 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
350 IDirect3DSurface8_Release(stereo_buffer);
352 backbuffer = (void *) 0xdeadbeef;
353 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
354 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%#08x)\n", hr);
355 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
356 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
358 backbuffer = (void *) 0xdeadbeef;
359 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
360 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
361 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
362 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
364 backbuffer = (void *) 0xdeadbeef;
365 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
366 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
367 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
368 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
371 /* Check the back buffers of the swapchains */
372 /* Swapchain 1, created with backbuffercount 0 */
373 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
374 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
375 ok(backbuffer != NULL, "The back buffer is NULL (%#08x)\n", hr);
376 if(backbuffer) IDirect3DSurface8_Release(backbuffer);
378 backbuffer = (void *) 0xdeadbeef;
379 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
380 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
381 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
382 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
384 /* Swapchain 2 - created with backbuffercount 1 */
385 backbuffer = (void *) 0xdeadbeef;
386 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
387 ok(SUCCEEDED(hr), "Failed to get the back buffer (%#08x)\n", hr);
388 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
389 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
391 backbuffer = (void *) 0xdeadbeef;
392 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
393 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %#08x\n", hr);
394 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
395 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
397 backbuffer = (void *) 0xdeadbeef;
398 hr = IDirect3DSwapChain8_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
399 ok(FAILED(hr), "Failed to get the back buffer (%#08x)\n", hr);
400 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
401 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface8_Release(backbuffer);
403 IDirect3DSwapChain8_Release(swapchain3);
404 IDirect3DSwapChain8_Release(swapchain2);
405 IDirect3DSwapChain8_Release(swapchain1);
407 d3dpp.Windowed = FALSE;
408 d3dpp.hDeviceWindow = window;
409 d3dpp.BackBufferCount = 1;
410 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
411 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
412 d3dpp.hDeviceWindow = window2;
413 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
414 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
416 device_desc.width = registry_mode.dmPelsWidth;
417 device_desc.height = registry_mode.dmPelsHeight;
418 device_desc.device_window = window;
419 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
420 hr = reset_device(device, &device_desc);
421 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
423 d3dpp.hDeviceWindow = window;
424 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
425 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
426 d3dpp.hDeviceWindow = window2;
427 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
428 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
429 d3dpp.Windowed = TRUE;
430 d3dpp.hDeviceWindow = window;
431 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
432 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
433 d3dpp.hDeviceWindow = window2;
434 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
437 refcount = IDirect3DDevice8_Release(device);
438 ok(!refcount, "Device has %u references left.\n", refcount);
439 cleanup:
440 IDirect3D8_Release(d3d);
441 DestroyWindow(window2);
442 DestroyWindow(window);
445 static void test_refcount(void)
447 IDirect3DVertexBuffer8 *pVertexBuffer = NULL;
448 IDirect3DIndexBuffer8 *pIndexBuffer = NULL;
449 DWORD dVertexShader = -1;
450 DWORD dPixelShader = -1;
451 IDirect3DCubeTexture8 *pCubeTexture = NULL;
452 IDirect3DTexture8 *pTexture = NULL;
453 IDirect3DVolumeTexture8 *pVolumeTexture = NULL;
454 IDirect3DVolume8 *pVolumeLevel = NULL;
455 IDirect3DSurface8 *pStencilSurface = NULL;
456 IDirect3DSurface8 *pImageSurface = NULL;
457 IDirect3DSurface8 *pRenderTarget = NULL;
458 IDirect3DSurface8 *pRenderTarget2 = NULL;
459 IDirect3DSurface8 *pRenderTarget3 = NULL;
460 IDirect3DSurface8 *pTextureLevel = NULL;
461 IDirect3DSurface8 *pBackBuffer = NULL;
462 DWORD dStateBlock = -1;
463 IDirect3DSwapChain8 *pSwapChain = NULL;
464 D3DCAPS8 caps;
465 D3DPRESENT_PARAMETERS d3dpp;
466 IDirect3DDevice8 *device = NULL;
467 ULONG refcount = 0, tmp;
468 IDirect3D8 *d3d, *d3d2;
469 HWND window;
470 HRESULT hr;
472 DWORD decl[] =
474 D3DVSD_STREAM(0),
475 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
476 D3DVSD_REG(D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), /* D3DVSDE_DIFFUSE, Register v5 */
477 D3DVSD_END()
480 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
481 0, 0, 640, 480, NULL, NULL, NULL, NULL);
482 ok(!!window, "Failed to create a window.\n");
483 d3d = Direct3DCreate8(D3D_SDK_VERSION);
484 ok(!!d3d, "Failed to create a D3D object.\n");
486 CHECK_REFCOUNT(d3d, 1);
488 if (!(device = create_device(d3d, window, NULL)))
490 skip("Failed to create a 3D device, skipping test.\n");
491 goto cleanup;
494 IDirect3DDevice8_GetDeviceCaps(device, &caps);
496 refcount = get_refcount((IUnknown *)device);
497 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
499 CHECK_REFCOUNT(d3d, 2);
501 hr = IDirect3DDevice8_GetDirect3D(device, &d3d2);
502 CHECK_CALL(hr, "GetDirect3D", device, refcount);
504 ok(d3d2 == d3d, "Expected IDirect3D8 pointers to be equal.\n");
505 CHECK_REFCOUNT(d3d, 3);
506 CHECK_RELEASE_REFCOUNT(d3d, 2);
509 * Check refcount of implicit surfaces. Findings:
510 * - the container is the device
511 * - they hold a reference to the device
512 * - they are created with a refcount of 0 (Get/Release returns original refcount)
513 * - they are not freed if refcount reaches 0.
514 * - the refcount is not forwarded to the container.
516 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget);
517 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
518 if(pRenderTarget)
520 CHECK_SURFACE_CONTAINER(pRenderTarget, IID_IDirect3DDevice8, device);
521 CHECK_REFCOUNT( pRenderTarget, 1);
523 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
524 CHECK_REFCOUNT(device, refcount);
525 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
526 CHECK_REFCOUNT(device, refcount);
528 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget);
529 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
530 CHECK_REFCOUNT( pRenderTarget, 2);
531 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
532 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
533 CHECK_REFCOUNT(device, --refcount);
535 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
536 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
537 CHECK_REFCOUNT(device, ++refcount);
538 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
539 CHECK_REFCOUNT(device, --refcount);
542 /* Render target and back buffer are identical. */
543 hr = IDirect3DDevice8_GetBackBuffer(device, 0, 0, &pBackBuffer);
544 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
545 if(pBackBuffer)
547 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
548 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
549 pRenderTarget, pBackBuffer);
550 pBackBuffer = NULL;
552 CHECK_REFCOUNT(device, --refcount);
554 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &pStencilSurface);
555 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
556 if(pStencilSurface)
558 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice8, device);
559 CHECK_REFCOUNT( pStencilSurface, 1);
561 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
562 CHECK_REFCOUNT(device, refcount);
563 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
564 CHECK_REFCOUNT(device, refcount);
566 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
567 CHECK_REFCOUNT(device, --refcount);
569 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
570 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
571 CHECK_REFCOUNT(device, ++refcount);
572 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
573 CHECK_REFCOUNT(device, --refcount);
574 pStencilSurface = NULL;
577 /* Buffers */
578 hr = IDirect3DDevice8_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer);
579 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount);
580 if(pIndexBuffer)
582 tmp = get_refcount( (IUnknown *)pIndexBuffer );
584 hr = IDirect3DDevice8_SetIndices(device, pIndexBuffer, 0);
585 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
586 hr = IDirect3DDevice8_SetIndices(device, NULL, 0);
587 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
590 hr = IDirect3DDevice8_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer);
591 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
592 if(pVertexBuffer)
594 IDirect3DVertexBuffer8 *pVBuf = (void*)~0;
595 UINT stride = ~0;
597 tmp = get_refcount( (IUnknown *)pVertexBuffer );
599 hr = IDirect3DDevice8_SetStreamSource(device, 0, pVertexBuffer, 3 * sizeof(float));
600 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
601 hr = IDirect3DDevice8_SetStreamSource(device, 0, NULL, 0);
602 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
604 hr = IDirect3DDevice8_GetStreamSource(device, 0, &pVBuf, &stride);
605 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
606 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
607 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
610 /* Shaders */
611 hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_vs, &dVertexShader, 0);
612 CHECK_CALL(hr, "CreateVertexShader", device, refcount);
613 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
615 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &dPixelShader);
616 CHECK_CALL(hr, "CreatePixelShader", device, refcount);
618 /* Textures */
619 hr = IDirect3DDevice8_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture);
620 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
621 if (pTexture)
623 tmp = get_refcount( (IUnknown *)pTexture );
625 /* SetTexture should not increase refcounts */
626 hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) pTexture);
627 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
628 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
629 CHECK_CALL( hr, "SetTexture", pTexture, tmp);
631 /* This should not increment device refcount */
632 hr = IDirect3DTexture8_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
633 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
634 /* But should increment texture's refcount */
635 CHECK_REFCOUNT( pTexture, tmp+1 );
636 /* Because the texture and surface refcount are identical */
637 if (pTextureLevel)
639 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
640 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
641 CHECK_REFCOUNT ( pTexture , tmp+2 );
642 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
643 CHECK_REFCOUNT ( pTexture , tmp+1 );
644 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
645 CHECK_REFCOUNT ( pTextureLevel, tmp );
648 if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
650 hr = IDirect3DDevice8_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture);
651 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
653 else
655 skip("Cube textures not supported\n");
657 if(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
659 hr = IDirect3DDevice8_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
660 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture);
661 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
663 else
665 skip("Volume textures not supported\n");
668 if (pVolumeTexture)
670 tmp = get_refcount( (IUnknown *)pVolumeTexture );
672 /* This should not increment device refcount */
673 hr = IDirect3DVolumeTexture8_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
674 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
675 /* But should increment volume texture's refcount */
676 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
677 /* Because the volume texture and volume refcount are identical */
678 if (pVolumeLevel)
680 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
681 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
682 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
683 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
684 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
685 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
686 CHECK_REFCOUNT ( pVolumeLevel , tmp );
689 /* Surfaces */
690 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32,
691 D3DFMT_D16, D3DMULTISAMPLE_NONE, &pStencilSurface);
692 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
693 CHECK_REFCOUNT( pStencilSurface, 1);
694 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32,
695 D3DFMT_X8R8G8B8, &pImageSurface);
696 CHECK_CALL(hr, "CreateImageSurface", device, ++refcount);
697 CHECK_REFCOUNT( pImageSurface, 1);
698 hr = IDirect3DDevice8_CreateRenderTarget(device, 32, 32,
699 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, TRUE, &pRenderTarget3);
700 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
701 CHECK_REFCOUNT( pRenderTarget3, 1);
702 /* Misc */
703 hr = IDirect3DDevice8_CreateStateBlock(device, D3DSBT_ALL, &dStateBlock);
704 CHECK_CALL(hr, "CreateStateBlock", device, refcount);
706 memset(&d3dpp, 0, sizeof(d3dpp));
707 d3dpp.Windowed = TRUE;
708 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
709 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
710 d3dpp.EnableAutoDepthStencil = TRUE;
711 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
712 hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
713 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
714 if(pSwapChain)
716 /* check implicit back buffer */
717 hr = IDirect3DSwapChain8_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
718 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
719 CHECK_REFCOUNT( pSwapChain, 1);
720 if(pBackBuffer)
722 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DDevice8, device);
723 CHECK_REFCOUNT( pBackBuffer, 1);
724 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
725 CHECK_REFCOUNT(device, --refcount);
727 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
728 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
729 CHECK_REFCOUNT(device, ++refcount);
730 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
731 CHECK_REFCOUNT(device, --refcount);
732 pBackBuffer = NULL;
734 CHECK_REFCOUNT( pSwapChain, 1);
737 if(pVertexBuffer)
739 BYTE *data;
740 /* Vertex buffers can be locked multiple times */
741 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
742 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
743 hr = IDirect3DVertexBuffer8_Lock(pVertexBuffer, 0, 0, &data, 0);
744 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Lock failed with %#08x\n", hr);
745 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
746 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
747 hr = IDirect3DVertexBuffer8_Unlock(pVertexBuffer);
748 ok(hr == D3D_OK, "IDirect3DVertexBuffer8::Unlock failed with %#08x\n", hr);
751 /* The implicit render target is not freed if refcount reaches 0.
752 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
753 hr = IDirect3DDevice8_GetRenderTarget(device, &pRenderTarget2);
754 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
755 if(pRenderTarget2)
757 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
758 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
759 pRenderTarget, pRenderTarget2);
760 CHECK_REFCOUNT(device, --refcount);
761 pRenderTarget2 = NULL;
763 pRenderTarget = NULL;
765 cleanup:
766 CHECK_RELEASE(device, device, --refcount);
768 /* Buffers */
769 CHECK_RELEASE(pVertexBuffer, device, --refcount);
770 CHECK_RELEASE(pIndexBuffer, device, --refcount);
771 /* Shaders */
772 if (dVertexShader != ~0u)
773 IDirect3DDevice8_DeleteVertexShader(device, dVertexShader);
774 if (dPixelShader != ~0u)
775 IDirect3DDevice8_DeletePixelShader(device, dPixelShader);
776 /* Textures */
777 CHECK_RELEASE(pTexture, device, --refcount);
778 CHECK_RELEASE(pCubeTexture, device, --refcount);
779 CHECK_RELEASE(pVolumeTexture, device, --refcount);
780 /* Surfaces */
781 CHECK_RELEASE(pStencilSurface, device, --refcount);
782 CHECK_RELEASE(pImageSurface, device, --refcount);
783 CHECK_RELEASE(pRenderTarget3, device, --refcount);
784 /* Misc */
785 if (dStateBlock != ~0u)
786 IDirect3DDevice8_DeleteStateBlock(device, dStateBlock);
787 /* This will destroy device - cannot check the refcount here */
788 if (pSwapChain)
789 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
790 CHECK_RELEASE_REFCOUNT(d3d, 0);
791 DestroyWindow(window);
794 static void test_checkdevicemultisampletype(void)
796 IDirect3D8 *d3d;
797 HWND window;
798 HRESULT hr;
800 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
801 0, 0, 640, 480, NULL, NULL, NULL, NULL);
802 ok(!!window, "Failed to create a window.\n");
803 d3d = Direct3DCreate8(D3D_SDK_VERSION);
804 ok(!!d3d, "Failed to create a D3D object.\n");
806 if (IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
807 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES) == D3DERR_NOTAVAILABLE)
809 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
810 goto cleanup;
813 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
814 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE);
815 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
816 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
817 65536, TRUE, D3DMULTISAMPLE_NONE);
818 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
820 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
821 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE);
822 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
823 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
824 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE);
825 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
827 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
828 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES);
829 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
831 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
832 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
833 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES);
834 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
836 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
837 D3DFMT_X8R8G8B8, TRUE, 65536);
838 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
840 hr = IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
841 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES);
842 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
844 cleanup:
845 IDirect3D8_Release(d3d);
846 DestroyWindow(window);
849 static void test_invalid_multisample(void)
851 IDirect3DDevice8 *device;
852 IDirect3DSurface8 *rt;
853 IDirect3D8 *d3d;
854 BOOL available;
855 ULONG refcount;
856 HWND window;
857 HRESULT hr;
859 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
860 0, 0, 640, 480, NULL, NULL, NULL, NULL);
861 ok(!!window, "Failed to create a window.\n");
862 d3d = Direct3DCreate8(D3D_SDK_VERSION);
863 ok(!!d3d, "Failed to create a D3D object.\n");
865 if (!(device = create_device(d3d, window, NULL)))
867 skip("Failed to create a 3D device, skipping test.\n");
868 goto cleanup;
871 available = SUCCEEDED(IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
872 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES));
874 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128,
875 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, FALSE, &rt);
876 if (available)
878 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
879 IDirect3DSurface8_Release(rt);
881 else
883 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
886 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
887 available = SUCCEEDED(IDirect3D8_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
888 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES));
889 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128,
890 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, FALSE, &rt);
891 if (available)
893 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
894 IDirect3DSurface8_Release(rt);
896 else
898 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
901 refcount = IDirect3DDevice8_Release(device);
902 ok(!refcount, "Device has %u references left.\n", refcount);
903 cleanup:
904 IDirect3D8_Release(d3d);
905 DestroyWindow(window);
908 static void test_cursor(void)
910 HMODULE user32_handle = GetModuleHandleA("user32.dll");
911 IDirect3DSurface8 *cursor = NULL;
912 IDirect3DDevice8 *device;
913 CURSORINFO info;
914 IDirect3D8 *d3d;
915 ULONG refcount;
916 HCURSOR cur;
917 HWND window;
918 HRESULT hr;
919 BOOL ret;
921 pGetCursorInfo = (void *)GetProcAddress(user32_handle, "GetCursorInfo");
922 if (!pGetCursorInfo)
924 win_skip("GetCursorInfo is not available\n");
925 return;
928 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
929 0, 0, 640, 480, NULL, NULL, NULL, NULL);
930 ok(!!window, "Failed to create a window.\n");
932 ret = SetCursorPos(50, 50);
933 ok(ret, "Failed to set cursor position.\n");
934 flush_events();
936 memset(&info, 0, sizeof(info));
937 info.cbSize = sizeof(info);
938 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
939 cur = info.hCursor;
941 d3d = Direct3DCreate8(D3D_SDK_VERSION);
942 ok(!!d3d, "Failed to create a D3D object.\n");
943 if (!(device = create_device(d3d, window, NULL)))
945 skip("Failed to create a 3D device, skipping test.\n");
946 goto cleanup;
949 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
950 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
952 /* Initially hidden */
953 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
954 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
956 /* Not enabled without a surface*/
957 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
958 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
960 /* Fails */
961 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, NULL);
962 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
964 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
965 ok(hr == D3D_OK, "IDirect3DDevice8_SetCursorProperties returned %#08x\n", hr);
967 IDirect3DSurface8_Release(cursor);
969 memset(&info, 0, sizeof(info));
970 info.cbSize = sizeof(info);
971 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
972 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
973 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
975 /* Still hidden */
976 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
977 ok(!ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
979 /* Enabled now*/
980 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
981 ok(ret, "IDirect3DDevice8_ShowCursor returned %d\n", ret);
983 memset(&info, 0, sizeof(info));
984 info.cbSize = sizeof(info);
985 ok(pGetCursorInfo(&info), "GetCursorInfo failed\n");
986 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
987 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
989 refcount = IDirect3DDevice8_Release(device);
990 ok(!refcount, "Device has %u references left.\n", refcount);
991 cleanup:
992 IDirect3D8_Release(d3d);
993 DestroyWindow(window);
996 static const POINT *expect_pos;
998 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
1000 if (message == WM_MOUSEMOVE)
1002 if (expect_pos && expect_pos->x && expect_pos->y)
1004 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
1006 ClientToScreen(window, &p);
1007 if (expect_pos->x == p.x && expect_pos->y == p.y)
1008 ++expect_pos;
1012 return DefWindowProcA(window, message, wparam, lparam);
1015 static void test_cursor_pos(void)
1017 IDirect3DSurface8 *cursor;
1018 IDirect3DDevice8 *device;
1019 WNDCLASSA wc = {0};
1020 IDirect3D8 *d3d8;
1021 UINT refcount;
1022 HWND window;
1023 HRESULT hr;
1024 BOOL ret;
1026 /* Note that we don't check for movement we're not supposed to receive.
1027 * That's because it's hard to distinguish from the user accidentally
1028 * moving the mouse. */
1029 static const POINT points[] =
1031 {50, 50},
1032 {75, 75},
1033 {100, 100},
1034 {125, 125},
1035 {150, 150},
1036 {125, 125},
1037 {150, 150},
1038 {150, 150},
1039 {0, 0},
1042 wc.lpfnWndProc = test_cursor_proc;
1043 wc.lpszClassName = "d3d8_test_cursor_wc";
1044 ok(RegisterClassA(&wc), "Failed to register window class.\n");
1045 window = CreateWindowA("d3d8_test_cursor_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1046 0, 0, 320, 240, NULL, NULL, NULL, NULL);
1047 ShowWindow(window, SW_SHOW);
1048 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1049 ok(!!d3d8, "Failed to create a D3D object.\n");
1051 if (!(device = create_device(d3d8, window, NULL)))
1053 skip("Failed to create a D3D device, skipping tests.\n");
1054 goto done;
1057 hr = IDirect3DDevice8_CreateImageSurface(device, 32, 32, D3DFMT_A8R8G8B8, &cursor);
1058 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1059 hr = IDirect3DDevice8_SetCursorProperties(device, 0, 0, cursor);
1060 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
1061 IDirect3DSurface8_Release(cursor);
1062 ret = IDirect3DDevice8_ShowCursor(device, TRUE);
1063 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
1065 flush_events();
1066 expect_pos = points;
1068 ret = SetCursorPos(50, 50);
1069 ok(ret, "Failed to set cursor position.\n");
1070 flush_events();
1072 IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
1073 flush_events();
1074 /* SetCursorPosition() eats duplicates. */
1075 IDirect3DDevice8_SetCursorPosition(device, 75, 75, 0);
1076 flush_events();
1078 ret = SetCursorPos(100, 100);
1079 ok(ret, "Failed to set cursor position.\n");
1080 flush_events();
1081 /* Even if the position was set with SetCursorPos(). */
1082 IDirect3DDevice8_SetCursorPosition(device, 100, 100, 0);
1083 flush_events();
1085 IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
1086 flush_events();
1087 ret = SetCursorPos(150, 150);
1088 ok(ret, "Failed to set cursor position.\n");
1089 flush_events();
1090 IDirect3DDevice8_SetCursorPosition(device, 125, 125, 0);
1091 flush_events();
1093 IDirect3DDevice8_SetCursorPosition(device, 150, 150, 0);
1094 flush_events();
1095 /* SetCursorPos() doesn't. */
1096 ret = SetCursorPos(150, 150);
1097 ok(ret, "Failed to set cursor position.\n");
1098 flush_events();
1100 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
1101 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
1103 refcount = IDirect3DDevice8_Release(device);
1104 ok(!refcount, "Device has %u references left.\n", refcount);
1105 done:
1106 DestroyWindow(window);
1107 UnregisterClassA("d3d8_test_cursor_wc", GetModuleHandleA(NULL));
1108 IDirect3D8_Release(d3d8);
1111 static void test_states(void)
1113 IDirect3DDevice8 *device;
1114 IDirect3D8 *d3d;
1115 ULONG refcount;
1116 HWND window;
1117 HRESULT hr;
1119 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1120 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1121 ok(!!window, "Failed to create a window.\n");
1122 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1123 ok(!!d3d, "Failed to create a D3D object.\n");
1124 if (!(device = create_device(d3d, window, NULL)))
1126 skip("Failed to create a 3D device, skipping test.\n");
1127 goto cleanup;
1130 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZVISIBLE, TRUE);
1131 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, TRUE) returned %#08x\n", hr);
1132 hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZVISIBLE, FALSE);
1133 ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState(D3DRS_ZVISIBLE, FALSE) returned %#08x\n", hr);
1135 refcount = IDirect3DDevice8_Release(device);
1136 ok(!refcount, "Device has %u references left.\n", refcount);
1137 cleanup:
1138 IDirect3D8_Release(d3d);
1139 DestroyWindow(window);
1142 static void test_shader_versions(void)
1144 IDirect3D8 *d3d;
1145 D3DCAPS8 caps;
1146 HRESULT hr;
1148 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1149 ok(!!d3d, "Failed to create a D3D object.\n");
1151 hr = IDirect3D8_GetDeviceCaps(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
1152 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "Failed to get device caps, hr %#x.\n", hr);
1153 IDirect3D8_Release(d3d);
1154 if (FAILED(hr))
1156 skip("No Direct3D support, skipping test.\n");
1157 return;
1160 ok(caps.VertexShaderVersion <= D3DVS_VERSION(1,1),
1161 "Got unexpected VertexShaderVersion %#x.\n", caps.VertexShaderVersion);
1162 ok(caps.PixelShaderVersion <= D3DPS_VERSION(1,4),
1163 "Got unexpected PixelShaderVersion %#x.\n", caps.PixelShaderVersion);
1166 static void test_display_formats(void)
1168 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
1169 unsigned int backbuffer, display;
1170 unsigned int windowed, i;
1171 D3DDISPLAYMODE mode;
1172 IDirect3D8 *d3d8;
1173 BOOL should_pass;
1174 BOOL has_modes;
1175 HRESULT hr;
1177 static const struct
1179 const char *name;
1180 D3DFORMAT format;
1181 D3DFORMAT alpha_format;
1182 BOOL display;
1183 BOOL windowed;
1185 formats[] =
1187 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
1188 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
1189 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
1190 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
1191 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
1192 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
1195 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1196 ok(!!d3d8, "Failed to create a D3D object.\n");
1198 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
1200 for (i = 0, has_modes = FALSE; SUCCEEDED(IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &mode)); ++i)
1202 if (mode.Format == formats[display].format)
1204 has_modes = TRUE;
1205 break;
1209 for (windowed = 0; windowed <= 1; ++windowed)
1211 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
1213 should_pass = FALSE;
1215 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
1217 D3DFORMAT backbuffer_format;
1219 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
1220 backbuffer_format = formats[display].format;
1221 else
1222 backbuffer_format = formats[backbuffer].format;
1224 hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, device_type, formats[display].format,
1225 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
1226 should_pass = (hr == D3D_OK) && (formats[display].format == formats[backbuffer].format
1227 || (formats[display].alpha_format
1228 && formats[display].alpha_format == formats[backbuffer].alpha_format));
1231 hr = IDirect3D8_CheckDeviceType(d3d8, D3DADAPTER_DEFAULT, device_type,
1232 formats[display].format, formats[backbuffer].format, windowed);
1233 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
1234 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
1235 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
1240 IDirect3D8_Release(d3d8);
1243 /* Test adapter display modes */
1244 static void test_display_modes(void)
1246 UINT max_modes, i;
1247 D3DDISPLAYMODE dmode;
1248 IDirect3D8 *d3d;
1249 HRESULT res;
1251 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1252 ok(!!d3d, "Failed to create a D3D object.\n");
1254 max_modes = IDirect3D8_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT);
1255 ok(max_modes > 0 ||
1256 broken(max_modes == 0), /* VMware */
1257 "GetAdapterModeCount(D3DADAPTER_DEFAULT) returned 0!\n");
1259 for (i = 0; i < max_modes; ++i)
1261 res = IDirect3D8_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, i, &dmode);
1262 ok(res==D3D_OK, "EnumAdapterModes returned %#08x for mode %u!\n", res, i);
1263 if(res != D3D_OK)
1264 continue;
1266 ok(dmode.Format==D3DFMT_X8R8G8B8 || dmode.Format==D3DFMT_R5G6B5,
1267 "Unexpected display mode returned for mode %u: %#x\n", i , dmode.Format);
1270 IDirect3D8_Release(d3d);
1273 struct mode
1275 unsigned int w;
1276 unsigned int h;
1279 static int compare_mode(const void *a, const void *b)
1281 const struct mode *mode_a = a;
1282 const struct mode *mode_b = b;
1283 unsigned int w = mode_a->w - mode_b->w;
1284 unsigned int h = mode_b->h - mode_b->h;
1285 return abs(w) >= abs(h) ? -w : -h;
1288 static void test_reset(void)
1290 UINT width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1291 UINT height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1292 IDirect3DDevice8 *device1 = NULL;
1293 IDirect3DDevice8 *device2 = NULL;
1294 struct device_desc device_desc;
1295 D3DDISPLAYMODE d3ddm, d3ddm2;
1296 D3DSURFACE_DESC surface_desc;
1297 D3DPRESENT_PARAMETERS d3dpp;
1298 IDirect3DSurface8 *surface;
1299 IDirect3DTexture8 *texture;
1300 UINT adapter_mode_count;
1301 D3DLOCKED_RECT lockrect;
1302 UINT mode_count = 0;
1303 DEVMODEW devmode;
1304 IDirect3D8 *d3d8;
1305 RECT winrect;
1306 D3DVIEWPORT8 vp;
1307 D3DCAPS8 caps;
1308 DWORD shader;
1309 DWORD value;
1310 HWND window;
1311 HRESULT hr;
1312 LONG ret;
1313 UINT i;
1315 static const DWORD decl[] =
1317 D3DVSD_STREAM(0),
1318 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT4),
1319 D3DVSD_END(),
1322 struct mode *modes = NULL;
1324 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1325 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1326 ok(!!window, "Failed to create a window.\n");
1327 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
1328 ok(!!d3d8, "Failed to create a D3D object.\n");
1330 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1331 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1332 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
1333 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1334 for (i = 0; i < adapter_mode_count; ++i)
1336 UINT j;
1338 memset(&d3ddm2, 0, sizeof(d3ddm2));
1339 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm2);
1340 ok(SUCCEEDED(hr), "EnumAdapterModes failed, hr %#x.\n", hr);
1342 if (d3ddm2.Format != d3ddm.Format)
1343 continue;
1345 for (j = 0; j < mode_count; ++j)
1347 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1348 break;
1350 if (j == mode_count)
1352 modes[j].w = d3ddm2.Width;
1353 modes[j].h = d3ddm2.Height;
1354 ++mode_count;
1357 /* We use them as invalid modes. */
1358 if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
1359 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
1361 skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
1362 d3ddm2.Width, d3ddm2.Height);
1363 goto cleanup;
1367 if (mode_count < 2)
1369 skip("Less than 2 modes supported, skipping mode tests.\n");
1370 goto cleanup;
1373 /* Prefer higher resolutions. */
1374 qsort(modes, mode_count, sizeof(*modes), compare_mode);
1376 i = 0;
1377 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1379 device_desc.width = modes[i].w;
1380 device_desc.height = modes[i].h;
1381 device_desc.device_window = window;
1382 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1383 if (!(device1 = create_device(d3d8, window, &device_desc)))
1385 skip("Failed to create a D3D device, skipping tests.\n");
1386 goto cleanup;
1388 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1389 /* This skips the test on testbot Win 8 VMs. */
1390 if (hr == D3DERR_DEVICELOST)
1392 skip("Device is lost.\n");
1393 goto cleanup;
1395 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1397 hr = IDirect3DDevice8_GetDeviceCaps(device1, &caps);
1398 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1400 width = GetSystemMetrics(SM_CXSCREEN);
1401 height = GetSystemMetrics(SM_CYSCREEN);
1402 ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1403 ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1405 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1406 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1407 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1408 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1409 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1410 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1411 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1412 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1414 i = 1;
1415 vp.X = 10;
1416 vp.Y = 20;
1417 vp.Width = modes[i].w / 2;
1418 vp.Height = modes[i].h / 2;
1419 vp.MinZ = 0.2f;
1420 vp.MaxZ = 0.3f;
1421 hr = IDirect3DDevice8_SetViewport(device1, &vp);
1422 ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1424 hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1425 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1426 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1427 hr = IDirect3DDevice8_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1428 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1430 memset(&d3dpp, 0, sizeof(d3dpp));
1431 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1432 d3dpp.Windowed = FALSE;
1433 d3dpp.BackBufferWidth = modes[i].w;
1434 d3dpp.BackBufferHeight = modes[i].h;
1435 d3dpp.BackBufferFormat = d3ddm.Format;
1436 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1437 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1438 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1439 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1441 hr = IDirect3DDevice8_GetRenderState(device1, D3DRS_LIGHTING, &value);
1442 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1443 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1445 memset(&vp, 0, sizeof(vp));
1446 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1447 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1448 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1449 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1450 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u.\n", vp.Width, modes[i].w);
1451 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u.\n", vp.Height, modes[i].h);
1452 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1453 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1455 width = GetSystemMetrics(SM_CXSCREEN);
1456 height = GetSystemMetrics(SM_CYSCREEN);
1457 ok(width == modes[i].w, "Screen width is %u, expected %u.\n", width, modes[i].w);
1458 ok(height == modes[i].h, "Screen height is %u, expected %u.\n", height, modes[i].h);
1460 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1461 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1462 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1463 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1464 ok(surface_desc.Width == modes[i].w, "Back buffer width is %u, expected %u.\n",
1465 surface_desc.Width, modes[i].w);
1466 ok(surface_desc.Height == modes[i].h, "Back buffer height is %u, expected %u.\n",
1467 surface_desc.Height, modes[i].h);
1468 IDirect3DSurface8_Release(surface);
1470 memset(&d3dpp, 0, sizeof(d3dpp));
1471 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1472 d3dpp.Windowed = TRUE;
1473 d3dpp.BackBufferWidth = 400;
1474 d3dpp.BackBufferHeight = 300;
1475 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1476 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1477 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1478 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1479 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1481 memset(&vp, 0, sizeof(vp));
1482 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1483 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1484 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1485 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1486 ok(vp.Width == 400, "D3DVIEWPORT->Width = %u, expected 400.\n", vp.Width);
1487 ok(vp.Height == 300, "D3DVIEWPORT->Height = %u, expected 300.\n", vp.Height);
1488 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1489 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1491 width = GetSystemMetrics(SM_CXSCREEN);
1492 height = GetSystemMetrics(SM_CYSCREEN);
1493 ok(width == orig_width, "Screen width is %u, expected %u.\n", width, orig_width);
1494 ok(height == orig_height, "Screen height is %u, expected %u.\n", height, orig_height);
1496 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1497 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1498 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1499 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1500 ok(surface_desc.Width == 400, "Back buffer width is %u, expected 400.\n",
1501 surface_desc.Width);
1502 ok(surface_desc.Height == 300, "Back buffer height is %u, expected 300.\n",
1503 surface_desc.Height);
1504 IDirect3DSurface8_Release(surface);
1506 memset(&devmode, 0, sizeof(devmode));
1507 devmode.dmSize = sizeof(devmode);
1508 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1509 devmode.dmPelsWidth = modes[1].w;
1510 devmode.dmPelsHeight = modes[1].h;
1511 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1512 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1513 width = GetSystemMetrics(SM_CXSCREEN);
1514 height = GetSystemMetrics(SM_CYSCREEN);
1515 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1516 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1518 d3dpp.BackBufferWidth = 500;
1519 d3dpp.BackBufferHeight = 400;
1520 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1521 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1522 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1523 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1524 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1526 width = GetSystemMetrics(SM_CXSCREEN);
1527 height = GetSystemMetrics(SM_CYSCREEN);
1528 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1529 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1531 ZeroMemory(&vp, sizeof(vp));
1532 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1533 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1534 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
1535 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
1536 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
1537 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
1538 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
1539 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
1541 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1542 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1543 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1544 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1545 ok(surface_desc.Width == 500, "Back buffer width is %u, expected 500.\n",
1546 surface_desc.Width);
1547 ok(surface_desc.Height == 400, "Back buffer height is %u, expected 400.\n",
1548 surface_desc.Height);
1549 IDirect3DSurface8_Release(surface);
1551 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1552 devmode.dmPelsWidth = orig_width;
1553 devmode.dmPelsHeight = orig_height;
1554 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1555 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1556 width = GetSystemMetrics(SM_CXSCREEN);
1557 height = GetSystemMetrics(SM_CYSCREEN);
1558 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1559 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1561 winrect.left = 0;
1562 winrect.top = 0;
1563 winrect.right = 200;
1564 winrect.bottom = 150;
1565 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1566 ok(SetWindowPos(window, NULL, 0, 0,
1567 winrect.right-winrect.left,
1568 winrect.bottom-winrect.top,
1569 SWP_NOMOVE|SWP_NOZORDER),
1570 "SetWindowPos failed\n");
1572 memset(&d3dpp, 0, sizeof(d3dpp));
1573 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1574 d3dpp.Windowed = TRUE;
1575 d3dpp.BackBufferWidth = 0;
1576 d3dpp.BackBufferHeight = 0;
1577 d3dpp.BackBufferFormat = d3ddm.Format;
1578 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1579 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1580 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1581 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1583 ok(!d3dpp.BackBufferWidth, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1584 ok(!d3dpp.BackBufferHeight, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1585 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1586 d3dpp.BackBufferFormat, d3ddm.Format);
1587 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1588 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1589 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1590 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1591 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1592 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1593 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1594 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1595 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1596 d3dpp.FullScreen_RefreshRateInHz);
1597 ok(!d3dpp.FullScreen_PresentationInterval, "Got unexpected FullScreen_PresentationInterval %#x.\n",
1598 d3dpp.FullScreen_PresentationInterval);
1600 memset(&vp, 0, sizeof(vp));
1601 hr = IDirect3DDevice8_GetViewport(device1, &vp);
1602 ok(SUCCEEDED(hr), "GetViewport failed, hr %#x.\n", hr);
1603 if (SUCCEEDED(hr))
1605 ok(vp.X == 0, "D3DVIEWPORT->X = %u, expected 0.\n", vp.X);
1606 ok(vp.Y == 0, "D3DVIEWPORT->Y = %u, expected 0.\n", vp.Y);
1607 ok(vp.Width == 200, "D3DVIEWPORT->Width = %u, expected 200.\n", vp.Width);
1608 ok(vp.Height == 150, "D3DVIEWPORT->Height = %u, expected 150.\n", vp.Height);
1609 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %.8e, expected 0.\n", vp.MinZ);
1610 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %.8e, expected 1.\n", vp.MaxZ);
1613 hr = IDirect3DDevice8_GetRenderTarget(device1, &surface);
1614 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1615 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
1616 ok(hr == D3D_OK, "GetDesc failed, hr %#x.\n", hr);
1617 ok(surface_desc.Format == d3ddm.Format, "Got unexpected Format %#x, expected %#x.\n",
1618 surface_desc.Format, d3ddm.Format);
1619 ok(!surface_desc.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1620 ok(surface_desc.Width == 200, "Back buffer width is %u, expected 200.\n", surface_desc.Width);
1621 ok(surface_desc.Height == 150, "Back buffer height is %u, expected 150.\n", surface_desc.Height);
1622 IDirect3DSurface8_Release(surface);
1624 memset(&d3dpp, 0, sizeof(d3dpp));
1625 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1626 d3dpp.Windowed = TRUE;
1627 d3dpp.BackBufferWidth = 400;
1628 d3dpp.BackBufferHeight = 300;
1629 d3dpp.BackBufferFormat = d3ddm.Format;
1631 /* Reset fails if there is a resource in the default pool. */
1632 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &texture);
1633 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1634 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1635 ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1636 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1637 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1638 IDirect3DTexture8_Release(texture);
1639 /* Reset again to get the device out of the lost state. */
1640 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1641 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1642 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1643 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1645 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1647 IDirect3DVolumeTexture8 *volume_texture;
1649 hr = IDirect3DDevice8_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1650 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture);
1651 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1652 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1653 ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1654 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1655 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1656 hr, D3DERR_DEVICENOTRESET);
1657 IDirect3DVolumeTexture8_Release(volume_texture);
1658 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1659 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1660 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1661 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1663 else
1665 skip("Volume textures not supported.\n");
1668 /* Scratch, sysmem and managed pool resources are fine. */
1669 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1670 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1671 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1672 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1673 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1674 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1675 IDirect3DTexture8_Release(texture);
1677 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1678 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1679 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1680 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1681 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1682 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1683 IDirect3DTexture8_Release(texture);
1685 /* The depth stencil should get reset to the auto depth stencil when present. */
1686 hr = IDirect3DDevice8_SetRenderTarget(device1, NULL, NULL);
1687 ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1689 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1690 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1691 ok(!surface, "Depth / stencil buffer should be NULL.\n");
1693 d3dpp.EnableAutoDepthStencil = TRUE;
1694 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1695 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1696 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1698 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1699 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1700 ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1701 if (surface) IDirect3DSurface8_Release(surface);
1703 d3dpp.EnableAutoDepthStencil = FALSE;
1704 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1705 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1707 hr = IDirect3DDevice8_GetDepthStencilSurface(device1, &surface);
1708 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned %#x, expected %#x.\n", hr, D3DERR_NOTFOUND);
1709 ok(!surface, "Depth / stencil buffer should be NULL.\n");
1711 /* Will a sysmem or scratch resource survive while locked? */
1712 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &texture);
1713 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1714 hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1715 ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1716 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1717 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1718 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1719 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1720 IDirect3DTexture8_UnlockRect(texture, 0);
1721 IDirect3DTexture8_Release(texture);
1723 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &texture);
1724 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1725 hr = IDirect3DTexture8_LockRect(texture, 0, &lockrect, NULL, D3DLOCK_DISCARD);
1726 ok(SUCCEEDED(hr), "LockRect failed, hr %#x.\n", hr);
1727 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1728 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1729 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1730 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1731 IDirect3DTexture8_UnlockRect(texture, 0);
1732 IDirect3DTexture8_Release(texture);
1734 hr = IDirect3DDevice8_CreateTexture(device1, 16, 16, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture);
1735 ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1736 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1737 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1738 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1739 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1740 IDirect3DTexture8_Release(texture);
1742 /* A reference held to an implicit surface causes failures as well. */
1743 hr = IDirect3DDevice8_GetBackBuffer(device1, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1744 ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
1745 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1746 ok(hr == D3DERR_DEVICELOST, "Reset returned %#x, expected %#x.\n", hr, D3DERR_DEVICELOST);
1747 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1748 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1749 IDirect3DSurface8_Release(surface);
1750 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1751 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1752 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1753 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1755 /* Shaders are fine as well. */
1756 hr = IDirect3DDevice8_CreateVertexShader(device1, decl, simple_vs, &shader, 0);
1757 ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
1758 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1759 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1760 hr = IDirect3DDevice8_DeleteVertexShader(device1, shader);
1761 ok(SUCCEEDED(hr), "DeleteVertexShader failed, hr %#x.\n", hr);
1763 /* Try setting invalid modes. */
1764 memset(&d3dpp, 0, sizeof(d3dpp));
1765 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1766 d3dpp.Windowed = FALSE;
1767 d3dpp.BackBufferWidth = 32;
1768 d3dpp.BackBufferHeight = 32;
1769 d3dpp.BackBufferFormat = d3ddm.Format;
1770 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1771 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1772 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1773 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1775 memset(&d3dpp, 0, sizeof(d3dpp));
1776 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1777 d3dpp.Windowed = FALSE;
1778 d3dpp.BackBufferWidth = 801;
1779 d3dpp.BackBufferHeight = 600;
1780 d3dpp.BackBufferFormat = d3ddm.Format;
1781 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1782 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1783 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1784 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1786 memset(&d3dpp, 0, sizeof(d3dpp));
1787 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1788 d3dpp.Windowed = FALSE;
1789 d3dpp.BackBufferWidth = 0;
1790 d3dpp.BackBufferHeight = 0;
1791 d3dpp.BackBufferFormat = d3ddm.Format;
1792 hr = IDirect3DDevice8_Reset(device1, &d3dpp);
1793 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1794 hr = IDirect3DDevice8_TestCooperativeLevel(device1);
1795 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n", hr, D3DERR_DEVICENOTRESET);
1797 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
1798 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
1800 memset(&d3dpp, 0, sizeof(d3dpp));
1801 d3dpp.Windowed = TRUE;
1802 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1803 d3dpp.BackBufferFormat = d3ddm.Format;
1804 d3dpp.EnableAutoDepthStencil = FALSE;
1805 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1807 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1808 window, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2);
1809 if (FAILED(hr))
1811 skip("Failed to create device, hr %#x.\n", hr);
1812 goto cleanup;
1815 hr = IDirect3DDevice8_TestCooperativeLevel(device2);
1816 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
1818 d3dpp.Windowed = TRUE;
1819 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1820 d3dpp.BackBufferWidth = 400;
1821 d3dpp.BackBufferHeight = 300;
1822 d3dpp.BackBufferFormat = d3ddm.Format;
1823 d3dpp.EnableAutoDepthStencil = TRUE;
1824 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1826 hr = IDirect3DDevice8_Reset(device2, &d3dpp);
1827 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1828 if (FAILED(hr))
1829 goto cleanup;
1831 hr = IDirect3DDevice8_GetDepthStencilSurface(device2, &surface);
1832 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1833 ok(!!surface, "Depth / stencil buffer should not be NULL.\n");
1834 if (surface)
1835 IDirect3DSurface8_Release(surface);
1837 cleanup:
1838 HeapFree(GetProcessHeap(), 0, modes);
1839 if (device2)
1840 IDirect3DDevice8_Release(device2);
1841 if (device1)
1842 IDirect3DDevice8_Release(device1);
1843 IDirect3D8_Release(d3d8);
1844 DestroyWindow(window);
1847 static void test_scene(void)
1849 IDirect3DDevice8 *device;
1850 IDirect3D8 *d3d;
1851 ULONG refcount;
1852 HWND window;
1853 HRESULT hr;
1855 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1856 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1857 ok(!!window, "Failed to create a window.\n");
1858 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1859 ok(!!d3d, "Failed to create a D3D object.\n");
1860 if (!(device = create_device(d3d, window, NULL)))
1862 skip("Failed to create a 3D device, skipping test.\n");
1863 goto cleanup;
1866 /* Test an EndScene without BeginScene. Should return an error */
1867 hr = IDirect3DDevice8_EndScene(device);
1868 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1870 /* Test a normal BeginScene / EndScene pair, this should work */
1871 hr = IDirect3DDevice8_BeginScene(device);
1872 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1873 hr = IDirect3DDevice8_EndScene(device);
1874 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1876 /* Test another EndScene without having begun a new scene. Should return an error */
1877 hr = IDirect3DDevice8_EndScene(device);
1878 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1880 /* Two nested BeginScene and EndScene calls */
1881 hr = IDirect3DDevice8_BeginScene(device);
1882 ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
1883 hr = IDirect3DDevice8_BeginScene(device);
1884 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1885 hr = IDirect3DDevice8_EndScene(device);
1886 ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
1887 hr = IDirect3DDevice8_EndScene(device);
1888 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1890 /* StretchRect does not exit in Direct3D8, so no equivalent to the d3d9 stretchrect tests */
1892 refcount = IDirect3DDevice8_Release(device);
1893 ok(!refcount, "Device has %u references left.\n", refcount);
1894 cleanup:
1895 IDirect3D8_Release(d3d);
1896 DestroyWindow(window);
1899 static void test_shader(void)
1901 DWORD hPixelShader = 0, hVertexShader = 0;
1902 DWORD hPixelShader2 = 0, hVertexShader2 = 0;
1903 DWORD hTempHandle;
1904 D3DCAPS8 caps;
1905 DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
1906 IDirect3DDevice8 *device;
1907 IDirect3D8 *d3d;
1908 DWORD data_size;
1909 ULONG refcount;
1910 HWND window;
1911 HRESULT hr;
1912 void *data;
1914 static DWORD dwVertexDecl[] =
1916 D3DVSD_STREAM(0),
1917 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
1918 D3DVSD_END()
1920 DWORD decl_normal_float2[] =
1922 D3DVSD_STREAM(0),
1923 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
1924 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT2), /* D3DVSDE_NORMAL, Register v1 */
1925 D3DVSD_END()
1927 DWORD decl_normal_float4[] =
1929 D3DVSD_STREAM(0),
1930 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
1931 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT4), /* D3DVSDE_NORMAL, Register v1 */
1932 D3DVSD_END()
1934 DWORD decl_normal_d3dcolor[] =
1936 D3DVSD_STREAM(0),
1937 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3), /* D3DVSDE_POSITION, Register v0 */
1938 D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_D3DCOLOR),/* D3DVSDE_NORMAL, Register v1 */
1939 D3DVSD_END()
1941 const DWORD vertex_decl_size = sizeof(dwVertexDecl);
1942 const DWORD simple_vs_size = sizeof(simple_vs);
1943 const DWORD simple_ps_size = sizeof(simple_ps);
1945 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
1946 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1947 ok(!!window, "Failed to create a window.\n");
1948 d3d = Direct3DCreate8(D3D_SDK_VERSION);
1949 ok(!!d3d, "Failed to create a D3D object.\n");
1950 if (!(device = create_device(d3d, window, NULL)))
1952 skip("Failed to create a 3D device, skipping test.\n");
1953 goto cleanup;
1956 IDirect3DDevice8_GetDeviceCaps(device, &caps);
1958 /* Test setting and retrieving a FVF */
1959 hr = IDirect3DDevice8_SetVertexShader(device, fvf);
1960 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1961 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
1962 ok(SUCCEEDED(hr), "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1963 ok(hTempHandle == fvf, "Vertex shader %#08x is set, expected %#08x\n", hTempHandle, fvf);
1965 /* First create a vertex shader */
1966 hr = IDirect3DDevice8_SetVertexShader(device, 0);
1967 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1968 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, simple_vs, &hVertexShader, 0);
1969 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
1970 /* Msdn says that the new vertex shader is set immediately. This is wrong, apparently */
1971 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
1972 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1973 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
1974 /* Assign the shader, then verify that GetVertexShader works */
1975 hr = IDirect3DDevice8_SetVertexShader(device, hVertexShader);
1976 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1977 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
1978 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
1979 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
1980 /* Verify that we can retrieve the declaration */
1981 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, NULL, &data_size);
1982 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1983 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1984 data = HeapAlloc(GetProcessHeap(), 0, vertex_decl_size);
1985 data_size = 1;
1986 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, data, &data_size);
1987 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderDeclaration returned (%#08x), "
1988 "expected D3DERR_INVALIDCALL\n", hr);
1989 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
1990 data_size = vertex_decl_size;
1991 hr = IDirect3DDevice8_GetVertexShaderDeclaration(device, hVertexShader, data, &data_size);
1992 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderDeclaration returned %#08x\n", hr);
1993 ok(data_size == vertex_decl_size, "Got data_size %u, expected %u\n", data_size, vertex_decl_size);
1994 ok(!memcmp(data, dwVertexDecl, vertex_decl_size), "data not equal to shader declaration\n");
1995 HeapFree(GetProcessHeap(), 0, data);
1996 /* Verify that we can retrieve the shader function */
1997 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, NULL, &data_size);
1998 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
1999 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
2000 data = HeapAlloc(GetProcessHeap(), 0, simple_vs_size);
2001 data_size = 1;
2002 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, data, &data_size);
2003 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetVertexShaderFunction returned (%#08x), "
2004 "expected D3DERR_INVALIDCALL\n", hr);
2005 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
2006 data_size = simple_vs_size;
2007 hr = IDirect3DDevice8_GetVertexShaderFunction(device, hVertexShader, data, &data_size);
2008 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShaderFunction returned %#08x\n", hr);
2009 ok(data_size == simple_vs_size, "Got data_size %u, expected %u\n", data_size, simple_vs_size);
2010 ok(!memcmp(data, simple_vs, simple_vs_size), "data not equal to shader function\n");
2011 HeapFree(GetProcessHeap(), 0, data);
2012 /* Delete the assigned shader. This is supposed to work */
2013 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2014 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2015 /* The shader should be unset now */
2016 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2017 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
2018 ok(hTempHandle == 0, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, 0);
2020 /* Test a broken declaration. 3DMark2001 tries to use normals with 2 components
2021 * First try the fixed function shader function, then a custom one
2023 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float2, 0, &hVertexShader, 0);
2024 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2025 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float4, 0, &hVertexShader, 0);
2026 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2027 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_d3dcolor, 0, &hVertexShader, 0);
2028 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2030 hr = IDirect3DDevice8_CreateVertexShader(device, decl_normal_float2, simple_vs, &hVertexShader, 0);
2031 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2032 IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2034 if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 0))
2036 /* The same with a pixel shader */
2037 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader);
2038 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2039 /* Msdn says that the new pixel shader is set immediately. This is wrong, apparently */
2040 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2041 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2042 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
2043 /* Assign the shader, then verify that GetPixelShader works */
2044 hr = IDirect3DDevice8_SetPixelShader(device, hPixelShader);
2045 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
2046 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2047 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2048 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
2049 /* Verify that we can retrieve the shader function */
2050 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, NULL, &data_size);
2051 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
2052 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
2053 data = HeapAlloc(GetProcessHeap(), 0, simple_ps_size);
2054 data_size = 1;
2055 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, data, &data_size);
2056 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_GetPixelShaderFunction returned (%#08x), "
2057 "expected D3DERR_INVALIDCALL\n", hr);
2058 ok(data_size == 1, "Got data_size %u, expected 1\n", data_size);
2059 data_size = simple_ps_size;
2060 hr = IDirect3DDevice8_GetPixelShaderFunction(device, hPixelShader, data, &data_size);
2061 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShaderFunction returned %#08x\n", hr);
2062 ok(data_size == simple_ps_size, "Got data_size %u, expected %u\n", data_size, simple_ps_size);
2063 ok(!memcmp(data, simple_ps, simple_ps_size), "data not equal to shader function\n");
2064 HeapFree(GetProcessHeap(), 0, data);
2065 /* Delete the assigned shader. This is supposed to work */
2066 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2067 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2068 /* The shader should be unset now */
2069 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2070 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2071 ok(hTempHandle == 0, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, 0);
2073 /* What happens if a non-bound shader is deleted? */
2074 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader);
2075 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2076 hr = IDirect3DDevice8_CreatePixelShader(device, simple_ps, &hPixelShader2);
2077 ok(hr == D3D_OK, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
2079 hr = IDirect3DDevice8_SetPixelShader(device, hPixelShader);
2080 ok(hr == D3D_OK, "IDirect3DDevice8_SetPixelShader returned %#08x\n", hr);
2081 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader2);
2082 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2083 hr = IDirect3DDevice8_GetPixelShader(device, &hTempHandle);
2084 ok(hr == D3D_OK, "IDirect3DDevice8_GetPixelShader returned %#08x\n", hr);
2085 ok(hTempHandle == hPixelShader, "Pixel Shader %d is set, expected shader %d\n", hTempHandle, hPixelShader);
2086 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2087 ok(hr == D3D_OK, "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2089 /* Check for double delete. */
2090 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader2);
2091 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2092 hr = IDirect3DDevice8_DeletePixelShader(device, hPixelShader);
2093 ok(hr == D3DERR_INVALIDCALL || broken(hr == D3D_OK), "IDirect3DDevice8_DeletePixelShader returned %#08x\n", hr);
2095 else
2097 skip("Pixel shaders not supported\n");
2100 /* What happens if a non-bound shader is deleted? */
2101 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, NULL, &hVertexShader, 0);
2102 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2103 hr = IDirect3DDevice8_CreateVertexShader(device, dwVertexDecl, NULL, &hVertexShader2, 0);
2104 ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
2106 hr = IDirect3DDevice8_SetVertexShader(device, hVertexShader);
2107 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2108 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader2);
2109 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2110 hr = IDirect3DDevice8_GetVertexShader(device, &hTempHandle);
2111 ok(hr == D3D_OK, "IDirect3DDevice8_GetVertexShader returned %#08x\n", hr);
2112 ok(hTempHandle == hVertexShader, "Vertex Shader %d is set, expected shader %d\n", hTempHandle, hVertexShader);
2113 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2114 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2116 /* Check for double delete. */
2117 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader2);
2118 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2119 hr = IDirect3DDevice8_DeleteVertexShader(device, hVertexShader);
2120 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
2122 refcount = IDirect3DDevice8_Release(device);
2123 ok(!refcount, "Device has %u references left.\n", refcount);
2124 cleanup:
2125 IDirect3D8_Release(d3d);
2126 DestroyWindow(window);
2129 static void test_limits(void)
2131 IDirect3DTexture8 *texture;
2132 IDirect3DDevice8 *device;
2133 IDirect3D8 *d3d;
2134 unsigned int i;
2135 ULONG refcount;
2136 HWND window;
2137 HRESULT hr;
2139 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2140 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2141 ok(!!window, "Failed to create a window.\n");
2142 d3d = Direct3DCreate8(D3D_SDK_VERSION);
2143 ok(!!d3d, "Failed to create a D3D object.\n");
2144 if (!(device = create_device(d3d, window, NULL)))
2146 skip("Failed to create a 3D device, skipping test.\n");
2147 goto cleanup;
2150 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture);
2151 ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed with %#08x\n", hr);
2153 /* There are 8 texture stages. We should be able to access all of them */
2154 for (i = 0; i < 8; ++i)
2156 hr = IDirect3DDevice8_SetTexture(device, i, (IDirect3DBaseTexture8 *)texture);
2157 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
2158 hr = IDirect3DDevice8_SetTexture(device, i, NULL);
2159 ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture for sampler %d failed with %#08x\n", i, hr);
2160 hr = IDirect3DDevice8_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2161 ok(hr == D3D_OK, "IDirect3DDevice8_SetTextureStageState for texture %d failed with %#08x\n", i, hr);
2164 /* Investigations show that accessing higher textures stage states does
2165 * not return an error either. Writing to too high texture stages
2166 * (approximately texture 40) causes memory corruption in windows, so
2167 * there is no bounds checking. */
2168 IDirect3DTexture8_Release(texture);
2169 refcount = IDirect3DDevice8_Release(device);
2170 ok(!refcount, "Device has %u references left.\n", refcount);
2171 cleanup:
2172 IDirect3D8_Release(d3d);
2173 DestroyWindow(window);
2176 static void test_lights(void)
2178 IDirect3DDevice8 *device;
2179 IDirect3D8 *d3d8;
2180 ULONG refcount;
2181 HWND window;
2182 HRESULT hr;
2183 unsigned int i;
2184 BOOL enabled;
2185 D3DCAPS8 caps;
2187 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2188 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2189 ok(!!window, "Failed to create a window.\n");
2190 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2191 ok(!!d3d8, "Failed to create a D3D object.\n");
2192 if (!(device = create_device(d3d8, window, NULL)))
2194 skip("Failed to create a 3D device, skipping test.\n");
2195 goto cleanup;
2198 memset(&caps, 0, sizeof(caps));
2199 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
2200 ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %08x\n", hr);
2202 for(i = 1; i <= caps.MaxActiveLights; i++) {
2203 hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
2204 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2205 hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
2206 ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL),
2207 "GetLightEnable on light %u failed with %08x\n", i, hr);
2208 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2211 /* TODO: Test the rendering results in this situation */
2212 hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
2213 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2214 hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
2215 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2216 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2217 hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
2218 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2220 for(i = 1; i <= caps.MaxActiveLights; i++) {
2221 hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
2222 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2225 refcount = IDirect3DDevice8_Release(device);
2226 ok(!refcount, "Device has %u references left.\n", refcount);
2227 cleanup:
2228 IDirect3D8_Release(d3d8);
2229 DestroyWindow(window);
2232 static void test_render_zero_triangles(void)
2234 IDirect3DDevice8 *device;
2235 IDirect3D8 *d3d8;
2236 ULONG refcount;
2237 HWND window;
2238 HRESULT hr;
2240 static const struct
2242 struct vec3 position;
2243 struct vec3 normal;
2244 DWORD diffuse;
2246 quad[] =
2248 {{0.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2249 {{0.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2250 {{1.0f, 0.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2251 {{1.0f, -1.0f, 0.1f}, {1.0f, 1.0f, 1.0f}, 0xff0000ff},
2254 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2255 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2256 ok(!!window, "Failed to create a window.\n");
2257 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2258 ok(!!d3d8, "Failed to create a D3D object.\n");
2259 if (!(device = create_device(d3d8, window, NULL)))
2261 skip("Failed to create a 3D device, skipping test.\n");
2262 goto cleanup;
2265 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2266 ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
2268 hr = IDirect3DDevice8_BeginScene(device);
2269 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2270 hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 0 /* NumVerts */,
2271 0 /* PrimCount */, NULL, D3DFMT_INDEX16, quad, sizeof(quad[0]));
2272 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2273 hr = IDirect3DDevice8_EndScene(device);
2274 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2276 IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2278 refcount = IDirect3DDevice8_Release(device);
2279 ok(!refcount, "Device has %u references left.\n", refcount);
2280 cleanup:
2281 IDirect3D8_Release(d3d8);
2282 DestroyWindow(window);
2285 static void test_depth_stencil_reset(void)
2287 D3DPRESENT_PARAMETERS present_parameters;
2288 D3DDISPLAYMODE display_mode;
2289 IDirect3DSurface8 *surface, *orig_rt;
2290 IDirect3DDevice8 *device = NULL;
2291 IDirect3D8 *d3d8;
2292 UINT refcount;
2293 HRESULT hr;
2294 HWND hwnd;
2296 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
2297 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2298 ok(!!hwnd, "Failed to create a window.\n");
2299 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2300 ok(!!d3d8, "Failed to create a D3D object.\n");
2302 IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &display_mode);
2303 memset(&present_parameters, 0, sizeof(present_parameters));
2304 present_parameters.Windowed = TRUE;
2305 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2306 present_parameters.BackBufferFormat = display_mode.Format;
2307 present_parameters.EnableAutoDepthStencil = TRUE;
2308 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2310 hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2311 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
2312 if(FAILED(hr))
2314 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2315 goto cleanup;
2318 hr = IDirect3DDevice8_GetRenderTarget(device, &orig_rt);
2319 ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2321 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2322 ok(SUCCEEDED(hr), "TestCooperativeLevel failed with %#x\n", hr);
2324 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
2325 ok(hr == D3D_OK, "SetRenderTarget failed with 0x%08x\n", hr);
2327 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
2328 ok(hr == D3D_OK, "GetRenderTarget failed with 0x%08x\n", hr);
2329 ok(surface == orig_rt, "Render target is %p, should be %p\n", surface, orig_rt);
2330 if (surface) IDirect3DSurface8_Release(surface);
2331 IDirect3DSurface8_Release(orig_rt);
2333 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2334 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2335 ok(surface == NULL, "Depth stencil should be NULL\n");
2337 present_parameters.EnableAutoDepthStencil = TRUE;
2338 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2339 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2340 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2342 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2343 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2344 ok(surface != NULL, "Depth stencil should not be NULL\n");
2345 if (surface) IDirect3DSurface8_Release(surface);
2347 present_parameters.EnableAutoDepthStencil = FALSE;
2348 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2349 ok(hr == D3D_OK, "Reset failed with 0x%08x\n", hr);
2351 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2352 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2353 ok(surface == NULL, "Depth stencil should be NULL\n");
2355 refcount = IDirect3DDevice8_Release(device);
2356 ok(!refcount, "Device has %u references left.\n", refcount);
2357 device = NULL;
2359 IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &display_mode );
2361 ZeroMemory( &present_parameters, sizeof(present_parameters) );
2362 present_parameters.Windowed = TRUE;
2363 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2364 present_parameters.BackBufferFormat = display_mode.Format;
2365 present_parameters.EnableAutoDepthStencil = FALSE;
2366 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2368 hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
2369 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device );
2371 if(FAILED(hr))
2373 skip("could not create device, IDirect3D8_CreateDevice returned %#x\n", hr);
2374 goto cleanup;
2377 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2378 ok(hr == D3D_OK, "IDirect3DDevice8_TestCooperativeLevel after creation returned %#x\n", hr);
2380 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
2381 present_parameters.Windowed = TRUE;
2382 present_parameters.BackBufferWidth = 400;
2383 present_parameters.BackBufferHeight = 300;
2384 present_parameters.EnableAutoDepthStencil = TRUE;
2385 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
2387 hr = IDirect3DDevice8_Reset(device, &present_parameters);
2388 ok(hr == D3D_OK, "IDirect3DDevice8_Reset failed with 0x%08x\n", hr);
2390 if (FAILED(hr)) goto cleanup;
2392 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surface);
2393 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2394 ok(surface != NULL, "Depth stencil should not be NULL\n");
2395 if (surface) IDirect3DSurface8_Release(surface);
2397 cleanup:
2398 if (device)
2400 refcount = IDirect3DDevice8_Release(device);
2401 ok(!refcount, "Device has %u references left.\n", refcount);
2403 IDirect3D8_Release(d3d8);
2404 DestroyWindow(hwnd);
2407 static HWND filter_messages;
2409 enum message_window
2411 DEVICE_WINDOW,
2412 FOCUS_WINDOW,
2415 struct message
2417 UINT message;
2418 enum message_window window;
2419 BOOL check_wparam;
2420 WPARAM expect_wparam;
2423 static const struct message *expect_messages;
2424 static HWND device_window, focus_window;
2425 static LONG windowposchanged_received, syscommand_received;
2427 struct wndproc_thread_param
2429 HWND dummy_window;
2430 HANDLE window_created;
2431 HANDLE test_finished;
2432 BOOL running_in_foreground;
2435 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2437 if (filter_messages && filter_messages == hwnd)
2439 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2440 todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2443 if (expect_messages)
2445 HWND w;
2447 switch (expect_messages->window)
2449 case DEVICE_WINDOW:
2450 w = device_window;
2451 break;
2453 case FOCUS_WINDOW:
2454 w = focus_window;
2455 break;
2457 default:
2458 w = NULL;
2459 break;
2462 if (hwnd == w && expect_messages->message == message)
2464 if (expect_messages->check_wparam)
2465 ok(wparam == expect_messages->expect_wparam,
2466 "Got unexpected wparam %lx for message %x, expected %lx.\n",
2467 wparam, message, expect_messages->expect_wparam);
2469 ++expect_messages;
2473 /* KDE randomly does something with the hidden window during the
2474 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
2475 * message. A WM_WINDOWPOSCHANGED message is not generated, so
2476 * just flag WM_WINDOWPOSCHANGED as bad. */
2477 if (message == WM_WINDOWPOSCHANGED)
2478 InterlockedIncrement(&windowposchanged_received);
2479 else if (message == WM_SYSCOMMAND)
2480 InterlockedIncrement(&syscommand_received);
2482 return DefWindowProcA(hwnd, message, wparam, lparam);
2485 static DWORD WINAPI wndproc_thread(void *param)
2487 struct wndproc_thread_param *p = param;
2488 DWORD res;
2489 BOOL ret;
2491 p->dummy_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2492 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
2493 registry_mode.dmPelsHeight, 0, 0, 0, 0);
2494 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2496 ret = SetEvent(p->window_created);
2497 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2499 for (;;)
2501 MSG msg;
2503 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
2504 res = WaitForSingleObject(p->test_finished, 100);
2505 if (res == WAIT_OBJECT_0) break;
2506 if (res != WAIT_TIMEOUT)
2508 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2509 break;
2513 DestroyWindow(p->dummy_window);
2515 return 0;
2518 static void test_wndproc(void)
2520 struct wndproc_thread_param thread_params;
2521 struct device_desc device_desc;
2522 IDirect3DDevice8 *device;
2523 WNDCLASSA wc = {0};
2524 IDirect3D8 *d3d8;
2525 HANDLE thread;
2526 LONG_PTR proc;
2527 ULONG ref;
2528 DWORD res, tid;
2529 HWND tmp;
2530 UINT i, adapter_mode_count;
2531 HRESULT hr;
2532 D3DDISPLAYMODE d3ddm;
2533 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
2534 DEVMODEW devmode;
2535 LONG change_ret;
2536 BOOL ret;
2538 static const struct message create_messages[] =
2540 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2541 /* Do not test wparam here. If device creation succeeds,
2542 * wparam is WA_ACTIVE. If device creation fails (testbot)
2543 * wparam is set to WA_INACTIVE on some Windows versions. */
2544 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
2545 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
2546 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2547 {WM_MOVE, DEVICE_WINDOW, FALSE, 0},
2548 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
2549 {0, 0, FALSE, 0},
2551 static const struct message focus_loss_messages[] =
2553 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
2554 * not reliable on X11 WMs. When the window focus follows the
2555 * mouse pointer the message is not sent.
2556 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
2557 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2558 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2559 * not deterministic. */
2560 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2561 /* Windows sends WM_ACTIVATE to the device window, indicating that
2562 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
2563 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
2564 * leaves the device window active, breaking re-activation in the
2565 * lost device test.
2566 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
2567 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2568 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
2569 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2570 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
2571 * not deterministic. It may be sent after the focus window handling
2572 * or before. */
2573 {0, 0, FALSE, 0},
2575 static const struct message reactivate_messages[] =
2577 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2578 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2579 {WM_MOVE, DEVICE_WINDOW, FALSE, 0},
2580 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
2581 {0, 0, FALSE, 0},
2583 static const struct message focus_loss_messages_hidden[] =
2585 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2586 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2587 {0, 0, FALSE, 0},
2589 static const struct message focus_loss_messages_filtered[] =
2591 /* WM_ACTIVATE is delivered to the window proc because it is
2592 * generated by SetForegroundWindow before the d3d routine
2593 * starts it work. Don't check for it due to focus-follows-mouse
2594 * WMs though. */
2595 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
2596 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2597 {0, 0, FALSE, 0},
2599 static const struct message reactivate_messages_filtered[] =
2601 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
2602 {0, 0, FALSE, 0},
2604 static const struct message sc_restore_messages[] =
2606 /* WM_SYSCOMMAND is delivered only once, after d3d has already
2607 * processed it. Our wndproc has no way to prevent d3d from
2608 * handling the message. The second DefWindowProc call done by
2609 * our wndproc doesn't do any changes to the window because it
2610 * is already restored due to d3d's handling. */
2611 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2612 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2613 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
2614 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
2615 {0, 0, FALSE, 0},
2617 static const struct message sc_minimize_messages[] =
2619 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
2620 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2621 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2622 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2623 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
2624 {0, 0, FALSE, 0},
2626 static const struct message sc_maximize_messages[] =
2628 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
2629 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2630 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2631 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2632 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MAXIMIZED},
2633 {0, 0, FALSE, 0},
2636 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
2637 ok(!!d3d8, "Failed to create a D3D object.\n");
2639 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
2640 for (i = 0; i < adapter_mode_count; ++i)
2642 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm);
2643 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2645 if (d3ddm.Format != D3DFMT_X8R8G8B8)
2646 continue;
2647 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
2648 continue;
2649 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
2650 * refuses to create a device at these sizes. */
2651 if (d3ddm.Width < 640 || d3ddm.Height < 480)
2652 continue;
2654 if (!user32_width)
2656 user32_width = d3ddm.Width;
2657 user32_height = d3ddm.Height;
2658 continue;
2661 /* Make sure the d3d mode is smaller in width or height and at most
2662 * equal in the other dimension than the mode passed to
2663 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
2664 * the ChangeDisplaySettings parameters + 12. */
2665 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
2666 continue;
2667 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
2669 d3d_width = d3ddm.Width;
2670 d3d_height = d3ddm.Height;
2671 break;
2673 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
2675 d3d_width = user32_width;
2676 d3d_height = user32_height;
2677 user32_width = d3ddm.Width;
2678 user32_height = d3ddm.Height;
2679 break;
2683 if (!d3d_width)
2685 skip("Could not find adequate modes, skipping mode tests.\n");
2686 IDirect3D8_Release(d3d8);
2687 return;
2690 wc.lpfnWndProc = test_proc;
2691 wc.lpszClassName = "d3d8_test_wndproc_wc";
2692 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2694 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
2695 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2696 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
2697 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2699 memset(&devmode, 0, sizeof(devmode));
2700 devmode.dmSize = sizeof(devmode);
2701 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2702 devmode.dmPelsWidth = user32_width;
2703 devmode.dmPelsHeight = user32_height;
2704 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2705 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2707 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2708 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2709 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
2710 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2711 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2712 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2714 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2715 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2717 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2718 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2719 (LONG_PTR)test_proc, proc);
2720 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2721 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2722 (LONG_PTR)test_proc, proc);
2724 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2725 device_window, focus_window, thread_params.dummy_window);
2727 tmp = GetFocus();
2728 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2729 if (thread_params.running_in_foreground)
2731 tmp = GetForegroundWindow();
2732 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2733 thread_params.dummy_window, tmp);
2735 else
2736 skip("Not running in foreground, skip foreground window test\n");
2738 flush_events();
2740 expect_messages = create_messages;
2742 device_desc.device_window = device_window;
2743 device_desc.width = d3d_width;
2744 device_desc.height = d3d_height;
2745 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
2746 if (!(device = create_device(d3d8, focus_window, &device_desc)))
2748 skip("Failed to create a D3D device, skipping tests.\n");
2749 goto done;
2752 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2753 expect_messages->message, expect_messages->window);
2754 expect_messages = NULL;
2756 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2758 tmp = GetFocus();
2759 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2760 tmp = GetForegroundWindow();
2761 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2763 SetForegroundWindow(focus_window);
2764 flush_events();
2766 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2767 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2768 (LONG_PTR)test_proc, proc);
2770 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2771 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
2773 /* Change the mode while the device is in use and then drop focus. */
2774 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2775 devmode.dmPelsWidth = user32_width;
2776 devmode.dmPelsHeight = user32_height;
2777 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2778 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
2780 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
2781 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
2782 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
2783 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2784 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
2785 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
2787 expect_messages = focus_loss_messages;
2788 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
2789 * manually changing the focus. It generates the same messages, but the task
2790 * bar still shows the previous foreground window as active, and the window has
2791 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
2792 * the device is difficult, see below. */
2793 SetForegroundWindow(GetDesktopWindow());
2794 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2795 expect_messages->message, expect_messages->window);
2796 expect_messages = NULL;
2797 tmp = GetFocus();
2798 ok(tmp != device_window, "The device window is active.\n");
2799 ok(tmp != focus_window, "The focus window is active.\n");
2801 /* The Present call is necessary to make native realize the device is lost. */
2802 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2803 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
2804 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2805 /* Focus-follows-mouse WMs prematurely reactivate our window. */
2806 todo_wine_if (hr == D3DERR_DEVICENOTRESET)
2807 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
2809 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2810 ok(ret, "Failed to get display mode.\n");
2811 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2812 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2813 devmode.dmPelsWidth, devmode.dmPelsHeight);
2815 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
2816 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
2817 * restore is triggered by the user. */
2818 expect_messages = reactivate_messages;
2819 ShowWindow(focus_window, SW_MINIMIZE);
2820 ShowWindow(focus_window, SW_RESTORE);
2821 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
2822 SetForegroundWindow(focus_window);
2823 flush_events();
2824 SetForegroundWindow(focus_window);
2825 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
2826 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2827 expect_messages->message, expect_messages->window, i);
2828 expect_messages = NULL;
2830 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2831 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
2833 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2834 ok(ret, "Failed to get display mode.\n");
2835 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2836 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2837 devmode.dmPelsWidth, devmode.dmPelsHeight);
2839 hr = reset_device(device, &device_desc);
2840 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2842 ShowWindow(device_window, SW_HIDE);
2843 flush_events();
2845 expect_messages = focus_loss_messages_hidden;
2846 windowposchanged_received = 0;
2847 SetForegroundWindow(GetDesktopWindow());
2848 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2849 expect_messages->message, expect_messages->window);
2850 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
2851 expect_messages = NULL;
2852 flush_events();
2854 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2855 ok(ret, "Failed to get display mode.\n");
2856 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
2857 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
2859 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
2860 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
2861 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
2862 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
2863 flush_events();
2865 syscommand_received = 0;
2866 expect_messages = sc_restore_messages;
2867 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
2868 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2869 expect_messages->message, expect_messages->window);
2870 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
2871 expect_messages = NULL;
2872 flush_events();
2874 expect_messages = sc_minimize_messages;
2875 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2876 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2877 expect_messages->message, expect_messages->window);
2878 expect_messages = NULL;
2879 flush_events();
2881 expect_messages = sc_maximize_messages;
2882 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2883 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2884 expect_messages->message, expect_messages->window);
2885 expect_messages = NULL;
2886 flush_events();
2888 SetForegroundWindow(GetDesktopWindow());
2889 ShowWindow(device_window, SW_MINIMIZE);
2890 ShowWindow(focus_window, SW_MINIMIZE);
2891 ShowWindow(focus_window, SW_RESTORE);
2892 SetForegroundWindow(focus_window);
2893 flush_events();
2895 /* Releasing a device in lost state breaks follow-up tests on native. */
2896 hr = reset_device(device, &device_desc);
2897 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2899 filter_messages = focus_window;
2900 ref = IDirect3DDevice8_Release(device);
2901 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2903 /* Fix up the mode until Wine's device release behavior is fixed. */
2904 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2905 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2907 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2908 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2909 (LONG_PTR)test_proc, proc);
2911 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
2912 * on native in the test below. It isn't needed anyways. Creating the third
2913 * device will show it again. */
2914 filter_messages = NULL;
2915 ShowWindow(device_window, SW_HIDE);
2916 /* Remove the maximized state from the SYSCOMMAND test while we're not
2917 * interfering with a device. */
2918 ShowWindow(focus_window, SW_SHOWNORMAL);
2919 filter_messages = focus_window;
2921 device_desc.device_window = focus_window;
2922 if (!(device = create_device(d3d8, focus_window, &device_desc)))
2924 skip("Failed to create a D3D device, skipping tests.\n");
2925 goto done;
2928 filter_messages = NULL;
2930 expect_messages = focus_loss_messages_filtered;
2931 windowposchanged_received = 0;
2932 SetForegroundWindow(GetDesktopWindow());
2933 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2934 expect_messages->message, expect_messages->window);
2935 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
2936 expect_messages = NULL;
2938 /* The window is iconic even though no message was sent. */
2939 ok(IsIconic(focus_window), "The focus window is not iconic.\n");
2941 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2942 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
2944 syscommand_received = 0;
2945 expect_messages = sc_restore_messages;
2946 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
2947 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2948 expect_messages->message, expect_messages->window);
2949 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
2950 expect_messages = NULL;
2951 flush_events();
2953 /* For FVWM. */
2954 ShowWindow(focus_window, SW_RESTORE);
2955 flush_events();
2957 expect_messages = sc_minimize_messages;
2958 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2959 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2960 expect_messages->message, expect_messages->window);
2961 expect_messages = NULL;
2962 /* Needed to make the next test reliably send WM_SIZE(SIZE_MAXIMIZED). Without
2963 * this call it sends WM_SIZE(SIZE_RESTORED). */
2964 ShowWindow(focus_window, SW_RESTORE);
2965 flush_events();
2967 expect_messages = sc_maximize_messages;
2968 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2969 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it.\n",
2970 expect_messages->message, expect_messages->window);
2971 expect_messages = NULL;
2972 SetForegroundWindow(GetDesktopWindow());
2973 flush_events();
2975 /* ShowWindow(SW_RESTORE); SetForegroundWindow(desktop); SetForegroundWindow(focus);
2976 * results in the second SetForegroundWindow call failing and the device not being
2977 * restored on native. Directly using ShowWindow(SW_RESTORE) works, but it means
2978 * we cannot test for the absence of WM_WINDOWPOSCHANGED messages. */
2979 expect_messages = reactivate_messages_filtered;
2980 ShowWindow(focus_window, SW_RESTORE);
2981 SetForegroundWindow(focus_window);
2982 flush_events();
2983 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it\n",
2984 expect_messages->message, expect_messages->window);
2985 expect_messages = NULL;
2987 filter_messages = focus_window;
2988 hr = IDirect3DDevice8_TestCooperativeLevel(device);
2989 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
2991 hr = reset_device(device, &device_desc);
2992 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2994 ref = IDirect3DDevice8_Release(device);
2995 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
2997 device_desc.device_window = device_window;
2998 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3000 skip("Failed to create a D3D device, skipping tests.\n");
3001 goto done;
3004 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3005 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3007 ref = IDirect3DDevice8_Release(device);
3008 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3010 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3011 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3012 (LONG_PTR)DefWindowProcA, proc);
3014 done:
3015 filter_messages = NULL;
3016 IDirect3D8_Release(d3d8);
3018 SetEvent(thread_params.test_finished);
3019 WaitForSingleObject(thread, INFINITE);
3020 CloseHandle(thread_params.test_finished);
3021 CloseHandle(thread_params.window_created);
3022 CloseHandle(thread);
3024 DestroyWindow(device_window);
3025 DestroyWindow(focus_window);
3026 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3029 static void test_wndproc_windowed(void)
3031 struct wndproc_thread_param thread_params;
3032 struct device_desc device_desc;
3033 IDirect3DDevice8 *device;
3034 WNDCLASSA wc = {0};
3035 IDirect3D8 *d3d8;
3036 HANDLE thread;
3037 LONG_PTR proc;
3038 HRESULT hr;
3039 ULONG ref;
3040 DWORD res, tid;
3041 HWND tmp;
3043 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3044 ok(!!d3d8, "Failed to create a D3D object.\n");
3046 wc.lpfnWndProc = test_proc;
3047 wc.lpszClassName = "d3d8_test_wndproc_wc";
3048 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3050 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3051 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3052 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3053 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3055 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3056 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3057 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3058 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test",
3059 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3060 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3061 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3062 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3064 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3065 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3067 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3068 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3069 (LONG_PTR)test_proc, proc);
3070 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3071 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3072 (LONG_PTR)test_proc, proc);
3074 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3075 device_window, focus_window, thread_params.dummy_window);
3077 tmp = GetFocus();
3078 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3079 if (thread_params.running_in_foreground)
3081 tmp = GetForegroundWindow();
3082 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3083 thread_params.dummy_window, tmp);
3085 else
3086 skip("Not running in foreground, skip foreground window test\n");
3088 filter_messages = focus_window;
3090 device_desc.device_window = device_window;
3091 device_desc.width = registry_mode.dmPelsWidth;
3092 device_desc.height = registry_mode.dmPelsHeight;
3093 device_desc.flags = 0;
3094 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3096 skip("Failed to create a D3D device, skipping tests.\n");
3097 goto done;
3100 tmp = GetFocus();
3101 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3102 tmp = GetForegroundWindow();
3103 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3104 thread_params.dummy_window, tmp);
3106 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3107 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3108 (LONG_PTR)test_proc, proc);
3110 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3111 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3112 (LONG_PTR)test_proc, proc);
3114 filter_messages = NULL;
3116 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3117 hr = reset_device(device, &device_desc);
3118 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3120 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3121 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3122 (LONG_PTR)test_proc, proc);
3124 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3125 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3127 device_desc.flags = 0;
3128 hr = reset_device(device, &device_desc);
3129 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3131 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3132 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3133 (LONG_PTR)test_proc, proc);
3135 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3136 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3137 (LONG_PTR)test_proc, proc);
3139 filter_messages = focus_window;
3141 ref = IDirect3DDevice8_Release(device);
3142 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3144 filter_messages = device_window;
3146 device_desc.device_window = focus_window;
3147 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3149 skip("Failed to create a D3D device, skipping tests.\n");
3150 goto done;
3153 filter_messages = NULL;
3155 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3156 hr = reset_device(device, &device_desc);
3157 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3159 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3160 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3161 (LONG_PTR)test_proc, proc);
3163 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3164 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3166 device_desc.flags = 0;
3167 hr = reset_device(device, &device_desc);
3168 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3170 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3171 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3172 (LONG_PTR)test_proc, proc);
3174 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3175 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3176 (LONG_PTR)test_proc, proc);
3178 filter_messages = device_window;
3180 ref = IDirect3DDevice8_Release(device);
3181 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3183 device_desc.device_window = device_window;
3184 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3186 skip("Failed to create a D3D device, skipping tests.\n");
3187 goto done;
3190 filter_messages = NULL;
3192 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3193 hr = reset_device(device, &device_desc);
3194 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3196 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3197 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3198 (LONG_PTR)test_proc, proc);
3200 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3201 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3203 device_desc.flags = 0;
3204 hr = reset_device(device, &device_desc);
3205 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3207 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3208 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3209 (LONG_PTR)test_proc, proc);
3211 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3212 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3213 (LONG_PTR)test_proc, proc);
3215 filter_messages = device_window;
3217 ref = IDirect3DDevice8_Release(device);
3218 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3220 done:
3221 filter_messages = NULL;
3222 IDirect3D8_Release(d3d8);
3224 SetEvent(thread_params.test_finished);
3225 WaitForSingleObject(thread, INFINITE);
3226 CloseHandle(thread_params.test_finished);
3227 CloseHandle(thread_params.window_created);
3228 CloseHandle(thread);
3230 DestroyWindow(device_window);
3231 DestroyWindow(focus_window);
3232 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
3235 static inline void set_fpu_cw(WORD cw)
3237 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3238 #define D3D8_TEST_SET_FPU_CW 1
3239 __asm__ volatile ("fnclex");
3240 __asm__ volatile ("fldcw %0" : : "m" (cw));
3241 #elif defined(__i386__) && defined(_MSC_VER)
3242 #define D3D8_TEST_SET_FPU_CW 1
3243 __asm fnclex;
3244 __asm fldcw cw;
3245 #endif
3248 static inline WORD get_fpu_cw(void)
3250 WORD cw = 0;
3251 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
3252 #define D3D8_TEST_GET_FPU_CW 1
3253 __asm__ volatile ("fnstcw %0" : "=m" (cw));
3254 #elif defined(__i386__) && defined(_MSC_VER)
3255 #define D3D8_TEST_GET_FPU_CW 1
3256 __asm fnstcw cw;
3257 #endif
3258 return cw;
3261 static WORD callback_cw, callback_set_cw;
3262 static DWORD callback_tid;
3264 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
3266 *out = NULL;
3267 return E_NOINTERFACE;
3270 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
3272 callback_cw = get_fpu_cw();
3273 set_fpu_cw(callback_set_cw);
3274 callback_tid = GetCurrentThreadId();
3275 return 2;
3278 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
3280 callback_cw = get_fpu_cw();
3281 set_fpu_cw(callback_set_cw);
3282 callback_tid = GetCurrentThreadId();
3283 return 1;
3286 static const IUnknownVtbl dummy_object_vtbl =
3288 dummy_object_QueryInterface,
3289 dummy_object_AddRef,
3290 dummy_object_Release,
3293 static const GUID d3d8_private_data_test_guid =
3295 0xfdb37466,
3296 0x428f,
3297 0x4edf,
3298 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
3301 static void test_fpu_setup(void)
3303 #if defined(D3D8_TEST_SET_FPU_CW) && defined(D3D8_TEST_GET_FPU_CW)
3304 struct device_desc device_desc;
3305 IDirect3DDevice8 *device;
3306 D3DDISPLAYMODE d3ddm;
3307 IDirect3D8 *d3d8;
3308 HWND window;
3309 HRESULT hr;
3310 WORD cw;
3311 IDirect3DSurface8 *surface;
3312 IUnknown dummy_object = {&dummy_object_vtbl};
3314 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_CAPTION, 0, 0,
3315 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
3316 ok(!!window, "Failed to create a window.\n");
3317 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3318 ok(!!d3d8, "Failed to create a D3D object.\n");
3320 hr = IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
3321 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
3323 device_desc.device_window = window;
3324 device_desc.width = 640;
3325 device_desc.height = 480;
3326 device_desc.flags = 0;
3328 set_fpu_cw(0xf60);
3329 cw = get_fpu_cw();
3330 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3332 if (!(device = create_device(d3d8, window, &device_desc)))
3334 skip("Failed to create a 3D device, skipping test.\n");
3335 set_fpu_cw(0x37f);
3336 goto done;
3339 cw = get_fpu_cw();
3340 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3342 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3343 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3345 callback_set_cw = 0xf60;
3346 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3347 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3348 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
3349 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
3350 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3351 cw = get_fpu_cw();
3352 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3354 callback_cw = 0;
3355 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3356 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3357 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
3358 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
3359 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3361 callback_set_cw = 0x7f;
3362 set_fpu_cw(0x7f);
3364 IDirect3DSurface8_Release(surface);
3366 callback_cw = 0;
3367 IDirect3DDevice8_Release(device);
3368 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
3369 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3371 cw = get_fpu_cw();
3372 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
3373 set_fpu_cw(0xf60);
3374 cw = get_fpu_cw();
3375 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3377 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
3378 device = create_device(d3d8, window, &device_desc);
3379 ok(!!device, "CreateDevice failed.\n");
3381 cw = get_fpu_cw();
3382 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
3384 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
3385 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
3387 callback_cw = 0;
3388 callback_set_cw = 0x37f;
3389 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
3390 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
3391 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
3392 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
3393 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3394 cw = get_fpu_cw();
3395 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
3397 IDirect3DSurface8_Release(surface);
3399 callback_cw = 0;
3400 IDirect3DDevice8_Release(device);
3401 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0x37f.\n", callback_cw);
3402 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
3404 done:
3405 DestroyWindow(window);
3406 IDirect3D8_Release(d3d8);
3407 #endif
3410 static void test_ApplyStateBlock(void)
3412 IDirect3DDevice8 *device;
3413 IDirect3D8 *d3d8;
3414 HWND window;
3415 HRESULT hr;
3416 DWORD received, token;
3418 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3419 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3420 ok(!!window, "Failed to create a window.\n");
3421 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3422 ok(!!d3d8, "Failed to create a D3D object.\n");
3423 if (!(device = create_device(d3d8, window, NULL)))
3425 skip("Failed to create a 3D device, skipping test.\n");
3426 goto cleanup;
3429 IDirect3DDevice8_BeginStateBlock(device);
3430 IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
3431 IDirect3DDevice8_EndStateBlock(device, &token);
3432 ok(token, "Received zero stateblock handle.\n");
3433 IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
3435 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3436 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3437 ok(!received, "Expected = FALSE, received TRUE.\n");
3439 hr = IDirect3DDevice8_ApplyStateBlock(device, 0);
3440 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3441 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3442 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3443 ok(!received, "Expected FALSE, received TRUE.\n");
3445 hr = IDirect3DDevice8_ApplyStateBlock(device, token);
3446 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3447 hr = IDirect3DDevice8_GetRenderState(device, D3DRS_ZENABLE, &received);
3448 ok(hr == D3D_OK, "Expected D3D_OK, received %#x.\n", hr);
3449 ok(received, "Expected TRUE, received FALSE.\n");
3451 IDirect3DDevice8_DeleteStateBlock(device, token);
3452 IDirect3DDevice8_Release(device);
3453 cleanup:
3454 IDirect3D8_Release(d3d8);
3455 DestroyWindow(window);
3458 static void test_depth_stencil_size(void)
3460 IDirect3DDevice8 *device;
3461 IDirect3DSurface8 *ds, *rt, *ds_bigger, *ds_bigger2;
3462 IDirect3DSurface8 *surf;
3463 IDirect3D8 *d3d8;
3464 HRESULT hr;
3465 HWND hwnd;
3467 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3468 100, 100, 160, 160, NULL, NULL, NULL, NULL);
3469 ok(!!hwnd, "Failed to create a window.\n");
3470 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3471 ok(!!d3d8, "Failed to create a D3D object.\n");
3473 if (!(device = create_device(d3d8, hwnd, NULL)))
3475 skip("Failed to create a 3D device, skipping test.\n");
3476 goto cleanup;
3479 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &rt);
3480 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateRenderTarget failed, hr %#x.\n", hr);
3481 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds);
3482 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
3483 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger);
3484 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
3485 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, &ds_bigger2);
3486 ok(SUCCEEDED(hr), "IDirect3DDevice8_CreateDepthStencilSurface failed, hr %#x.\n", hr);
3488 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
3489 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
3490 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds_bigger);
3491 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
3493 /* try to set the small ds without changing the render target at the same time */
3494 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds);
3495 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_SetRenderTarget returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
3496 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, ds_bigger2);
3497 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
3499 hr = IDirect3DDevice8_GetRenderTarget(device, &surf);
3500 ok(hr == D3D_OK, "IDirect3DDevice8_GetRenderTarget failed, hr %#x.\n", hr);
3501 ok(surf == rt, "The render target is %p, expected %p\n", surf, rt);
3502 IDirect3DSurface8_Release(surf);
3503 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
3504 ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr %#x.\n", hr);
3505 ok(surf == ds_bigger2, "The depth stencil is %p, expected %p\n", surf, ds_bigger2);
3506 IDirect3DSurface8_Release(surf);
3508 hr = IDirect3DDevice8_SetRenderTarget(device, NULL, NULL);
3509 ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget failed, hr %#x.\n", hr);
3510 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &surf);
3511 ok(FAILED(hr), "IDirect3DDevice8_GetDepthStencilSurface should have failed, hr %#x.\n", hr);
3512 ok(surf == NULL, "The depth stencil is %p, expected NULL\n", surf);
3513 if (surf) IDirect3DSurface8_Release(surf);
3515 IDirect3DSurface8_Release(rt);
3516 IDirect3DSurface8_Release(ds);
3517 IDirect3DSurface8_Release(ds_bigger);
3518 IDirect3DSurface8_Release(ds_bigger2);
3520 cleanup:
3521 IDirect3D8_Release(d3d8);
3522 DestroyWindow(hwnd);
3525 static void test_window_style(void)
3527 RECT focus_rect, fullscreen_rect, r;
3528 LONG device_style, device_exstyle;
3529 LONG focus_style, focus_exstyle;
3530 struct device_desc device_desc;
3531 LONG style, expected_style;
3532 IDirect3DDevice8 *device;
3533 IDirect3D8 *d3d8;
3534 HRESULT hr;
3535 ULONG ref;
3536 BOOL ret;
3538 focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3539 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3540 device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3541 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3542 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3543 ok(!!d3d8, "Failed to create a D3D object.\n");
3545 device_style = GetWindowLongA(device_window, GWL_STYLE);
3546 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3547 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3548 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3550 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3551 GetWindowRect(focus_window, &focus_rect);
3553 device_desc.device_window = device_window;
3554 device_desc.width = registry_mode.dmPelsWidth;
3555 device_desc.height = registry_mode.dmPelsHeight;
3556 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3557 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3559 skip("Failed to create a D3D device, skipping tests.\n");
3560 goto done;
3563 style = GetWindowLongA(device_window, GWL_STYLE);
3564 expected_style = device_style | WS_VISIBLE;
3565 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3566 expected_style, style);
3567 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3568 expected_style = device_exstyle | WS_EX_TOPMOST;
3569 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3570 expected_style, style);
3572 style = GetWindowLongA(focus_window, GWL_STYLE);
3573 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3574 focus_style, style);
3575 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3576 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3577 focus_exstyle, style);
3579 GetWindowRect(device_window, &r);
3580 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
3581 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
3582 GetClientRect(device_window, &r);
3583 todo_wine ok(!EqualRect(&r, &fullscreen_rect), "Client rect and window rect are equal.\n");
3584 GetWindowRect(focus_window, &r);
3585 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&focus_rect),
3586 wine_dbgstr_rect(&r));
3588 device_desc.flags = 0;
3589 hr = reset_device(device, &device_desc);
3590 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3592 style = GetWindowLongA(device_window, GWL_STYLE);
3593 expected_style = device_style | WS_VISIBLE;
3594 ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3595 expected_style, style);
3596 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3597 expected_style = device_exstyle | WS_EX_TOPMOST;
3598 ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3599 expected_style, style);
3601 style = GetWindowLongA(focus_window, GWL_STYLE);
3602 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3603 focus_style, style);
3604 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3605 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3606 focus_exstyle, style);
3608 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3609 hr = reset_device(device, &device_desc);
3610 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3611 ret = SetForegroundWindow(GetDesktopWindow());
3612 ok(ret, "Failed to set foreground window.\n");
3614 style = GetWindowLongA(device_window, GWL_STYLE);
3615 expected_style = device_style | WS_MINIMIZE | WS_VISIBLE;
3616 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
3617 expected_style, style);
3618 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3619 expected_style = device_exstyle | WS_EX_TOPMOST;
3620 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
3621 expected_style, style);
3623 style = GetWindowLongA(focus_window, GWL_STYLE);
3624 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
3625 focus_style, style);
3626 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3627 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
3628 focus_exstyle, style);
3630 /* Follow-up tests fail on native if the device is destroyed while lost. */
3631 ShowWindow(focus_window, SW_MINIMIZE);
3632 ShowWindow(focus_window, SW_RESTORE);
3633 ret = SetForegroundWindow(focus_window);
3634 ok(ret, "Failed to set foreground window.\n");
3635 flush_events();
3636 hr = reset_device(device, &device_desc);
3637 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3639 ref = IDirect3DDevice8_Release(device);
3640 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3642 done:
3643 IDirect3D8_Release(d3d8);
3645 DestroyWindow(device_window);
3646 DestroyWindow(focus_window);
3649 static void test_unsupported_shaders(void)
3651 IDirect3DDevice8 *device;
3652 IDirect3D8 *d3d;
3653 ULONG refcount;
3654 DWORD vs, ps;
3655 HWND window;
3656 HRESULT hr;
3657 D3DCAPS8 caps;
3659 static const DWORD vs_2_0[] =
3661 0xfffe0200, /* vs_2_0 */
3662 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
3663 0x02000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
3664 0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002, /* add oD0, r1, c2 */
3665 0x02000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
3666 0x0000ffff /* end */
3668 static const DWORD ps_2_0[] =
3670 0xffff0200, /* ps_2_0 */
3671 0x02000001, 0x800f0001, 0xa0e40001, /* mov r1, c1 */
3672 0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002, /* add r0, r1, c2 */
3673 0x02000001, 0x800f0800, 0x80e40000, /* mov oC0, r0 */
3674 0x0000ffff /* end */
3676 #if 0
3677 vs_1_1
3678 dcl_position v0
3679 def c255, 1.0, 1.0, 1.0, 1.0
3680 add r0, v0, c255
3681 mov oPos, r0
3682 #endif
3683 static const DWORD vs_1_255[] =
3685 0xfffe0101,
3686 0x0000001f, 0x80000000, 0x900f0000,
3687 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
3688 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
3689 0x00000001, 0xc00f0000, 0x80e40000,
3690 0x0000ffff
3692 #if 0
3693 vs_1_1
3694 dcl_position v0
3695 def c256, 1.0, 1.0, 1.0, 1.0
3696 add r0, v0, c256
3697 mov oPos, r0
3698 #endif
3699 static const DWORD vs_1_256[] =
3701 0xfffe0101,
3702 0x0000001f, 0x80000000, 0x900f0000,
3703 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
3704 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
3705 0x00000001, 0xc00f0000, 0x80e40000,
3706 0x0000ffff
3709 static const DWORD decl[] =
3711 D3DVSD_STREAM(0),
3712 D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
3713 D3DVSD_END()
3716 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3717 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3718 ok(!!window, "Failed to create a window.\n");
3719 d3d = Direct3DCreate8(D3D_SDK_VERSION);
3720 ok(!!d3d, "Failed to create a D3D object.\n");
3721 if (!(device = create_device(d3d, window, NULL)))
3723 skip("Failed to create a D3D device, skipping tests.\n");
3724 IDirect3D8_Release(d3d);
3725 DestroyWindow(window);
3726 return;
3729 hr = IDirect3DDevice8_CreateVertexShader(device, decl, simple_ps, &vs, 0);
3730 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
3732 hr = IDirect3DDevice8_CreatePixelShader(device, simple_vs, &ps);
3733 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
3735 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_2_0, &vs, 0);
3736 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreateVertexShader returned %#08x\n", hr);
3738 hr = IDirect3DDevice8_CreatePixelShader(device, ps_2_0, &ps);
3739 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice8_CreatePixelShader returned %#08x\n", hr);
3741 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3742 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3743 if (caps.MaxVertexShaderConst < 256)
3745 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_255, &vs, 0);
3746 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3748 else
3750 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_255, &vs, 0);
3751 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3752 hr = IDirect3DDevice8_DeleteVertexShader(device, vs);
3753 ok(hr == D3D_OK, "IDirect3DDevice8_DeleteVertexShader returned %#08x\n", hr);
3754 hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_1_256, &vs, 0);
3755 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3758 refcount = IDirect3DDevice8_Release(device);
3759 ok(!refcount, "Device has %u references left.\n", refcount);
3760 IDirect3D8_Release(d3d);
3761 DestroyWindow(window);
3764 static void test_mode_change(void)
3766 RECT d3d_rect, focus_rect, r;
3767 struct device_desc device_desc;
3768 IDirect3DSurface8 *backbuffer;
3769 IDirect3DDevice8 *device;
3770 D3DSURFACE_DESC desc;
3771 IDirect3D8 *d3d8;
3772 DEVMODEW devmode;
3773 ULONG refcount;
3774 UINT adapter_mode_count, i;
3775 HRESULT hr;
3776 BOOL ret;
3777 LONG change_ret;
3778 D3DDISPLAYMODE d3ddm;
3779 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3781 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3782 ok(!!d3d8, "Failed to create a D3D object.\n");
3784 adapter_mode_count = IDirect3D8_GetAdapterModeCount(d3d8, D3DADAPTER_DEFAULT);
3785 for (i = 0; i < adapter_mode_count; ++i)
3787 hr = IDirect3D8_EnumAdapterModes(d3d8, D3DADAPTER_DEFAULT, i, &d3ddm);
3788 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3790 if (d3ddm.Format != D3DFMT_X8R8G8B8)
3791 continue;
3792 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3793 continue;
3794 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3795 * refuses to create a device at these sizes. */
3796 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3797 continue;
3799 if (!user32_width)
3801 user32_width = d3ddm.Width;
3802 user32_height = d3ddm.Height;
3803 continue;
3806 /* Make sure the d3d mode is smaller in width or height and at most
3807 * equal in the other dimension than the mode passed to
3808 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3809 * the ChangeDisplaySettings parameters + 12. */
3810 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3811 continue;
3812 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3814 d3d_width = d3ddm.Width;
3815 d3d_height = d3ddm.Height;
3816 break;
3818 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3820 d3d_width = user32_width;
3821 d3d_height = user32_height;
3822 user32_width = d3ddm.Width;
3823 user32_height = d3ddm.Height;
3824 break;
3828 if (!d3d_width)
3830 skip("Could not find adequate modes, skipping mode tests.\n");
3831 IDirect3D8_Release(d3d8);
3832 return;
3835 memset(&devmode, 0, sizeof(devmode));
3836 devmode.dmSize = sizeof(devmode);
3837 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3838 devmode.dmPelsWidth = user32_width;
3839 devmode.dmPelsHeight = user32_height;
3840 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3841 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3843 /* Make the windows visible, otherwise device::release does not restore the mode if
3844 * the application is not in foreground like on the testbot. */
3845 focus_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3846 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
3847 device_window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3848 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
3850 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
3851 GetWindowRect(focus_window, &focus_rect);
3853 device_desc.device_window = device_window;
3854 device_desc.width = d3d_width;
3855 device_desc.height = d3d_height;
3856 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3857 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3859 skip("Failed to create a D3D device, skipping tests.\n");
3860 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3861 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3862 goto done;
3865 devmode.dmPelsWidth = user32_width;
3866 devmode.dmPelsHeight = user32_height;
3867 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3868 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3870 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3871 ok(ret, "Failed to get display mode.\n");
3872 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
3873 "Expected resolution %ux%u, got %ux%u.\n",
3874 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
3876 GetWindowRect(device_window, &r);
3877 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&d3d_rect),
3878 wine_dbgstr_rect(&r));
3879 GetWindowRect(focus_window, &r);
3880 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&focus_rect),
3881 wine_dbgstr_rect(&r));
3883 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3884 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3885 hr = IDirect3DSurface8_GetDesc(backbuffer, &desc);
3886 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
3887 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
3888 desc.Width, d3d_width);
3889 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
3890 desc.Height, d3d_height);
3891 IDirect3DSurface8_Release(backbuffer);
3893 refcount = IDirect3DDevice8_Release(device);
3894 ok(!refcount, "Device has %u references left.\n", refcount);
3896 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3897 ok(ret, "Failed to get display mode.\n");
3898 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3899 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3900 "Expected resolution %ux%u, got %ux%u.\n",
3901 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
3903 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3904 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3906 /* The mode restore also happens when the device was created at the original screen size. */
3908 device_desc.device_window = device_window;
3909 device_desc.width = registry_mode.dmPelsWidth;
3910 device_desc.height = registry_mode.dmPelsHeight;
3911 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3912 ok(!!(device = create_device(d3d8, focus_window, &device_desc)), "Failed to create a D3D device.\n");
3914 devmode.dmPelsWidth = user32_width;
3915 devmode.dmPelsHeight = user32_height;
3916 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3917 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3919 refcount = IDirect3DDevice8_Release(device);
3920 ok(!refcount, "Device has %u references left.\n", refcount);
3922 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3923 ok(ret, "Failed to get display mode.\n");
3924 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3925 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
3926 "Expected resolution %ux%u, got %ux%u.\n",
3927 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
3929 done:
3930 DestroyWindow(device_window);
3931 DestroyWindow(focus_window);
3932 IDirect3D8_Release(d3d8);
3935 static void test_device_window_reset(void)
3937 RECT fullscreen_rect, device_rect, r;
3938 struct device_desc device_desc;
3939 IDirect3DDevice8 *device;
3940 WNDCLASSA wc = {0};
3941 IDirect3D8 *d3d8;
3942 LONG_PTR proc;
3943 HRESULT hr;
3944 ULONG ref;
3946 wc.lpfnWndProc = test_proc;
3947 wc.lpszClassName = "d3d8_test_wndproc_wc";
3948 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3950 focus_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3951 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3952 device_window = CreateWindowA("d3d8_test_wndproc_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
3953 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3954 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
3955 ok(!!d3d8, "Failed to create a D3D object.\n");
3957 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3958 GetWindowRect(device_window, &device_rect);
3960 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3961 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3962 (LONG_PTR)test_proc, proc);
3963 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3964 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3965 (LONG_PTR)test_proc, proc);
3967 device_desc.device_window = NULL;
3968 device_desc.width = registry_mode.dmPelsWidth;
3969 device_desc.height = registry_mode.dmPelsHeight;
3970 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3971 if (!(device = create_device(d3d8, focus_window, &device_desc)))
3973 skip("Failed to create a D3D device, skipping tests.\n");
3974 goto done;
3977 GetWindowRect(focus_window, &r);
3978 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
3979 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
3980 GetWindowRect(device_window, &r);
3981 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n", wine_dbgstr_rect(&device_rect),
3982 wine_dbgstr_rect(&r));
3984 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3985 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3986 (LONG_PTR)test_proc, proc);
3987 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3988 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3990 device_desc.device_window = device_window;
3991 hr = reset_device(device, &device_desc);
3992 ok(SUCCEEDED(hr), "Failed to reset device.\n");
3994 GetWindowRect(focus_window, &r);
3995 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
3996 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
3997 GetWindowRect(device_window, &r);
3998 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
3999 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
4001 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4002 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4003 (LONG_PTR)test_proc, proc);
4004 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4005 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4007 ref = IDirect3DDevice8_Release(device);
4008 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4010 done:
4011 IDirect3D8_Release(d3d8);
4012 DestroyWindow(device_window);
4013 DestroyWindow(focus_window);
4014 UnregisterClassA("d3d8_test_wndproc_wc", GetModuleHandleA(NULL));
4017 static void depth_blit_test(void)
4019 IDirect3DDevice8 *device = NULL;
4020 IDirect3DSurface8 *backbuffer, *ds1, *ds2, *ds3;
4021 RECT src_rect;
4022 const POINT dst_point = {0, 0};
4023 IDirect3D8 *d3d8;
4024 HRESULT hr;
4025 HWND hwnd;
4027 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4028 100, 100, 160, 160, NULL, NULL, NULL, NULL);
4029 ok(!!hwnd, "Failed to create a window.\n");
4030 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4031 ok(!!d3d8, "Failed to create a D3D object.\n");
4033 if (!(device = create_device(d3d8, hwnd, NULL)))
4035 skip("Failed to create a D3D device, skipping tests.\n");
4036 goto done;
4039 hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
4040 ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
4041 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds1);
4042 ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
4043 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds2);
4044 ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
4045 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, &ds3);
4046 ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
4048 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
4049 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
4051 /* Partial blit. */
4052 SetRect(&src_rect, 0, 0, 320, 240);
4053 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4054 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4055 /* Flipped. */
4056 SetRect(&src_rect, 0, 480, 640, 0);
4057 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4058 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4059 /* Full, explicit. */
4060 SetRect(&src_rect, 0, 0, 640, 480);
4061 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, ds2, &dst_point);
4062 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4063 /* Depth -> color blit.*/
4064 hr = IDirect3DDevice8_CopyRects(device, ds1, &src_rect, 1, backbuffer, &dst_point);
4065 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4066 /* Full, NULL rects, current depth stencil -> unbound depth stencil */
4067 hr = IDirect3DDevice8_CopyRects(device, ds1, NULL, 0, ds2, NULL);
4068 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4069 /* Full, NULL rects, unbound depth stencil -> current depth stencil */
4070 hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds1, NULL);
4071 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4072 /* Full, NULL rects, unbound depth stencil -> unbound depth stencil */
4073 hr = IDirect3DDevice8_CopyRects(device, ds2, NULL, 0, ds3, NULL);
4074 ok(hr == D3DERR_INVALIDCALL, "CopyRects returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
4076 IDirect3DSurface8_Release(backbuffer);
4077 IDirect3DSurface8_Release(ds3);
4078 IDirect3DSurface8_Release(ds2);
4079 IDirect3DSurface8_Release(ds1);
4081 done:
4082 if (device) IDirect3DDevice8_Release(device);
4083 IDirect3D8_Release(d3d8);
4084 DestroyWindow(hwnd);
4087 static void test_reset_resources(void)
4089 IDirect3DSurface8 *surface, *rt;
4090 IDirect3DTexture8 *texture;
4091 IDirect3DDevice8 *device;
4092 IDirect3D8 *d3d8;
4093 HWND window;
4094 HRESULT hr;
4095 ULONG ref;
4097 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
4098 0, 0, 640, 480, 0, 0, 0, 0);
4099 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4100 ok(!!d3d8, "Failed to create a D3D object.\n");
4102 if (!(device = create_device(d3d8, window, NULL)))
4104 skip("Failed to create a D3D device, skipping tests.\n");
4105 goto done;
4108 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24S8,
4109 D3DMULTISAMPLE_NONE, &surface);
4110 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
4112 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
4113 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
4114 ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr);
4115 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &rt);
4116 ok(SUCCEEDED(hr), "Failed to get surface, hr %#x.\n", hr);
4117 IDirect3DTexture8_Release(texture);
4119 hr = IDirect3DDevice8_SetRenderTarget(device, rt, surface);
4120 ok(SUCCEEDED(hr), "Failed to set render target surface, hr %#x.\n", hr);
4121 IDirect3DSurface8_Release(rt);
4122 IDirect3DSurface8_Release(surface);
4124 hr = reset_device(device, NULL);
4125 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4127 hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
4128 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
4129 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
4130 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4131 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
4132 IDirect3DSurface8_Release(surface);
4133 IDirect3DSurface8_Release(rt);
4135 ref = IDirect3DDevice8_Release(device);
4136 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4138 done:
4139 IDirect3D8_Release(d3d8);
4140 DestroyWindow(window);
4143 static void test_set_rt_vp_scissor(void)
4145 IDirect3DDevice8 *device;
4146 IDirect3DSurface8 *rt;
4147 IDirect3D8 *d3d8;
4148 DWORD stateblock;
4149 D3DVIEWPORT8 vp;
4150 UINT refcount;
4151 HWND window;
4152 HRESULT hr;
4154 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
4155 0, 0, 640, 480, 0, 0, 0, 0);
4156 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4157 ok(!!d3d8, "Failed to create a D3D object.\n");
4158 if (!(device = create_device(d3d8, window, NULL)))
4160 skip("Failed to create a D3D device, skipping tests.\n");
4161 IDirect3D8_Release(d3d8);
4162 DestroyWindow(window);
4163 return;
4166 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
4167 D3DMULTISAMPLE_NONE, FALSE, &rt);
4168 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4170 hr = IDirect3DDevice8_GetViewport(device, &vp);
4171 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4172 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4173 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4174 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
4175 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
4176 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4177 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4179 hr = IDirect3DDevice8_BeginStateBlock(device);
4180 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
4182 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4183 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4185 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
4186 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
4187 hr = IDirect3DDevice8_DeleteStateBlock(device, stateblock);
4188 ok(SUCCEEDED(hr), "Failed to delete stateblock, hr %#x.\n", hr);
4190 hr = IDirect3DDevice8_GetViewport(device, &vp);
4191 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4192 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4193 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4194 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4195 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4196 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4197 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4199 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4200 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4202 vp.X = 10;
4203 vp.Y = 20;
4204 vp.Width = 30;
4205 vp.Height = 40;
4206 vp.MinZ = 0.25f;
4207 vp.MaxZ = 0.75f;
4208 hr = IDirect3DDevice8_SetViewport(device, &vp);
4209 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
4211 hr = IDirect3DDevice8_SetRenderTarget(device, rt, NULL);
4212 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4214 hr = IDirect3DDevice8_GetViewport(device, &vp);
4215 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4216 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4217 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4218 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4219 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4220 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4221 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4223 IDirect3DSurface8_Release(rt);
4224 refcount = IDirect3DDevice8_Release(device);
4225 ok(!refcount, "Device has %u references left.\n", refcount);
4226 IDirect3D8_Release(d3d8);
4227 DestroyWindow(window);
4230 static void test_validate_vs(void)
4232 static DWORD vs[] =
4234 0xfffe0101, /* vs_1_1 */
4235 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
4236 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
4237 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
4238 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
4239 0x0000ffff, /* end */
4241 HRESULT hr;
4243 hr = ValidateVertexShader(0, 0, 0, 0, 0);
4244 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4245 hr = ValidateVertexShader(0, 0, 0, 1, 0);
4246 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4247 hr = ValidateVertexShader(vs, 0, 0, 0, 0);
4248 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4250 hr = ValidateVertexShader(vs, 0, 0, 1, 0);
4251 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4252 /* Seems to do some version checking. */
4253 *vs = 0xfffe0100; /* vs_1_0 */
4254 hr = ValidateVertexShader(vs, 0, 0, 0, 0);
4255 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4257 *vs = 0xfffe0102; /* bogus version */
4258 hr = ValidateVertexShader(vs, 0, 0, 1, 0);
4259 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4260 /* I've seen that applications always pass the 2nd and 3rd parameter as 0.
4261 * Simple test with non-zero parameters. */
4262 *vs = 0xfffe0101; /* vs_1_1 */
4263 hr = ValidateVertexShader(vs, vs, 0, 1, 0);
4264 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4266 hr = ValidateVertexShader(vs, 0, vs, 1, 0);
4267 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4268 /* I've seen the 4th parameter always passed as either 0 or 1, but passing
4269 * other values doesn't seem to hurt. */
4270 hr = ValidateVertexShader(vs, 0, 0, 12345, 0);
4271 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4272 /* What is the 5th parameter? The following seems to work ok. */
4273 hr = ValidateVertexShader(vs, 0, 0, 1, vs);
4274 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4277 static void test_validate_ps(void)
4279 static DWORD ps[] =
4281 0xffff0101, /* ps_1_1 */
4282 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
4283 0x00000042, 0xb00f0000, /* tex t0 */
4284 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
4285 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
4286 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
4287 0x0000ffff, /* end */
4289 HRESULT hr;
4291 hr = ValidatePixelShader(0, 0, 0, 0);
4292 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4293 hr = ValidatePixelShader(0, 0, 1, 0);
4294 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4295 hr = ValidatePixelShader(ps, 0, 0, 0);
4296 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4298 hr = ValidatePixelShader(ps, 0, 1, 0);
4299 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4300 /* Seems to do some version checking. */
4301 *ps = 0xffff0105; /* bogus version */
4302 hr = ValidatePixelShader(ps, 0, 1, 0);
4303 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4304 /* I've seen that applications always pass the 2nd parameter as 0.
4305 * Simple test with a non-zero parameter. */
4306 *ps = 0xffff0101; /* ps_1_1 */
4307 hr = ValidatePixelShader(ps, ps, 1, 0);
4308 ok(hr == E_FAIL, "Got unexpected hr %#x.\n", hr);
4309 /* I've seen the 3rd parameter always passed as either 0 or 1, but passing
4310 * other values doesn't seem to hurt. */
4311 hr = ValidatePixelShader(ps, 0, 12345, 0);
4312 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4313 /* What is the 4th parameter? The following seems to work ok. */
4314 hr = ValidatePixelShader(ps, 0, 1, ps);
4315 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
4318 static void test_volume_get_container(void)
4320 IDirect3DVolumeTexture8 *texture = NULL;
4321 IDirect3DVolume8 *volume = NULL;
4322 IDirect3DDevice8 *device;
4323 IUnknown *container;
4324 IDirect3D8 *d3d8;
4325 ULONG refcount;
4326 D3DCAPS8 caps;
4327 HWND window;
4328 HRESULT hr;
4330 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4331 0, 0, 640, 480, 0, 0, 0, 0);
4332 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4333 ok(!!d3d8, "Failed to create a D3D object.\n");
4334 if (!(device = create_device(d3d8, window, NULL)))
4336 skip("Failed to create a D3D device, skipping tests.\n");
4337 IDirect3D8_Release(d3d8);
4338 DestroyWindow(window);
4339 return;
4342 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4343 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4344 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
4346 skip("No volume texture support, skipping tests.\n");
4347 IDirect3DDevice8_Release(device);
4348 IDirect3D8_Release(d3d8);
4349 DestroyWindow(window);
4350 return;
4353 hr = IDirect3DDevice8_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
4354 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
4355 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
4356 ok(!!texture, "Got unexpected texture %p.\n", texture);
4358 hr = IDirect3DVolumeTexture8_GetVolumeLevel(texture, 0, &volume);
4359 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
4360 ok(!!volume, "Got unexpected volume %p.\n", volume);
4362 /* These should work... */
4363 container = NULL;
4364 hr = IDirect3DVolume8_GetContainer(volume, &IID_IUnknown, (void **)&container);
4365 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4366 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4367 IUnknown_Release(container);
4369 container = NULL;
4370 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DResource8, (void **)&container);
4371 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4372 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4373 IUnknown_Release(container);
4375 container = NULL;
4376 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DBaseTexture8, (void **)&container);
4377 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4378 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4379 IUnknown_Release(container);
4381 container = NULL;
4382 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolumeTexture8, (void **)&container);
4383 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
4384 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4385 IUnknown_Release(container);
4387 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
4388 hr = IDirect3DVolume8_GetContainer(volume, &IID_IDirect3DVolume8, (void **)&container);
4389 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
4390 ok(!container, "Got unexpected container %p.\n", container);
4392 IDirect3DVolume8_Release(volume);
4393 IDirect3DVolumeTexture8_Release(texture);
4394 refcount = IDirect3DDevice8_Release(device);
4395 ok(!refcount, "Device has %u references left.\n", refcount);
4396 IDirect3D8_Release(d3d8);
4397 DestroyWindow(window);
4400 static void test_vb_lock_flags(void)
4402 static const struct
4404 DWORD flags;
4405 const char *debug_string;
4406 HRESULT result;
4408 test_data[] =
4410 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
4411 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
4412 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
4413 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
4414 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
4415 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3D_OK },
4416 /* Completely bogus flags aren't an error. */
4417 {0xdeadbeef, "0xdeadbeef", D3D_OK },
4419 IDirect3DVertexBuffer8 *buffer;
4420 IDirect3DDevice8 *device;
4421 IDirect3D8 *d3d8;
4422 unsigned int i;
4423 ULONG refcount;
4424 HWND window;
4425 HRESULT hr;
4426 BYTE *data;
4428 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4429 0, 0, 640, 480, 0, 0, 0, 0);
4430 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4431 ok(!!d3d8, "Failed to create a D3D object.\n");
4432 if (!(device = create_device(d3d8, window, NULL)))
4434 skip("Failed to create a D3D device, skipping tests.\n");
4435 IDirect3D8_Release(d3d8);
4436 DestroyWindow(window);
4437 return;
4440 hr = IDirect3DDevice8_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer);
4441 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
4443 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
4445 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &data, test_data[i].flags);
4446 ok(hr == test_data[i].result, "Got unexpected hr %#x for %s.\n",
4447 hr, test_data[i].debug_string);
4448 if (SUCCEEDED(hr))
4450 ok(!!data, "Got unexpected data %p.\n", data);
4451 hr = IDirect3DVertexBuffer8_Unlock(buffer);
4452 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
4456 IDirect3DVertexBuffer8_Release(buffer);
4457 refcount = IDirect3DDevice8_Release(device);
4458 ok(!refcount, "Device has %u references left.\n", refcount);
4459 IDirect3D8_Release(d3d8);
4460 DestroyWindow(window);
4463 /* Test the default texture stage state values */
4464 static void test_texture_stage_states(void)
4466 IDirect3DDevice8 *device;
4467 IDirect3D8 *d3d8;
4468 unsigned int i;
4469 ULONG refcount;
4470 D3DCAPS8 caps;
4471 DWORD value;
4472 HWND window;
4473 HRESULT hr;
4475 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4476 0, 0, 640, 480, 0, 0, 0, 0);
4477 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4478 ok(!!d3d8, "Failed to create a D3D object.\n");
4479 if (!(device = create_device(d3d8, window, NULL)))
4481 skip("Failed to create a D3D device, skipping tests.\n");
4482 IDirect3D8_Release(d3d8);
4483 DestroyWindow(window);
4484 return;
4487 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4488 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4490 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
4492 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
4493 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4494 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
4495 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
4496 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
4497 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4498 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
4499 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
4500 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4501 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
4502 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
4503 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4504 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
4505 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
4506 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
4507 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4508 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
4509 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
4510 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4511 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
4512 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
4513 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4514 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
4515 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
4516 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4517 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
4518 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
4519 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4520 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
4521 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
4522 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4523 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
4524 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
4525 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4526 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
4527 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
4528 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4529 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
4530 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
4531 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4532 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
4533 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
4534 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4535 ok(value == D3DTTFF_DISABLE,
4536 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
4537 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
4538 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4539 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
4540 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
4541 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4542 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
4543 hr = IDirect3DDevice8_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
4544 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
4545 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
4548 refcount = IDirect3DDevice8_Release(device);
4549 ok(!refcount, "Device has %u references left.\n", refcount);
4550 IDirect3D8_Release(d3d8);
4551 DestroyWindow(window);
4554 static void test_cube_textures(void)
4556 IDirect3DCubeTexture8 *texture;
4557 IDirect3DDevice8 *device;
4558 IDirect3D8 *d3d8;
4559 ULONG refcount;
4560 D3DCAPS8 caps;
4561 HWND window;
4562 HRESULT hr;
4564 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4565 0, 0, 640, 480, 0, 0, 0, 0);
4566 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4567 ok(!!d3d8, "Failed to create a D3D object.\n");
4568 if (!(device = create_device(d3d8, window, NULL)))
4570 skip("Failed to create a D3D device, skipping tests.\n");
4571 IDirect3D8_Release(d3d8);
4572 DestroyWindow(window);
4573 return;
4576 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
4577 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4579 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
4581 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
4582 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
4583 IDirect3DCubeTexture8_Release(texture);
4584 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
4585 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
4586 IDirect3DCubeTexture8_Release(texture);
4587 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
4588 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
4589 IDirect3DCubeTexture8_Release(texture);
4591 else
4593 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture);
4594 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
4595 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture);
4596 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
4597 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture);
4598 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
4600 hr = IDirect3DDevice8_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture);
4601 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
4602 IDirect3DCubeTexture8_Release(texture);
4604 refcount = IDirect3DDevice8_Release(device);
4605 ok(!refcount, "Device has %u references left.\n", refcount);
4606 IDirect3D8_Release(d3d8);
4607 DestroyWindow(window);
4610 static void test_get_set_texture(void)
4612 const IDirect3DBaseTexture8Vtbl *texture_vtbl;
4613 IDirect3DBaseTexture8 *texture;
4614 IDirect3DDevice8 *device;
4615 IDirect3D8 *d3d;
4616 ULONG refcount;
4617 HWND window;
4618 HRESULT hr;
4620 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4621 0, 0, 640, 480, 0, 0, 0, 0);
4622 d3d = Direct3DCreate8(D3D_SDK_VERSION);
4623 ok(!!d3d, "Failed to create a D3D object.\n");
4624 if (!(device = create_device(d3d, window, NULL)))
4626 skip("Failed to create a D3D device, skipping tests.\n");
4627 IDirect3D8_Release(d3d);
4628 DestroyWindow(window);
4629 return;
4632 texture = (IDirect3DBaseTexture8 *)0xdeadbeef;
4633 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
4634 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4635 hr = IDirect3DDevice8_GetTexture(device, 0, &texture);
4636 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
4637 ok(!texture, "Got unexpected texture %p.\n", texture);
4639 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
4640 D3DPOOL_MANAGED, (IDirect3DTexture8 **)&texture);
4641 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4642 texture_vtbl = texture->lpVtbl;
4643 texture->lpVtbl = (IDirect3DBaseTexture8Vtbl *)0xdeadbeef;
4644 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
4645 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4646 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
4647 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4648 texture->lpVtbl = NULL;
4649 hr = IDirect3DDevice8_SetTexture(device, 0, texture);
4650 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4651 hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
4652 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
4653 texture->lpVtbl = texture_vtbl;
4654 IDirect3DBaseTexture8_Release(texture);
4656 refcount = IDirect3DDevice8_Release(device);
4657 ok(!refcount, "Device has %u references left.\n", refcount);
4658 IDirect3D8_Release(d3d);
4659 DestroyWindow(window);
4662 /* Test the behaviour of the IDirect3DDevice8::CreateImageSurface() method.
4664 * The expected behaviour (as documented in the original DX8 docs) is that the
4665 * call returns a surface in the SYSTEMMEM pool. Games like Max Payne 1 and 2
4666 * depend on this behaviour.
4668 * A short remark in the DX9 docs however states that the pool of the returned
4669 * surface object is D3DPOOL_SCRATCH. This is misinformation and would result
4670 * in screenshots not appearing in the savegame loading menu of both games
4671 * mentioned above (engine tries to display a texture from the scratch pool).
4673 * This test verifies that the behaviour described in the original d3d8 docs
4674 * is the correct one. For more information about this issue, see the MSDN:
4675 * d3d9 docs: "Converting to Direct3D 9"
4676 * d3d9 reference: "IDirect3DDevice9::CreateOffscreenPlainSurface"
4677 * d3d8 reference: "IDirect3DDevice8::CreateImageSurface" */
4678 static void test_image_surface_pool(void)
4680 IDirect3DSurface8 *surface;
4681 IDirect3DDevice8 *device;
4682 D3DSURFACE_DESC desc;
4683 IDirect3D8 *d3d8;
4684 ULONG refcount;
4685 HWND window;
4686 HRESULT hr;
4688 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4689 0, 0, 640, 480, 0, 0, 0, 0);
4690 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4691 ok(!!d3d8, "Failed to create a D3D object.\n");
4692 if (!(device = create_device(d3d8, window, NULL)))
4694 skip("Failed to create a D3D device, skipping tests.\n");
4695 IDirect3D8_Release(d3d8);
4696 DestroyWindow(window);
4697 return;
4700 hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
4701 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
4702 hr = IDirect3DSurface8_GetDesc(surface, &desc);
4703 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
4704 ok(desc.Pool == D3DPOOL_SYSTEMMEM, "Got unexpected pool %#x.\n", desc.Pool);
4705 IDirect3DSurface8_Release(surface);
4707 refcount = IDirect3DDevice8_Release(device);
4708 ok(!refcount, "Device has %u references left.\n", refcount);
4709 IDirect3D8_Release(d3d8);
4710 DestroyWindow(window);
4713 static void test_surface_get_container(void)
4715 IDirect3DTexture8 *texture = NULL;
4716 IDirect3DSurface8 *surface = NULL;
4717 IDirect3DDevice8 *device;
4718 IUnknown *container;
4719 IDirect3D8 *d3d8;
4720 ULONG refcount;
4721 HWND window;
4722 HRESULT hr;
4724 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4725 0, 0, 640, 480, 0, 0, 0, 0);
4726 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4727 ok(!!d3d8, "Failed to create a D3D object.\n");
4728 if (!(device = create_device(d3d8, window, NULL)))
4730 skip("Failed to create a D3D device, skipping tests.\n");
4731 IDirect3D8_Release(d3d8);
4732 DestroyWindow(window);
4733 return;
4736 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0,
4737 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture);
4738 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
4739 ok(!!texture, "Got unexpected texture %p.\n", texture);
4741 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
4742 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
4743 ok(!!surface, "Got unexpected surface %p.\n", surface);
4745 /* These should work... */
4746 container = NULL;
4747 hr = IDirect3DSurface8_GetContainer(surface, &IID_IUnknown, (void **)&container);
4748 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4749 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4750 IUnknown_Release(container);
4752 container = NULL;
4753 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DResource8, (void **)&container);
4754 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4755 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4756 IUnknown_Release(container);
4758 container = NULL;
4759 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DBaseTexture8, (void **)&container);
4760 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4761 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4762 IUnknown_Release(container);
4764 container = NULL;
4765 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DTexture8, (void **)&container);
4766 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
4767 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
4768 IUnknown_Release(container);
4770 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
4771 hr = IDirect3DSurface8_GetContainer(surface, &IID_IDirect3DSurface8, (void **)&container);
4772 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
4773 ok(!container, "Got unexpected container %p.\n", container);
4775 IDirect3DSurface8_Release(surface);
4776 IDirect3DTexture8_Release(texture);
4777 refcount = IDirect3DDevice8_Release(device);
4778 ok(!refcount, "Device has %u references left.\n", refcount);
4779 IDirect3D8_Release(d3d8);
4780 DestroyWindow(window);
4783 static void test_lockrect_invalid(void)
4785 static const RECT valid[] =
4787 {60, 60, 68, 68},
4788 {120, 60, 128, 68},
4789 {60, 120, 68, 128},
4791 static const RECT invalid[] =
4793 {60, 60, 60, 68}, /* 0 height */
4794 {60, 60, 68, 60}, /* 0 width */
4795 {68, 60, 60, 68}, /* left > right */
4796 {60, 68, 68, 60}, /* top > bottom */
4797 {-8, 60, 0, 68}, /* left < surface */
4798 {60, -8, 68, 0}, /* top < surface */
4799 {-16, 60, -8, 68}, /* right < surface */
4800 {60, -16, 68, -8}, /* bottom < surface */
4801 {60, 60, 136, 68}, /* right > surface */
4802 {60, 60, 68, 136}, /* bottom > surface */
4803 {136, 60, 144, 68}, /* left > surface */
4804 {60, 136, 68, 144}, /* top > surface */
4806 IDirect3DSurface8 *surface;
4807 IDirect3DTexture8 *texture;
4808 IDirect3DCubeTexture8 *cube_texture;
4809 D3DLOCKED_RECT locked_rect;
4810 IDirect3DDevice8 *device;
4811 IDirect3D8 *d3d8;
4812 unsigned int i, r;
4813 ULONG refcount;
4814 HWND window;
4815 BYTE *base;
4816 HRESULT hr;
4817 unsigned int offset, expected_offset;
4818 static const struct
4820 D3DRESOURCETYPE type;
4821 D3DPOOL pool;
4822 const char *name;
4823 BOOL validate, clear;
4825 resources[] =
4827 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface", TRUE, TRUE},
4828 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture", FALSE, FALSE},
4829 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture", FALSE, FALSE},
4830 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture", FALSE, FALSE},
4831 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture", TRUE, TRUE},
4832 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture", TRUE, TRUE},
4833 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture", TRUE, TRUE},
4836 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
4837 0, 0, 640, 480, 0, 0, 0, 0);
4838 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
4839 ok(!!d3d8, "Failed to create a D3D object.\n");
4840 if (!(device = create_device(d3d8, window, NULL)))
4842 skip("Failed to create a D3D device, skipping tests.\n");
4843 IDirect3D8_Release(d3d8);
4844 DestroyWindow(window);
4845 return;
4848 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
4850 texture = NULL;
4851 cube_texture = NULL;
4852 switch (resources[r].type)
4854 case D3DRTYPE_SURFACE:
4855 hr = IDirect3DDevice8_CreateImageSurface(device, 128, 128, D3DFMT_A8R8G8B8, &surface);
4856 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n", hr, resources[r].name);
4857 break;
4859 case D3DRTYPE_TEXTURE:
4860 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
4861 resources[r].pool, &texture);
4862 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n", hr, resources[r].name);
4863 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
4864 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n", hr, resources[r].name);
4865 break;
4867 case D3DRTYPE_CUBETEXTURE:
4868 hr = IDirect3DDevice8_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
4869 resources[r].pool, &cube_texture);
4870 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n", hr, resources[r].name);
4871 hr = IDirect3DCubeTexture8_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
4872 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n", hr, resources[r].name);
4873 break;
4875 default:
4876 break;
4878 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4879 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
4880 base = locked_rect.pBits;
4881 hr = IDirect3DSurface8_UnlockRect(surface);
4882 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4884 for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
4886 const RECT *rect = &valid[i];
4888 locked_rect.pBits = (BYTE *)0xdeadbeef;
4889 locked_rect.Pitch = 0xdeadbeef;
4891 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
4892 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
4893 wine_dbgstr_rect(rect), hr, resources[r].name);
4895 offset = (BYTE *)locked_rect.pBits - base;
4896 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
4897 ok(offset == expected_offset,
4898 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4899 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
4901 hr = IDirect3DSurface8_UnlockRect(surface);
4902 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s\n", hr, resources[r].name);
4904 if (texture)
4906 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, rect, 0);
4907 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
4908 wine_dbgstr_rect(rect), hr, resources[r].name);
4910 offset = (BYTE *)locked_rect.pBits - base;
4911 ok(offset == expected_offset,
4912 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4913 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
4915 hr = IDirect3DTexture8_UnlockRect(texture, 0);
4916 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4918 if (cube_texture)
4920 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0, &locked_rect, rect, 0);
4921 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
4922 wine_dbgstr_rect(rect), hr, resources[r].name);
4924 offset = (BYTE *)locked_rect.pBits - base;
4925 ok(offset == expected_offset,
4926 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4927 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
4929 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
4930 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4934 for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
4936 const RECT *rect = &invalid[i];
4938 locked_rect.pBits = (void *)0xdeadbeef;
4939 locked_rect.Pitch = 1;
4940 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
4941 if (resources[r].validate)
4942 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
4943 hr, wine_dbgstr_rect(rect), resources[r].name);
4944 else
4945 ok(SUCCEEDED(hr), "Got unexpected hr %#x for rect %s, type %s.\n",
4946 hr, wine_dbgstr_rect(rect), resources[r].name);
4948 if (SUCCEEDED(hr))
4950 offset = (BYTE *)locked_rect.pBits - base;
4951 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
4952 ok(offset == expected_offset,
4953 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4954 offset, expected_offset,wine_dbgstr_rect(rect), resources[r].name);
4956 hr = IDirect3DSurface8_UnlockRect(surface);
4957 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4959 else
4961 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
4962 locked_rect.pBits, resources[r].name);
4963 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
4964 locked_rect.Pitch, resources[r].name);
4968 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4969 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n",
4970 hr, resources[r].name);
4971 locked_rect.pBits = (void *)0xdeadbeef;
4972 locked_rect.Pitch = 1;
4973 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4974 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
4975 if (resources[r].clear)
4977 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
4978 locked_rect.pBits, resources[r].name);
4979 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
4980 locked_rect.Pitch, resources[r].name);
4982 else
4984 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
4985 locked_rect.pBits, resources[r].name);
4986 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
4987 locked_rect.Pitch, resources[r].name);
4989 hr = IDirect3DSurface8_UnlockRect(surface);
4990 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4992 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
4993 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
4994 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
4995 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
4996 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
4997 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
4998 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[1], 0);
4999 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5000 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5001 hr = IDirect3DSurface8_UnlockRect(surface);
5002 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5004 IDirect3DSurface8_Release(surface);
5005 if (texture)
5007 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5008 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
5009 hr, resources[r].name);
5010 locked_rect.pBits = (void *)0xdeadbeef;
5011 locked_rect.Pitch = 1;
5012 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5013 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5014 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
5015 locked_rect.pBits, resources[r].name);
5016 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
5017 locked_rect.Pitch, resources[r].name);
5018 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5019 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5020 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5021 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5023 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5024 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
5025 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5026 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5027 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5028 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5029 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[1], 0);
5030 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5031 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5032 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5033 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5035 IDirect3DTexture8_Release(texture);
5038 if (cube_texture)
5040 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5041 &locked_rect, NULL, 0);
5042 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
5043 hr, resources[r].name);
5044 locked_rect.pBits = (void *)0xdeadbeef;
5045 locked_rect.Pitch = 1;
5046 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5047 &locked_rect, NULL, 0);
5048 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5049 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5050 locked_rect.pBits, resources[r].name);
5051 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5052 locked_rect.Pitch, resources[r].name);
5053 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5054 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5055 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5056 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5058 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5059 &locked_rect, &valid[0], 0);
5060 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
5061 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5062 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5063 &locked_rect, &valid[0], 0);
5064 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5065 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5066 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5067 &locked_rect, &valid[1], 0);
5068 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5069 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5070 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5071 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5073 IDirect3DTexture8_Release(cube_texture);
5077 refcount = IDirect3DDevice8_Release(device);
5078 ok(!refcount, "Device has %u references left.\n", refcount);
5079 IDirect3D8_Release(d3d8);
5080 DestroyWindow(window);
5083 static void test_private_data(void)
5085 ULONG refcount, expected_refcount;
5086 IDirect3DTexture8 *texture;
5087 IDirect3DSurface8 *surface, *surface2;
5088 IDirect3DDevice8 *device;
5089 IDirect3D8 *d3d8;
5090 IUnknown *ptr;
5091 HWND window;
5092 HRESULT hr;
5093 DWORD size;
5094 DWORD data[4] = {1, 2, 3, 4};
5095 static const GUID d3d8_private_data_test_guid2 =
5097 0x2e5afac2,
5098 0x87b5,
5099 0x4c10,
5100 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
5103 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5104 0, 0, 640, 480, 0, 0, 0, 0);
5105 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5106 ok(!!d3d8, "Failed to create a D3D object.\n");
5107 if (!(device = create_device(d3d8, window, NULL)))
5109 skip("Failed to create a D3D device, skipping tests.\n");
5110 IDirect3D8_Release(d3d8);
5111 DestroyWindow(window);
5112 return;
5115 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_A8R8G8B8, &surface);
5116 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5118 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5119 device, 0, D3DSPD_IUNKNOWN);
5120 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5121 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5122 device, 5, D3DSPD_IUNKNOWN);
5123 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5124 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5125 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
5126 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5128 /* A failing SetPrivateData call does not clear the old data with the same tag. */
5129 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
5130 sizeof(device), D3DSPD_IUNKNOWN);
5131 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5132 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
5133 sizeof(device) * 2, D3DSPD_IUNKNOWN);
5134 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5135 size = sizeof(ptr);
5136 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5137 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
5138 IUnknown_Release(ptr);
5139 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5140 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5142 refcount = get_refcount((IUnknown *)device);
5143 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5144 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5145 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5146 expected_refcount = refcount + 1;
5147 refcount = get_refcount((IUnknown *)device);
5148 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5149 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5150 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5151 expected_refcount = refcount - 1;
5152 refcount = get_refcount((IUnknown *)device);
5153 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5155 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5156 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5157 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5158 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5159 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5160 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5161 refcount = get_refcount((IUnknown *)device);
5162 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5164 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5165 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5166 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5167 size = 2 * sizeof(ptr);
5168 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5169 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5170 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5171 expected_refcount = refcount + 2;
5172 refcount = get_refcount((IUnknown *)device);
5173 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5174 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
5175 IUnknown_Release(ptr);
5176 expected_refcount--;
5178 ptr = (IUnknown *)0xdeadbeef;
5179 size = 1;
5180 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
5181 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5182 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5183 size = 2 * sizeof(ptr);
5184 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
5185 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5186 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5187 refcount = get_refcount((IUnknown *)device);
5188 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5189 size = 1;
5190 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5191 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
5192 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5193 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
5194 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, NULL, NULL);
5195 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5196 size = 0xdeadbabe;
5197 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, &ptr, &size);
5198 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5199 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
5200 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
5201 /* GetPrivateData with size = NULL causes an access violation on Windows if the
5202 * requested data exists. */
5204 /* Destroying the surface frees the held reference. */
5205 IDirect3DSurface8_Release(surface);
5206 expected_refcount = refcount - 2;
5207 refcount = get_refcount((IUnknown *)device);
5208 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5210 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
5211 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5212 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5213 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
5214 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
5215 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
5217 hr = IDirect3DTexture8_SetPrivateData(texture, &d3d8_private_data_test_guid, data, sizeof(data), 0);
5218 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5220 memset(data, 0, sizeof(data));
5221 size = sizeof(data);
5222 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, data, &size);
5223 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5224 hr = IDirect3DTexture8_GetPrivateData(texture, &d3d8_private_data_test_guid, data, &size);
5225 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
5226 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
5227 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
5229 hr = IDirect3DTexture8_FreePrivateData(texture, &d3d8_private_data_test_guid);
5230 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5232 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, data, sizeof(data), 0);
5233 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5234 hr = IDirect3DSurface8_GetPrivateData(surface2, &d3d8_private_data_test_guid, data, &size);
5235 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5236 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5237 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5239 IDirect3DSurface8_Release(surface2);
5240 IDirect3DSurface8_Release(surface);
5241 IDirect3DTexture8_Release(texture);
5243 refcount = IDirect3DDevice8_Release(device);
5244 ok(!refcount, "Device has %u references left.\n", refcount);
5245 IDirect3D8_Release(d3d8);
5246 DestroyWindow(window);
5249 static void test_surface_dimensions(void)
5251 IDirect3DSurface8 *surface;
5252 IDirect3DDevice8 *device;
5253 IDirect3D8 *d3d8;
5254 ULONG refcount;
5255 HWND window;
5256 HRESULT hr;
5258 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5259 0, 0, 640, 480, 0, 0, 0, 0);
5260 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5261 ok(!!d3d8, "Failed to create a D3D object.\n");
5262 if (!(device = create_device(d3d8, window, NULL)))
5264 skip("Failed to create a D3D device, skipping tests.\n");
5265 IDirect3D8_Release(d3d8);
5266 DestroyWindow(window);
5267 return;
5270 hr = IDirect3DDevice8_CreateImageSurface(device, 0, 1, D3DFMT_A8R8G8B8, &surface);
5271 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5272 hr = IDirect3DDevice8_CreateImageSurface(device, 1, 0, D3DFMT_A8R8G8B8, &surface);
5273 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5275 refcount = IDirect3DDevice8_Release(device);
5276 ok(!refcount, "Device has %u references left.\n", refcount);
5277 IDirect3D8_Release(d3d8);
5278 DestroyWindow(window);
5281 static void test_surface_format_null(void)
5283 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
5284 IDirect3DTexture8 *texture;
5285 IDirect3DSurface8 *surface;
5286 IDirect3DSurface8 *rt, *ds;
5287 D3DLOCKED_RECT locked_rect;
5288 IDirect3DDevice8 *device;
5289 D3DSURFACE_DESC desc;
5290 IDirect3D8 *d3d;
5291 ULONG refcount;
5292 HWND window;
5293 HRESULT hr;
5295 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5296 ok(!!d3d, "Failed to create a D3D object.\n");
5298 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5299 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
5300 if (hr != D3D_OK)
5302 skip("No D3DFMT_NULL support, skipping test.\n");
5303 IDirect3D8_Release(d3d);
5304 return;
5307 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5308 0, 0, 640, 480, 0, 0, 0, 0);
5309 if (!(device = create_device(d3d, window, NULL)))
5311 skip("Failed to create a D3D device, skipping tests.\n");
5312 IDirect3D8_Release(d3d);
5313 DestroyWindow(window);
5314 return;
5317 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5318 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
5319 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
5321 hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5322 D3DFMT_NULL, D3DFMT_D24S8);
5323 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
5325 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
5326 D3DMULTISAMPLE_NONE, TRUE, &surface);
5327 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5329 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
5330 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
5332 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds);
5333 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
5335 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
5336 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5338 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
5339 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
5341 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
5342 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5344 IDirect3DSurface8_Release(rt);
5345 IDirect3DSurface8_Release(ds);
5347 hr = IDirect3DSurface8_GetDesc(surface, &desc);
5348 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5349 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
5350 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
5352 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5353 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5354 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
5355 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
5357 hr = IDirect3DSurface8_UnlockRect(surface);
5358 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5360 IDirect3DSurface8_Release(surface);
5362 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
5363 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture);
5364 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5365 IDirect3DTexture8_Release(texture);
5367 refcount = IDirect3DDevice8_Release(device);
5368 ok(!refcount, "Device has %u references left.\n", refcount);
5369 IDirect3D8_Release(d3d);
5370 DestroyWindow(window);
5373 static void test_surface_double_unlock(void)
5375 static const D3DPOOL pools[] =
5377 D3DPOOL_DEFAULT,
5378 D3DPOOL_SYSTEMMEM,
5380 IDirect3DSurface8 *surface;
5381 IDirect3DDevice8 *device;
5382 D3DLOCKED_RECT lr;
5383 IDirect3D8 *d3d;
5384 unsigned int i;
5385 ULONG refcount;
5386 HWND window;
5387 HRESULT hr;
5389 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5390 0, 0, 640, 480, 0, 0, 0, 0);
5391 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5392 ok(!!d3d, "Failed to create a D3D object.\n");
5393 if (!(device = create_device(d3d, window, NULL)))
5395 skip("Failed to create a D3D device, skipping tests.\n");
5396 IDirect3D8_Release(d3d);
5397 DestroyWindow(window);
5398 return;
5401 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
5403 switch (pools[i])
5405 case D3DPOOL_DEFAULT:
5406 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5407 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
5408 if (FAILED(hr))
5410 skip("D3DFMT_X8R8G8B8 render targets not supported, skipping double unlock DEFAULT pool test.\n");
5411 continue;
5414 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_X8R8G8B8,
5415 D3DMULTISAMPLE_NONE, TRUE, &surface);
5416 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5417 break;
5419 case D3DPOOL_SYSTEMMEM:
5420 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64, D3DFMT_X8R8G8B8, &surface);
5421 ok(SUCCEEDED(hr), "Failed to create image surface, hr %#x.\n", hr);
5422 break;
5424 default:
5425 break;
5428 hr = IDirect3DSurface8_UnlockRect(surface);
5429 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5430 hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
5431 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
5432 hr = IDirect3DSurface8_UnlockRect(surface);
5433 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
5434 hr = IDirect3DSurface8_UnlockRect(surface);
5435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5437 IDirect3DSurface8_Release(surface);
5440 refcount = IDirect3DDevice8_Release(device);
5441 ok(!refcount, "Device has %u references left.\n", refcount);
5442 IDirect3D8_Release(d3d);
5443 DestroyWindow(window);
5446 static void test_surface_blocks(void)
5448 static const struct
5450 D3DFORMAT fmt;
5451 const char *name;
5452 unsigned int block_width;
5453 unsigned int block_height;
5454 BOOL broken;
5455 BOOL create_size_checked, core_fmt;
5457 formats[] =
5459 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
5460 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
5461 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
5462 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
5463 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
5464 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
5465 * which doesn't match the format spec. On newer Nvidia cards
5466 * they have the correct 4x4 block size */
5467 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
5468 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
5469 /* Windows drivers generally enforce block-aligned locks for
5470 * YUY2 and UYVY. The notable exception is the AMD r500 driver
5471 * in d3d8. The same driver checks the sizes in d3d9. */
5472 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, TRUE, FALSE, TRUE },
5473 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, TRUE, FALSE, TRUE },
5475 static const struct
5477 D3DPOOL pool;
5478 const char *name;
5479 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
5480 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
5481 BOOL success;
5483 pools[] =
5485 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
5486 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
5487 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
5488 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
5490 static struct
5492 D3DRESOURCETYPE rtype;
5493 const char *type_name;
5494 D3DPOOL pool;
5495 const char *pool_name;
5496 BOOL need_driver_support, need_runtime_support;
5498 create_tests[] =
5500 /* D3d8 only supports sysmem surfaces, which are created via CreateImageSurface. Other tests confirm
5501 * that they are D3DPOOL_SYSTEMMEM surfaces, but their creation restriction behaves like the scratch
5502 * pool in d3d9. */
5503 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE, TRUE },
5505 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
5506 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
5507 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
5508 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5510 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
5511 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
5512 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
5513 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5515 IDirect3DTexture8 *texture;
5516 IDirect3DCubeTexture8 *cube_texture;
5517 IDirect3DSurface8 *surface;
5518 D3DLOCKED_RECT locked_rect;
5519 IDirect3DDevice8 *device;
5520 unsigned int i, j, k, w, h;
5521 IDirect3D8 *d3d;
5522 ULONG refcount;
5523 HWND window;
5524 HRESULT hr;
5525 RECT rect;
5526 BOOL tex_pow2, cube_pow2;
5527 D3DCAPS8 caps;
5528 static const RECT invalid[] =
5530 {60, 60, 60, 68}, /* 0 height */
5531 {60, 60, 68, 60}, /* 0 width */
5532 {68, 60, 60, 68}, /* left > right */
5533 {60, 68, 68, 60}, /* top > bottom */
5534 {-8, 60, 0, 68}, /* left < surface */
5535 {60, -8, 68, 0}, /* top < surface */
5536 {-16, 60, -8, 68}, /* right < surface */
5537 {60, -16, 68, -8}, /* bottom < surface */
5538 {60, 60, 136, 68}, /* right > surface */
5539 {60, 60, 68, 136}, /* bottom > surface */
5540 {136, 60, 144, 68}, /* left > surface */
5541 {60, 136, 68, 144}, /* top > surface */
5544 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5545 0, 0, 640, 480, 0, 0, 0, 0);
5546 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5547 ok(!!d3d, "Failed to create a D3D object.\n");
5548 if (!(device = create_device(d3d, window, NULL)))
5550 skip("Failed to create a D3D device, skipping tests.\n");
5551 IDirect3D8_Release(d3d);
5552 DestroyWindow(window);
5553 return;
5556 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5557 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5558 tex_pow2 = caps.TextureCaps & D3DPTEXTURECAPS_POW2;
5559 if (tex_pow2)
5560 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
5561 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
5563 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
5565 BOOL tex_support, cube_support, surface_support, format_known;
5567 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5568 0, D3DRTYPE_TEXTURE, formats[i].fmt);
5569 tex_support = SUCCEEDED(hr);
5570 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5571 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
5572 cube_support = SUCCEEDED(hr);
5573 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5574 0, D3DRTYPE_SURFACE, formats[i].fmt);
5575 surface_support = SUCCEEDED(hr);
5577 /* Scratch pool in general allows texture creation even if the driver does
5578 * not support the format. If the format is an extension format that is not
5579 * known to the runtime, like ATI2N, some driver support is required for
5580 * this to work.
5582 * It is also possible that Windows Vista and Windows 7 d3d8 runtimes know
5583 * about ATI2N. I cannot check this because all my Vista+ machines support
5584 * ATI2N in hardware, but none of my WinXP machines do. */
5585 format_known = tex_support || cube_support || surface_support;
5587 for (w = 1; w <= 8; w++)
5589 for (h = 1; h <= 8; h++)
5591 BOOL block_aligned = TRUE;
5592 BOOL size_is_pow2;
5594 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5595 block_aligned = FALSE;
5597 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
5599 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
5601 BOOL support, pow2;
5602 HRESULT expect_hr;
5603 BOOL may_succeed = FALSE;
5604 IUnknown **check_null;
5606 if (!formats[i].core_fmt)
5608 /* AMD warns against creating ATI2N textures smaller than
5609 * the block size because the runtime cannot calculate the
5610 * correct texture size. Generalize this for all extension
5611 * formats. */
5612 if (w < formats[i].block_width || h < formats[i].block_height)
5613 continue;
5616 texture = (IDirect3DTexture8 *)0xdeadbeef;
5617 cube_texture = (IDirect3DCubeTexture8 *)0xdeadbeef;
5618 surface = (IDirect3DSurface8 *)0xdeadbeef;
5620 switch (create_tests[j].rtype)
5622 case D3DRTYPE_TEXTURE:
5623 check_null = (IUnknown **)&texture;
5624 hr = IDirect3DDevice8_CreateTexture(device, w, h, 1, 0,
5625 formats[i].fmt, create_tests[j].pool, &texture);
5626 support = tex_support;
5627 pow2 = tex_pow2;
5628 break;
5630 case D3DRTYPE_CUBETEXTURE:
5631 if (w != h)
5632 continue;
5633 check_null = (IUnknown **)&cube_texture;
5634 hr = IDirect3DDevice8_CreateCubeTexture(device, w, 1, 0,
5635 formats[i].fmt, create_tests[j].pool, &cube_texture);
5636 support = cube_support;
5637 pow2 = cube_pow2;
5638 break;
5640 case D3DRTYPE_SURFACE:
5641 check_null = (IUnknown **)&surface;
5642 hr = IDirect3DDevice8_CreateImageSurface(device, w, h,
5643 formats[i].fmt, &surface);
5644 support = surface_support;
5645 pow2 = FALSE;
5646 break;
5648 default:
5649 pow2 = FALSE;
5650 support = FALSE;
5651 check_null = NULL;
5652 break;
5655 if (create_tests[j].need_driver_support && !support)
5656 expect_hr = D3DERR_INVALIDCALL;
5657 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
5658 expect_hr = D3DERR_INVALIDCALL;
5659 else if (formats[i].create_size_checked && !block_aligned)
5660 expect_hr = D3DERR_INVALIDCALL;
5661 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
5662 expect_hr = D3DERR_INVALIDCALL;
5663 else
5664 expect_hr = D3D_OK;
5666 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
5667 may_succeed = TRUE;
5669 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
5670 * does not support it. Accept scratch creation of extension formats on
5671 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
5672 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
5673 * support it. */
5674 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
5675 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
5676 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
5678 if (FAILED(hr))
5679 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
5680 else
5681 IUnknown_Release(*check_null);
5686 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5687 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
5688 if (FAILED(hr))
5690 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
5691 continue;
5694 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5696 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1,
5697 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
5698 formats[i].fmt, pools[j].pool, &texture);
5699 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5700 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5701 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5702 IDirect3DTexture8_Release(texture);
5704 if (formats[i].block_width > 1)
5706 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
5707 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5708 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5709 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5710 SUCCEEDED(hr) ? "succeeded" : "failed",
5711 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5712 if (SUCCEEDED(hr))
5714 hr = IDirect3DSurface8_UnlockRect(surface);
5715 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5718 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
5719 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5720 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5721 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5722 SUCCEEDED(hr) ? "succeeded" : "failed",
5723 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5724 if (SUCCEEDED(hr))
5726 hr = IDirect3DSurface8_UnlockRect(surface);
5727 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5731 if (formats[i].block_height > 1)
5733 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
5734 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5735 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5736 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5737 SUCCEEDED(hr) ? "succeeded" : "failed",
5738 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5739 if (SUCCEEDED(hr))
5741 hr = IDirect3DSurface8_UnlockRect(surface);
5742 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5745 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
5746 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5747 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5748 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5749 SUCCEEDED(hr) ? "succeeded" : "failed",
5750 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5751 if (SUCCEEDED(hr))
5753 hr = IDirect3DSurface8_UnlockRect(surface);
5754 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5758 for (k = 0; k < sizeof(invalid) / sizeof(*invalid); ++k)
5760 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &invalid[k], 0);
5761 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
5762 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
5763 formats[i].name, pools[j].name, k);
5764 if (SUCCEEDED(hr))
5766 hr = IDirect3DSurface8_UnlockRect(surface);
5767 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5771 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
5772 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5773 ok(hr == D3D_OK, "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
5774 hr = IDirect3DSurface8_UnlockRect(surface);
5775 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5777 IDirect3DSurface8_Release(surface);
5780 if (formats[i].block_width == 1 && formats[i].block_height == 1)
5781 continue;
5782 if (!formats[i].core_fmt)
5783 continue;
5785 hr = IDirect3DDevice8_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
5786 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture);
5787 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
5789 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, NULL, 0);
5790 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5791 hr = IDirect3DTexture8_UnlockRect(texture, 1);
5792 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5794 rect.left = 0;
5795 rect.top = 0;
5796 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
5797 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
5798 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
5799 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5800 hr = IDirect3DTexture8_UnlockRect(texture, 1);
5801 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5803 rect.right = formats[i].block_width;
5804 rect.bottom = formats[i].block_height;
5805 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
5806 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5807 if (SUCCEEDED(hr))
5808 IDirect3DTexture8_UnlockRect(texture, 1);
5810 IDirect3DTexture8_Release(texture);
5813 refcount = IDirect3DDevice8_Release(device);
5814 ok(!refcount, "Device has %u references left.\n", refcount);
5815 IDirect3D8_Release(d3d);
5816 DestroyWindow(window);
5819 static void test_set_palette(void)
5821 IDirect3DDevice8 *device;
5822 IDirect3D8 *d3d8;
5823 UINT refcount;
5824 HWND window;
5825 HRESULT hr;
5826 PALETTEENTRY pal[256];
5827 unsigned int i;
5828 D3DCAPS8 caps;
5830 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5831 0, 0, 640, 480, 0, 0, 0, 0);
5832 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5833 ok(!!d3d8, "Failed to create a D3D object.\n");
5834 if (!(device = create_device(d3d8, window, NULL)))
5836 skip("Failed to create a D3D device, skipping tests.\n");
5837 IDirect3D8_Release(d3d8);
5838 DestroyWindow(window);
5839 return;
5842 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
5844 pal[i].peRed = i;
5845 pal[i].peGreen = i;
5846 pal[i].peBlue = i;
5847 pal[i].peFlags = 0xff;
5849 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5850 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
5852 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5853 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5854 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
5856 pal[i].peRed = i;
5857 pal[i].peGreen = i;
5858 pal[i].peBlue = i;
5859 pal[i].peFlags = i;
5861 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
5863 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5864 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
5866 else
5868 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5869 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
5872 refcount = IDirect3DDevice8_Release(device);
5873 ok(!refcount, "Device has %u references left.\n", refcount);
5874 IDirect3D8_Release(d3d8);
5875 DestroyWindow(window);
5878 static void test_swvp_buffer(void)
5880 IDirect3DDevice8 *device;
5881 IDirect3D8 *d3d8;
5882 UINT refcount;
5883 HWND window;
5884 HRESULT hr;
5885 unsigned int i;
5886 IDirect3DVertexBuffer8 *buffer;
5887 static const unsigned int bufsize = 1024;
5888 D3DVERTEXBUFFER_DESC desc;
5889 struct device_desc device_desc;
5890 struct
5892 float x, y, z;
5893 } *ptr, *ptr2;
5895 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5896 0, 0, 640, 480, 0, 0, 0, 0);
5897 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5898 ok(!!d3d8, "Failed to create a D3D object.\n");
5900 device_desc.device_window = window;
5901 device_desc.width = 640;
5902 device_desc.height = 480;
5903 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
5904 if (!(device = create_device(d3d8, window, &device_desc)))
5906 skip("Failed to create a D3D device, skipping tests.\n");
5907 IDirect3D8_Release(d3d8);
5908 DestroyWindow(window);
5909 return;
5912 hr = IDirect3DDevice8_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
5913 D3DPOOL_DEFAULT, &buffer);
5914 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
5915 hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
5916 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
5917 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
5918 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
5919 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
5921 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
5922 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
5923 for (i = 0; i < bufsize; i++)
5925 ptr[i].x = i * 1.0f;
5926 ptr[i].y = i * 2.0f;
5927 ptr[i].z = i * 3.0f;
5929 hr = IDirect3DVertexBuffer8_Unlock(buffer);
5930 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
5932 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
5933 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
5934 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
5935 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
5936 hr = IDirect3DDevice8_BeginScene(device);
5937 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5938 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
5939 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5940 hr = IDirect3DDevice8_EndScene(device);
5941 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5943 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
5944 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
5945 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
5946 for (i = 0; i < bufsize; i++)
5948 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
5950 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
5951 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
5952 break;
5955 hr = IDirect3DVertexBuffer8_Unlock(buffer);
5956 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
5958 IDirect3DVertexBuffer8_Release(buffer);
5959 refcount = IDirect3DDevice8_Release(device);
5960 ok(!refcount, "Device has %u references left.\n", refcount);
5961 IDirect3D8_Release(d3d8);
5962 DestroyWindow(window);
5965 static void test_managed_buffer(void)
5967 static const unsigned int vertex_count = 1024;
5968 IDirect3DVertexBuffer8 *buffer;
5969 D3DVERTEXBUFFER_DESC desc;
5970 IDirect3DDevice8 *device;
5971 struct vec3 *ptr, *ptr2;
5972 IDirect3D8 *d3d8;
5973 unsigned int i;
5974 UINT refcount;
5975 HWND window;
5976 HRESULT hr;
5978 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
5979 0, 0, 640, 480, 0, 0, 0, 0);
5980 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5981 ok(!!d3d8, "Failed to create a D3D object.\n");
5982 if (!(device = create_device(d3d8, window, NULL)))
5984 skip("Failed to create a D3D device, skipping tests.\n");
5985 IDirect3D8_Release(d3d8);
5986 DestroyWindow(window);
5987 return;
5990 hr = IDirect3DDevice8_CreateVertexBuffer(device, vertex_count * sizeof(*ptr), 0, 0, D3DPOOL_MANAGED, &buffer);
5991 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
5992 hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
5993 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
5994 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
5995 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
5997 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
5998 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
5999 for (i = 0; i < vertex_count; ++i)
6001 ptr[i].x = i * 1.0f;
6002 ptr[i].y = i * 2.0f;
6003 ptr[i].z = i * 3.0f;
6005 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6006 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6008 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
6009 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6010 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
6011 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6012 hr = IDirect3DDevice8_BeginScene(device);
6013 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6014 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6015 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6016 hr = IDirect3DDevice8_EndScene(device);
6017 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6019 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
6020 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6021 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
6022 for (i = 0; i < vertex_count; ++i)
6024 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6026 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
6027 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6028 break;
6031 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6032 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6034 IDirect3DVertexBuffer8_Release(buffer);
6035 refcount = IDirect3DDevice8_Release(device);
6036 ok(!refcount, "Device has %u references left.\n", refcount);
6037 IDirect3D8_Release(d3d8);
6038 DestroyWindow(window);
6041 static void test_npot_textures(void)
6043 IDirect3DDevice8 *device = NULL;
6044 IDirect3D8 *d3d8;
6045 ULONG refcount;
6046 HWND window = NULL;
6047 HRESULT hr;
6048 D3DCAPS8 caps;
6049 IDirect3DTexture8 *texture;
6050 IDirect3DCubeTexture8 *cube_texture;
6051 IDirect3DVolumeTexture8 *volume_texture;
6052 struct
6054 D3DPOOL pool;
6055 const char *pool_name;
6056 HRESULT hr;
6058 pools[] =
6060 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
6061 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
6062 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
6063 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
6065 unsigned int i, levels;
6066 BOOL tex_pow2, cube_pow2, vol_pow2;
6068 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6069 0, 0, 640, 480, 0, 0, 0, 0);
6070 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6071 ok(!!d3d8, "Failed to create a D3D object.\n");
6072 if (!(device = create_device(d3d8, window, NULL)))
6074 skip("Failed to create a D3D device, skipping tests.\n");
6075 goto done;
6078 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6079 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6080 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
6081 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6082 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6083 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
6084 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
6086 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
6088 for (levels = 0; levels <= 2; levels++)
6090 HRESULT expected;
6092 hr = IDirect3DDevice8_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
6093 pools[i].pool, &texture);
6094 if (!tex_pow2)
6096 expected = D3D_OK;
6098 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
6100 if (levels == 1)
6101 expected = D3D_OK;
6102 else
6103 expected = pools[i].hr;
6105 else
6107 expected = pools[i].hr;
6109 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
6110 pools[i].pool_name, levels, hr, expected);
6112 if (SUCCEEDED(hr))
6113 IDirect3DTexture8_Release(texture);
6116 hr = IDirect3DDevice8_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8,
6117 pools[i].pool, &cube_texture);
6118 if (tex_pow2)
6120 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6121 pools[i].pool_name, hr, pools[i].hr);
6123 else
6125 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6126 pools[i].pool_name, hr, D3D_OK);
6129 if (SUCCEEDED(hr))
6130 IDirect3DCubeTexture8_Release(cube_texture);
6132 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8,
6133 pools[i].pool, &volume_texture);
6134 if (tex_pow2)
6136 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6137 pools[i].pool_name, hr, pools[i].hr);
6139 else
6141 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6142 pools[i].pool_name, hr, D3D_OK);
6145 if (SUCCEEDED(hr))
6146 IDirect3DVolumeTexture8_Release(volume_texture);
6149 done:
6150 if (device)
6152 refcount = IDirect3DDevice8_Release(device);
6153 ok(!refcount, "Device has %u references left.\n", refcount);
6155 IDirect3D8_Release(d3d8);
6156 DestroyWindow(window);
6160 static void test_volume_locking(void)
6162 IDirect3DDevice8 *device;
6163 IDirect3D8 *d3d8;
6164 HWND window;
6165 HRESULT hr;
6166 IDirect3DVolumeTexture8 *texture;
6167 unsigned int i;
6168 D3DLOCKED_BOX locked_box;
6169 ULONG refcount;
6170 D3DCAPS8 caps;
6171 static const struct
6173 D3DPOOL pool;
6174 DWORD usage;
6175 HRESULT create_hr, lock_hr;
6177 tests[] =
6179 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
6180 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6181 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
6182 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6183 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
6184 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6185 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
6186 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6189 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6190 0, 0, 640, 480, 0, 0, 0, 0);
6191 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6192 ok(!!d3d8, "Failed to create a D3D object.\n");
6193 if (!(device = create_device(d3d8, window, NULL)))
6195 skip("Failed to create a D3D device, skipping tests.\n");
6196 IDirect3D8_Release(d3d8);
6197 DestroyWindow(window);
6198 return;
6201 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6202 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6203 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6205 skip("Volume textures not supported, skipping test.\n");
6206 goto out;
6209 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6211 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
6212 D3DFMT_A8R8G8B8, tests[i].pool, &texture);
6213 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
6214 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
6215 if (FAILED(hr))
6216 continue;
6218 locked_box.pBits = (void *)0xdeadbeef;
6219 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6220 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
6221 if (SUCCEEDED(hr))
6223 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6224 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6226 else
6228 ok (locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
6230 IDirect3DVolumeTexture8_Release(texture);
6233 out:
6234 refcount = IDirect3DDevice8_Release(device);
6235 ok(!refcount, "Device has %u references left.\n", refcount);
6236 IDirect3D8_Release(d3d8);
6237 DestroyWindow(window);
6240 static void test_update_volumetexture(void)
6242 IDirect3DDevice8 *device;
6243 IDirect3D8 *d3d8;
6244 HWND window;
6245 HRESULT hr;
6246 IDirect3DVolumeTexture8 *src, *dst;
6247 unsigned int i;
6248 D3DLOCKED_BOX locked_box;
6249 ULONG refcount;
6250 D3DCAPS8 caps;
6251 static const struct
6253 D3DPOOL src_pool, dst_pool;
6254 HRESULT hr;
6256 tests[] =
6258 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6259 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6260 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
6261 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6263 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6264 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6265 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6266 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6268 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6269 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6270 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6271 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6273 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6274 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6275 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6276 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6278 static const struct
6280 UINT src_size, dst_size;
6281 UINT src_lvl, dst_lvl;
6282 D3DFORMAT src_fmt, dst_fmt;
6284 tests2[] =
6286 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6287 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6288 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6289 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6290 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6291 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
6292 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
6293 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
6296 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6297 0, 0, 640, 480, 0, 0, 0, 0);
6298 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6299 ok(!!d3d8, "Failed to create a D3D object.\n");
6300 if (!(device = create_device(d3d8, window, NULL)))
6302 skip("Failed to create a D3D device, skipping tests.\n");
6303 IDirect3D8_Release(d3d8);
6304 DestroyWindow(window);
6305 return;
6308 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6309 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6310 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6312 skip("Volume textures not supported, skipping test.\n");
6313 goto out;
6316 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6318 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6319 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6321 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
6322 D3DFMT_A8R8G8B8, tests[i].src_pool, &src);
6323 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6324 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
6325 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst);
6326 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6328 hr = IDirect3DVolumeTexture8_LockBox(src, 0, &locked_box, NULL, 0);
6329 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6330 *((DWORD *)locked_box.pBits) = 0x11223344;
6331 hr = IDirect3DVolumeTexture8_UnlockBox(src, 0);
6332 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6334 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src, (IDirect3DBaseTexture8 *)dst);
6335 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
6336 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
6338 if (SUCCEEDED(hr))
6340 DWORD content = *((DWORD *)locked_box.pBits);
6341 hr = IDirect3DVolumeTexture8_LockBox(dst, 0, &locked_box, NULL, 0);
6342 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6343 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
6344 hr = IDirect3DVolumeTexture8_UnlockBox(dst, 0);
6345 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6347 IDirect3DVolumeTexture8_Release(src);
6348 IDirect3DVolumeTexture8_Release(dst);
6351 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
6353 skip("Mipmapped volume maps not supported.\n");
6354 goto out;
6357 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
6359 hr = IDirect3DDevice8_CreateVolumeTexture(device,
6360 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
6361 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src);
6362 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6363 hr = IDirect3DDevice8_CreateVolumeTexture(device,
6364 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
6365 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst);
6366 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6368 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src, (IDirect3DBaseTexture8 *)dst);
6369 todo_wine_if (FAILED(hr))
6370 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
6372 IDirect3DVolumeTexture8_Release(src);
6373 IDirect3DVolumeTexture8_Release(dst);
6376 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
6377 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
6378 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
6379 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
6380 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
6382 * I'm not adding tests for this behavior until an application needs it. */
6384 out:
6385 refcount = IDirect3DDevice8_Release(device);
6386 ok(!refcount, "Device has %u references left.\n", refcount);
6387 IDirect3D8_Release(d3d8);
6388 DestroyWindow(window);
6391 static void test_create_rt_ds_fail(void)
6393 IDirect3DDevice8 *device;
6394 HWND window;
6395 HRESULT hr;
6396 ULONG refcount;
6397 IDirect3D8 *d3d8;
6398 IDirect3DSurface8 *surface;
6400 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6401 0, 0, 640, 480, 0, 0, 0, 0);
6402 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6403 ok(!!d3d8, "Failed to create a D3D object.\n");
6404 if (!(device = create_device(d3d8, window, NULL)))
6406 skip("Failed to create a D3D device, skipping tests.\n");
6407 IDirect3D8_Release(d3d8);
6408 DestroyWindow(window);
6409 return;
6412 /* Output pointer == NULL segfaults on Windows. */
6414 surface = (IDirect3DSurface8 *)0xdeadbeef;
6415 hr = IDirect3DDevice8_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
6416 D3DMULTISAMPLE_NONE, FALSE, &surface);
6417 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
6418 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6419 if (SUCCEEDED(hr))
6420 IDirect3DSurface8_Release(surface);
6422 surface = (IDirect3DSurface8 *)0xdeadbeef;
6423 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
6424 D3DMULTISAMPLE_NONE, &surface);
6425 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
6426 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6427 if (SUCCEEDED(hr))
6428 IDirect3DSurface8_Release(surface);
6430 refcount = IDirect3DDevice8_Release(device);
6431 ok(!refcount, "Device has %u references left.\n", refcount);
6432 IDirect3D8_Release(d3d8);
6433 DestroyWindow(window);
6436 static void test_volume_blocks(void)
6438 IDirect3DDevice8 *device;
6439 IDirect3D8 *d3d8;
6440 UINT refcount;
6441 HWND window;
6442 HRESULT hr;
6443 D3DCAPS8 caps;
6444 IDirect3DVolumeTexture8 *texture;
6445 unsigned int w, h, d, i, j;
6446 static const struct
6448 D3DFORMAT fmt;
6449 const char *name;
6450 unsigned int block_width;
6451 unsigned int block_height;
6452 unsigned int block_depth;
6453 unsigned int block_size;
6454 unsigned int broken;
6455 BOOL create_size_checked, core_fmt;
6457 formats[] =
6459 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
6460 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
6461 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
6462 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
6463 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
6464 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
6465 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
6466 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
6467 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
6468 * which doesn't match the format spec. On newer Nvidia cards
6469 * it has the correct 4x4 block size.
6470 * ATI1N volume textures are only supported by AMD GPUs right
6471 * now and locking offsets seem just wrong. */
6472 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
6473 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
6474 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
6475 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
6477 static const struct
6479 D3DPOOL pool;
6480 const char *name;
6481 BOOL need_driver_support, need_runtime_support;
6483 create_tests[] =
6485 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6486 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6487 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
6488 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
6490 static const struct
6492 unsigned int x, y, z, x2, y2, z2;
6494 offset_tests[] =
6496 {0, 0, 0, 8, 8, 8},
6497 {0, 0, 3, 8, 8, 8},
6498 {0, 4, 0, 8, 8, 8},
6499 {0, 4, 3, 8, 8, 8},
6500 {4, 0, 0, 8, 8, 8},
6501 {4, 0, 3, 8, 8, 8},
6502 {4, 4, 0, 8, 8, 8},
6503 {4, 4, 3, 8, 8, 8},
6505 D3DBOX box;
6506 D3DLOCKED_BOX locked_box;
6507 BYTE *base;
6508 INT expected_row_pitch, expected_slice_pitch;
6509 BOOL support;
6510 BOOL pow2;
6511 unsigned int offset, expected_offset;
6513 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6514 0, 0, 640, 480, 0, 0, 0, 0);
6515 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6516 ok(!!d3d8, "Failed to create a D3D object.\n");
6517 if (!(device = create_device(d3d8, window, NULL)))
6519 skip("Failed to create a D3D device, skipping tests.\n");
6520 IDirect3D8_Release(d3d8);
6521 DestroyWindow(window);
6522 return;
6524 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6525 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6526 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6528 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
6530 hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6531 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
6532 support = SUCCEEDED(hr);
6534 /* Test creation restrictions */
6535 for (w = 1; w <= 8; w++)
6537 for (h = 1; h <= 8; h++)
6539 for (d = 1; d <= 8; d++)
6541 HRESULT expect_hr;
6542 BOOL size_is_pow2;
6543 BOOL block_aligned = TRUE;
6545 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6546 block_aligned = FALSE;
6548 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
6550 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
6552 BOOL may_succeed = FALSE;
6554 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
6555 expect_hr = D3DERR_INVALIDCALL;
6556 else if (formats[i].create_size_checked && !block_aligned)
6557 expect_hr = D3DERR_INVALIDCALL;
6558 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6559 expect_hr = D3DERR_INVALIDCALL;
6560 else if (create_tests[j].need_driver_support && !support)
6561 expect_hr = D3DERR_INVALIDCALL;
6562 else
6563 expect_hr = D3D_OK;
6565 texture = (IDirect3DVolumeTexture8 *)0xdeadbeef;
6566 hr = IDirect3DDevice8_CreateVolumeTexture(device, w, h, d, 1, 0,
6567 formats[i].fmt, create_tests[j].pool, &texture);
6569 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6570 * does not support it. Accept scratch creation of extension formats on
6571 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6572 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6573 * support it. */
6574 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
6575 may_succeed = TRUE;
6577 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6578 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
6579 hr, formats[i].name, create_tests[j].name, w, h, d);
6581 if (FAILED(hr))
6582 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
6583 else
6584 IDirect3DVolumeTexture8_Release(texture);
6590 if (!support && !formats[i].core_fmt)
6591 continue;
6593 hr = IDirect3DDevice8_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
6594 formats[i].fmt, D3DPOOL_SCRATCH, &texture);
6595 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6597 /* Test lockrect offset */
6598 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
6600 unsigned int bytes_per_pixel;
6601 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
6603 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6604 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6606 base = locked_box.pBits;
6607 if (formats[i].broken == 1)
6609 expected_row_pitch = bytes_per_pixel * 24;
6611 else if (formats[i].broken == 2)
6613 expected_row_pitch = 24;
6615 else
6617 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
6618 * formats[i].block_size;
6620 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
6621 locked_box.RowPitch, formats[i].name, expected_row_pitch);
6623 if (formats[i].broken)
6625 expected_slice_pitch = expected_row_pitch * 8;
6627 else
6629 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
6630 * expected_row_pitch;
6632 ok(locked_box.SlicePitch == expected_slice_pitch,
6633 "Got unexpected slice pitch %d for format %s, expected %d.\n",
6634 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
6636 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6637 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
6639 box.Left = offset_tests[j].x;
6640 box.Top = offset_tests[j].y;
6641 box.Front = offset_tests[j].z;
6642 box.Right = offset_tests[j].x2;
6643 box.Bottom = offset_tests[j].y2;
6644 box.Back = offset_tests[j].z2;
6645 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6646 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
6648 offset = (BYTE *)locked_box.pBits - base;
6649 if (formats[i].broken == 1)
6651 expected_offset = box.Front * expected_slice_pitch
6652 + box.Top * expected_row_pitch
6653 + box.Left * bytes_per_pixel;
6655 else if (formats[i].broken == 2)
6657 expected_offset = box.Front * expected_slice_pitch
6658 + box.Top * expected_row_pitch
6659 + box.Left;
6661 else
6663 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
6664 + (box.Top / formats[i].block_height) * expected_row_pitch
6665 + (box.Left / formats[i].block_width) * formats[i].block_size;
6667 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
6668 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
6670 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6671 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6674 /* Test partial block locks */
6675 box.Front = 0;
6676 box.Back = 1;
6677 if (formats[i].block_width > 1)
6679 box.Left = formats[i].block_width >> 1;
6680 box.Top = 0;
6681 box.Right = formats[i].block_width;
6682 box.Bottom = formats[i].block_height;
6683 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6684 ok(FAILED(hr) || broken(formats[i].broken),
6685 "Partial block lock succeeded, expected failure, format %s.\n",
6686 formats[i].name);
6687 if (SUCCEEDED(hr))
6689 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6690 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6693 box.Left = 0;
6694 box.Top = 0;
6695 box.Right = formats[i].block_width >> 1;
6696 box.Bottom = formats[i].block_height;
6697 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6698 ok(FAILED(hr) || broken(formats[i].broken),
6699 "Partial block lock succeeded, expected failure, format %s.\n",
6700 formats[i].name);
6701 if (SUCCEEDED(hr))
6703 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6704 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6708 if (formats[i].block_height > 1)
6710 box.Left = 0;
6711 box.Top = formats[i].block_height >> 1;
6712 box.Right = formats[i].block_width;
6713 box.Bottom = formats[i].block_height;
6714 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6715 ok(FAILED(hr) || broken(formats[i].broken),
6716 "Partial block lock succeeded, expected failure, format %s.\n",
6717 formats[i].name);
6718 if (SUCCEEDED(hr))
6720 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6721 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6724 box.Left = 0;
6725 box.Top = 0;
6726 box.Right = formats[i].block_width;
6727 box.Bottom = formats[i].block_height >> 1;
6728 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6729 ok(FAILED(hr) || broken(formats[i].broken),
6730 "Partial block lock succeeded, expected failure, format %s.\n",
6731 formats[i].name);
6732 if (SUCCEEDED(hr))
6734 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6735 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6739 /* Test full block lock */
6740 box.Left = 0;
6741 box.Top = 0;
6742 box.Right = formats[i].block_width;
6743 box.Bottom = formats[i].block_height;
6744 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6745 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6746 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6747 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6749 IDirect3DVolumeTexture8_Release(texture);
6751 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
6752 * does not allocate surfaces smaller than the blocksize properly. */
6753 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
6755 hr = IDirect3DDevice8_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
6756 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture);
6758 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
6759 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, NULL, 0);
6760 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
6761 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6762 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6764 box.Left = box.Top = box.Front = 0;
6765 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
6766 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
6767 box.Back = 1;
6768 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
6769 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
6770 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6771 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6773 box.Right = formats[i].block_width;
6774 box.Bottom = formats[i].block_height;
6775 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
6776 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6777 if (SUCCEEDED(hr))
6778 IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6780 IDirect3DVolumeTexture8_Release(texture);
6784 refcount = IDirect3DDevice8_Release(device);
6785 ok(!refcount, "Device has %u references left.\n", refcount);
6786 IDirect3D8_Release(d3d8);
6787 DestroyWindow(window);
6790 static void test_lockbox_invalid(void)
6792 static const struct
6794 D3DBOX box;
6795 HRESULT result;
6797 test_data[] =
6799 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
6800 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
6801 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
6802 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
6803 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
6804 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
6805 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
6806 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
6807 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
6808 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
6809 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
6810 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
6811 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
6812 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
6814 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
6815 IDirect3DVolumeTexture8 *texture = NULL;
6816 D3DLOCKED_BOX locked_box;
6817 IDirect3DDevice8 *device;
6818 IDirect3D8 *d3d;
6819 unsigned int i;
6820 ULONG refcount;
6821 HWND window;
6822 BYTE *base;
6823 HRESULT hr;
6825 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
6826 0, 0, 640, 480, 0, 0, 0, 0);
6827 d3d = Direct3DCreate8(D3D_SDK_VERSION);
6828 ok(!!d3d, "Failed to create a D3D object.\n");
6829 if (!(device = create_device(d3d, window, NULL)))
6831 skip("Failed to create a D3D device, skipping tests.\n");
6832 IDirect3D8_Release(d3d);
6833 DestroyWindow(window);
6834 return;
6837 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
6838 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
6839 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6840 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6841 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6842 base = locked_box.pBits;
6843 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6844 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6846 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
6848 unsigned int offset, expected_offset;
6849 const D3DBOX *box = &test_data[i].box;
6851 locked_box.pBits = (BYTE *)0xdeadbeef;
6852 locked_box.RowPitch = 0xdeadbeef;
6853 locked_box.SlicePitch = 0xdeadbeef;
6855 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, box, 0);
6856 /* Unlike surfaces, volumes properly check the box even in Windows XP */
6857 ok(hr == test_data[i].result,
6858 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
6859 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
6860 test_data[i].result);
6861 if (FAILED(hr))
6862 continue;
6864 offset = (BYTE *)locked_box.pBits - base;
6865 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
6866 ok(offset == expected_offset,
6867 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
6868 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
6870 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6871 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6874 /* locked_box = NULL throws an exception on Windows */
6875 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6876 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6877 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6878 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6879 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6880 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6881 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6882 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6884 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
6885 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
6886 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
6887 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
6888 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
6889 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
6890 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
6891 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
6892 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
6893 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
6894 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
6895 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
6896 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6897 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6899 IDirect3DVolumeTexture8_Release(texture);
6900 refcount = IDirect3DDevice8_Release(device);
6901 ok(!refcount, "Device has %u references left.\n", refcount);
6902 IDirect3D8_Release(d3d);
6903 DestroyWindow(window);
6906 static void test_pixel_format(void)
6908 HWND hwnd, hwnd2 = NULL;
6909 HDC hdc, hdc2 = NULL;
6910 HMODULE gl = NULL;
6911 int format, test_format;
6912 PIXELFORMATDESCRIPTOR pfd;
6913 IDirect3D8 *d3d8 = NULL;
6914 IDirect3DDevice8 *device = NULL;
6915 HRESULT hr;
6916 static const float point[3] = {0.0, 0.0, 0.0};
6918 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
6919 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6920 if (!hwnd)
6922 skip("Failed to create window\n");
6923 return;
6926 hwnd2 = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
6927 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6929 hdc = GetDC(hwnd);
6930 if (!hdc)
6932 skip("Failed to get DC\n");
6933 goto cleanup;
6936 if (hwnd2)
6937 hdc2 = GetDC(hwnd2);
6939 gl = LoadLibraryA("opengl32.dll");
6940 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
6942 format = GetPixelFormat(hdc);
6943 ok(format == 0, "new window has pixel format %d\n", format);
6945 ZeroMemory(&pfd, sizeof(pfd));
6946 pfd.nSize = sizeof(pfd);
6947 pfd.nVersion = 1;
6948 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
6949 pfd.iPixelType = PFD_TYPE_RGBA;
6950 pfd.iLayerType = PFD_MAIN_PLANE;
6951 format = ChoosePixelFormat(hdc, &pfd);
6952 if (format <= 0)
6954 skip("no pixel format available\n");
6955 goto cleanup;
6958 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
6960 skip("failed to set pixel format\n");
6961 goto cleanup;
6964 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
6966 skip("failed to set pixel format on second window\n");
6967 if (hdc2)
6969 ReleaseDC(hwnd2, hdc2);
6970 hdc2 = NULL;
6974 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6975 ok(!!d3d8, "Failed to create a D3D object.\n");
6977 test_format = GetPixelFormat(hdc);
6978 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6980 if (!(device = create_device(d3d8, hwnd, NULL)))
6982 skip("Failed to create device\n");
6983 goto cleanup;
6986 test_format = GetPixelFormat(hdc);
6987 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6989 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
6990 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
6992 test_format = GetPixelFormat(hdc);
6993 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6995 hr = IDirect3DDevice8_BeginScene(device);
6996 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
6998 test_format = GetPixelFormat(hdc);
6999 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7001 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
7002 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7004 test_format = GetPixelFormat(hdc);
7005 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7007 hr = IDirect3DDevice8_EndScene(device);
7008 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
7010 test_format = GetPixelFormat(hdc);
7011 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7013 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7014 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
7016 test_format = GetPixelFormat(hdc);
7017 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7019 if (hdc2)
7021 hr = IDirect3DDevice8_Present(device, NULL, NULL, hwnd2, NULL);
7022 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
7024 test_format = GetPixelFormat(hdc);
7025 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7027 test_format = GetPixelFormat(hdc2);
7028 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7031 cleanup:
7032 if (device)
7034 UINT refcount = IDirect3DDevice8_Release(device);
7035 ok(!refcount, "Device has %u references left.\n", refcount);
7037 if (d3d8) IDirect3D8_Release(d3d8);
7038 if (gl) FreeLibrary(gl);
7039 if (hdc) ReleaseDC(hwnd, hdc);
7040 if (hdc2) ReleaseDC(hwnd2, hdc2);
7041 if (hwnd) DestroyWindow(hwnd);
7042 if (hwnd2) DestroyWindow(hwnd2);
7045 static void test_begin_end_state_block(void)
7047 IDirect3DDevice8 *device;
7048 DWORD stateblock;
7049 IDirect3D8 *d3d;
7050 ULONG refcount;
7051 HWND window;
7052 HRESULT hr;
7054 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7055 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7056 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7057 ok(!!d3d, "Failed to create a D3D object.\n");
7058 if (!(device = create_device(d3d, window, NULL)))
7060 skip("Failed to create a D3D device, skipping tests.\n");
7061 IDirect3D8_Release(d3d);
7062 DestroyWindow(window);
7063 return;
7066 /* Should succeed. */
7067 hr = IDirect3DDevice8_BeginStateBlock(device);
7068 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
7070 /* Calling BeginStateBlock() while recording should return
7071 * D3DERR_INVALIDCALL. */
7072 hr = IDirect3DDevice8_BeginStateBlock(device);
7073 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7075 /* Should succeed. */
7076 stateblock = 0xdeadbeef;
7077 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7078 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
7079 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
7080 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
7082 /* Calling EndStateBlock() while not recording should return
7083 * D3DERR_INVALIDCALL. stateblock should not be touched. */
7084 stateblock = 0xdeadbeef;
7085 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7086 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7087 ok(stateblock == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
7089 refcount = IDirect3DDevice8_Release(device);
7090 ok(!refcount, "Device has %u references left.\n", refcount);
7091 IDirect3D8_Release(d3d);
7092 DestroyWindow(window);
7095 static void test_shader_constant_apply(void)
7097 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
7098 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
7099 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
7100 DWORD vs_version, ps_version;
7101 IDirect3DDevice8 *device;
7102 DWORD stateblock;
7103 IDirect3D8 *d3d;
7104 ULONG refcount;
7105 D3DCAPS8 caps;
7106 float ret[4];
7107 HWND window;
7108 HRESULT hr;
7110 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7111 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7112 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7113 ok(!!d3d, "Failed to create a D3D object.\n");
7114 if (!(device = create_device(d3d, window, NULL)))
7116 skip("Failed to create a D3D device, skipping tests.\n");
7117 IDirect3D8_Release(d3d);
7118 DestroyWindow(window);
7119 return;
7122 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7123 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7124 vs_version = caps.VertexShaderVersion & 0xffff;
7125 ps_version = caps.PixelShaderVersion & 0xffff;
7127 if (vs_version)
7129 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, initial, 1);
7130 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7131 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, initial, 1);
7132 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7134 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7135 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7136 ok(!memcmp(ret, initial, sizeof(initial)),
7137 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7138 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7139 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7140 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7141 ok(!memcmp(ret, initial, sizeof(initial)),
7142 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7143 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7145 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, vs_const, 1);
7146 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7148 if (ps_version)
7150 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, initial, 1);
7151 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7152 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, initial, 1);
7153 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7155 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7156 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7157 ok(!memcmp(ret, initial, sizeof(initial)),
7158 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7159 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7160 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7161 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7162 ok(!memcmp(ret, initial, sizeof(initial)),
7163 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7164 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7166 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, ps_const, 1);
7167 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7170 hr = IDirect3DDevice8_BeginStateBlock(device);
7171 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
7173 if (vs_version)
7175 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, vs_const, 1);
7176 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7178 if (ps_version)
7180 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, ps_const, 1);
7181 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7184 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7185 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
7187 if (vs_version)
7189 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7190 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7191 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7192 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7193 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7194 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7195 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7196 ok(!memcmp(ret, initial, sizeof(initial)),
7197 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7198 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7200 if (ps_version)
7202 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7203 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7204 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7205 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7206 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7207 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7208 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7209 ok(!memcmp(ret, initial, sizeof(initial)),
7210 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7211 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7214 /* Apply doesn't overwrite constants that aren't explicitly set on the
7215 * source stateblock. */
7216 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
7217 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
7219 if (vs_version)
7221 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7222 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7223 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7224 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7225 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7226 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7227 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7228 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7229 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7230 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7232 if (ps_version)
7234 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7235 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7236 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7237 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7238 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7239 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7240 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7241 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7242 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7243 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7246 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
7247 refcount = IDirect3DDevice8_Release(device);
7248 ok(!refcount, "Device has %u references left.\n", refcount);
7249 IDirect3D8_Release(d3d);
7250 DestroyWindow(window);
7253 static void test_resource_type(void)
7255 IDirect3DDevice8 *device;
7256 IDirect3DSurface8 *surface;
7257 IDirect3DTexture8 *texture;
7258 IDirect3DCubeTexture8 *cube_texture;
7259 IDirect3DVolume8 *volume;
7260 IDirect3DVolumeTexture8 *volume_texture;
7261 D3DSURFACE_DESC surface_desc;
7262 D3DVOLUME_DESC volume_desc;
7263 D3DRESOURCETYPE type;
7264 IDirect3D8 *d3d;
7265 ULONG refcount;
7266 HWND window;
7267 HRESULT hr;
7268 D3DCAPS8 caps;
7270 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7271 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7272 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7273 ok(!!d3d, "Failed to create a D3D object.\n");
7274 if (!(device = create_device(d3d, window, NULL)))
7276 skip("Failed to create a D3D device, skipping tests.\n");
7277 IDirect3D8_Release(d3d);
7278 DestroyWindow(window);
7279 return;
7282 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7283 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7285 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_X8R8G8B8, &surface);
7286 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7287 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7288 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7289 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7290 surface_desc.Type);
7291 IDirect3DSurface8_Release(surface);
7293 hr = IDirect3DDevice8_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
7294 D3DPOOL_SYSTEMMEM, &texture);
7295 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7296 type = IDirect3DTexture8_GetType(texture);
7297 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
7299 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
7300 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7301 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7302 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7303 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7304 surface_desc.Type);
7305 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
7306 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
7307 hr = IDirect3DTexture8_GetLevelDesc(texture, 0, &surface_desc);
7308 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7309 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7310 surface_desc.Type);
7311 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
7312 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
7313 IDirect3DSurface8_Release(surface);
7315 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 2, &surface);
7316 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7317 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7318 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7319 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7320 surface_desc.Type);
7321 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
7322 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
7323 hr = IDirect3DTexture8_GetLevelDesc(texture, 2, &surface_desc);
7324 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7325 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7326 surface_desc.Type);
7327 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
7328 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
7329 IDirect3DSurface8_Release(surface);
7330 IDirect3DTexture8_Release(texture);
7332 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7334 hr = IDirect3DDevice8_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
7335 D3DPOOL_SYSTEMMEM, &cube_texture);
7336 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
7337 type = IDirect3DCubeTexture8_GetType(cube_texture);
7338 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
7340 hr = IDirect3DCubeTexture8_GetCubeMapSurface(cube_texture,
7341 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7342 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
7343 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7344 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7345 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7346 surface_desc.Type);
7347 hr = IDirect3DCubeTexture8_GetLevelDesc(cube_texture, 0, &surface_desc);
7348 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7349 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7350 surface_desc.Type);
7351 IDirect3DSurface8_Release(surface);
7352 IDirect3DCubeTexture8_Release(cube_texture);
7354 else
7355 skip("Cube maps not supported.\n");
7357 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
7359 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
7360 D3DPOOL_SYSTEMMEM, &volume_texture);
7361 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
7362 type = IDirect3DVolumeTexture8_GetType(volume_texture);
7363 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
7365 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 0, &volume);
7366 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
7367 /* IDirect3DVolume8 is not an IDirect3DResource8 and has no GetType method. */
7368 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
7369 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
7370 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7371 volume_desc.Type);
7372 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
7373 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
7374 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
7375 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 0, &volume_desc);
7376 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7377 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7378 volume_desc.Type);
7379 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
7380 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
7381 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
7382 IDirect3DVolume8_Release(volume);
7384 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 2, &volume);
7385 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
7386 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
7387 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
7388 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7389 volume_desc.Type);
7390 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
7391 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
7392 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
7393 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 2, &volume_desc);
7394 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7395 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7396 volume_desc.Type);
7397 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
7398 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
7399 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
7400 IDirect3DVolume8_Release(volume);
7401 IDirect3DVolumeTexture8_Release(volume_texture);
7403 else
7404 skip("Mipmapped volume maps not supported.\n");
7406 refcount = IDirect3DDevice8_Release(device);
7407 ok(!refcount, "Device has %u references left.\n", refcount);
7408 IDirect3D8_Release(d3d);
7409 DestroyWindow(window);
7412 static void test_mipmap_lock(void)
7414 IDirect3DDevice8 *device;
7415 IDirect3DSurface8 *surface, *surface2, *surface_dst, *surface_dst2;
7416 IDirect3DTexture8 *texture, *texture_dst;
7417 IDirect3D8 *d3d;
7418 ULONG refcount;
7419 HWND window;
7420 HRESULT hr;
7421 D3DLOCKED_RECT locked_rect;
7423 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7424 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7425 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7426 ok(!!d3d, "Failed to create a D3D object.\n");
7427 if (!(device = create_device(d3d, window, NULL)))
7429 skip("Failed to create a D3D device, skipping tests.\n");
7430 IDirect3D8_Release(d3d);
7431 DestroyWindow(window);
7432 return;
7435 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
7436 D3DPOOL_DEFAULT, &texture_dst);
7437 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7438 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 0, &surface_dst);
7439 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7440 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
7441 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7443 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
7444 D3DPOOL_SYSTEMMEM, &texture);
7445 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7446 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
7447 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7448 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
7449 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7451 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
7452 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7453 hr = IDirect3DSurface8_LockRect(surface2, &locked_rect, NULL, 0);
7454 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7455 hr = IDirect3DSurface8_UnlockRect(surface);
7456 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7458 hr = IDirect3DDevice8_CopyRects(device, surface, NULL, 0, surface_dst, NULL);
7459 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
7460 hr = IDirect3DDevice8_CopyRects(device, surface2, NULL, 0, surface_dst2, NULL);
7461 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7463 /* Apparently there's no validation on the container. */
7464 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)texture,
7465 (IDirect3DBaseTexture8 *)texture_dst);
7466 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
7468 hr = IDirect3DSurface8_UnlockRect(surface2);
7469 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7471 IDirect3DSurface8_Release(surface_dst2);
7472 IDirect3DSurface8_Release(surface_dst);
7473 IDirect3DSurface8_Release(surface2);
7474 IDirect3DSurface8_Release(surface);
7475 IDirect3DTexture8_Release(texture_dst);
7476 IDirect3DTexture8_Release(texture);
7478 refcount = IDirect3DDevice8_Release(device);
7479 ok(!refcount, "Device has %u references left.\n", refcount);
7480 IDirect3D8_Release(d3d);
7481 DestroyWindow(window);
7484 static void test_writeonly_resource(void)
7486 IDirect3D8 *d3d;
7487 IDirect3DDevice8 *device;
7488 IDirect3DVertexBuffer8 *buffer;
7489 ULONG refcount;
7490 HWND window;
7491 HRESULT hr;
7492 BYTE *ptr;
7493 static const struct
7495 struct vec3 pos;
7497 quad[] =
7499 {{-1.0f, -1.0f, 0.0f}},
7500 {{-1.0f, 1.0f, 0.0f}},
7501 {{ 1.0f, -1.0f, 0.0f}},
7502 {{ 1.0f, 1.0f, 0.0f}}
7505 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7506 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7507 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7508 ok(!!d3d, "Failed to create a D3D object.\n");
7509 if (!(device = create_device(d3d, window, NULL)))
7511 skip("Failed to create a D3D device, skipping tests.\n");
7512 IDirect3D8_Release(d3d);
7513 DestroyWindow(window);
7514 return;
7517 hr = IDirect3DDevice8_CreateVertexBuffer(device, sizeof(quad),
7518 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer);
7519 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
7521 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
7522 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7523 memcpy(ptr, quad, sizeof(quad));
7524 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7525 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7526 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*quad));
7527 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
7528 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
7529 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
7531 hr = IDirect3DDevice8_BeginScene(device);
7532 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
7533 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7534 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7535 hr = IDirect3DDevice8_EndScene(device);
7536 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
7538 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, 0);
7539 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7540 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7541 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7542 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7544 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
7545 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7546 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7547 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7548 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7550 refcount = IDirect3DVertexBuffer8_Release(buffer);
7551 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
7552 refcount = IDirect3DDevice8_Release(device);
7553 ok(!refcount, "Device has %u references left.\n", refcount);
7554 IDirect3D8_Release(d3d);
7555 DestroyWindow(window);
7558 static void test_lost_device(void)
7560 struct device_desc device_desc;
7561 IDirect3DDevice8 *device;
7562 IDirect3D8 *d3d;
7563 ULONG refcount;
7564 HWND window;
7565 HRESULT hr;
7566 BOOL ret;
7568 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7569 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7570 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7571 ok(!!d3d, "Failed to create a D3D object.\n");
7572 device_desc.device_window = window;
7573 device_desc.width = registry_mode.dmPelsWidth;
7574 device_desc.height = registry_mode.dmPelsHeight;
7575 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
7576 if (!(device = create_device(d3d, window, &device_desc)))
7578 skip("Failed to create a D3D device, skipping tests.\n");
7579 goto done;
7582 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7583 if (hr == D3DERR_DEVICELOST)
7585 win_skip("Broken TestCooperativeLevel(), skipping test.\n");
7586 IDirect3DDevice8_Release(device);
7587 goto done;
7589 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7590 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7591 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7593 ret = SetForegroundWindow(GetDesktopWindow());
7594 ok(ret, "Failed to set foreground window.\n");
7595 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7596 /* The device is not lost on Windows 10. */
7597 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7598 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7599 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7601 ret = ShowWindow(window, SW_RESTORE);
7602 ok(ret, "Failed to restore window.\n");
7603 ret = SetForegroundWindow(window);
7604 ok(ret, "Failed to set foreground window.\n");
7605 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7606 ok(hr == D3DERR_DEVICENOTRESET || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7607 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7608 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7610 hr = reset_device(device, &device_desc);
7611 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7612 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7613 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7614 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7615 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7617 device_desc.flags = 0;
7618 hr = reset_device(device, &device_desc);
7619 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7620 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7621 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7622 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7623 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7625 ret = SetForegroundWindow(GetDesktopWindow());
7626 ok(ret, "Failed to set foreground window.\n");
7627 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7628 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7629 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7630 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7632 ret = ShowWindow(window, SW_RESTORE);
7633 ok(ret, "Failed to restore window.\n");
7634 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7635 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7636 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7637 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7639 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
7640 hr = reset_device(device, &device_desc);
7641 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7642 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7643 /* The device is not lost on Windows 10. */
7644 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7645 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7646 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7648 ret = SetForegroundWindow(GetDesktopWindow());
7649 ok(ret, "Failed to set foreground window.\n");
7650 hr = reset_device(device, &device_desc);
7651 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7652 ret = ShowWindow(window, SW_RESTORE);
7653 ok(ret, "Failed to restore window.\n");
7654 ret = SetForegroundWindow(window);
7655 ok(ret, "Failed to set foreground window.\n");
7656 hr = reset_device(device, &device_desc);
7657 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7659 refcount = IDirect3DDevice8_Release(device);
7660 ok(!refcount, "Device has %u references left.\n", refcount);
7661 done:
7662 IDirect3D8_Release(d3d);
7663 DestroyWindow(window);
7666 static void test_resource_priority(void)
7668 IDirect3DDevice8 *device;
7669 IDirect3DTexture8 *texture;
7670 IDirect3DVertexBuffer8 *buffer;
7671 IDirect3D8 *d3d;
7672 ULONG refcount;
7673 HWND window;
7674 HRESULT hr;
7675 static const struct
7677 D3DPOOL pool;
7678 const char *name;
7679 BOOL can_set_priority;
7681 test_data[] =
7683 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
7684 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
7685 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
7686 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
7688 unsigned int i;
7689 DWORD priority;
7691 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7692 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7693 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7694 ok(!!d3d, "Failed to create a D3D object.\n");
7695 if (!(device = create_device(d3d, window, NULL)))
7697 skip("Failed to create a D3D device, skipping tests.\n");
7698 IDirect3D8_Release(d3d);
7699 DestroyWindow(window);
7700 return;
7703 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
7705 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
7706 test_data[i].pool, &texture);
7707 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
7709 priority = IDirect3DTexture8_GetPriority(texture);
7710 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7711 priority = IDirect3DTexture8_SetPriority(texture, 1);
7712 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7713 priority = IDirect3DTexture8_GetPriority(texture);
7714 if (test_data[i].can_set_priority)
7716 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7717 priority = IDirect3DTexture8_SetPriority(texture, 0);
7718 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7720 else
7721 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7723 IDirect3DTexture8_Release(texture);
7725 if (test_data[i].pool != D3DPOOL_SCRATCH)
7727 hr = IDirect3DDevice8_CreateVertexBuffer(device, 256, 0, 0,
7728 test_data[i].pool, &buffer);
7729 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
7731 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
7732 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7733 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 1);
7734 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7735 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
7736 if (test_data[i].can_set_priority)
7738 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7739 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 0);
7740 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7742 else
7743 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7745 IDirect3DVertexBuffer8_Release(buffer);
7749 refcount = IDirect3DDevice8_Release(device);
7750 ok(!refcount, "Device has %u references left.\n", refcount);
7751 IDirect3D8_Release(d3d);
7752 DestroyWindow(window);
7755 static void test_swapchain_parameters(void)
7757 IDirect3DDevice8 *device;
7758 IDirect3D8 *d3d;
7759 IDirect3DSurface8 *backbuffer;
7760 HWND window;
7761 HRESULT hr;
7762 unsigned int i, j;
7763 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0};
7764 static const struct
7766 BOOL windowed;
7767 UINT backbuffer_count;
7768 D3DSWAPEFFECT swap_effect;
7769 HRESULT hr;
7771 tests[] =
7773 /* Swap effect 0 is not allowed. */
7774 {TRUE, 1, 0, D3DERR_INVALIDCALL},
7775 {FALSE, 1, 0, D3DERR_INVALIDCALL},
7777 /* All (non-ex) swap effects are allowed in
7778 * windowed and fullscreen mode. */
7779 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
7780 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
7781 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
7782 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
7783 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
7785 /* Only one backbuffer in copy mode. Reset allows it for
7786 * some reason. */
7787 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
7788 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
7789 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
7790 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
7791 {TRUE, 0, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
7792 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
7793 {TRUE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
7794 {FALSE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
7796 /* Ok with the others, in fullscreen and windowed mode. */
7797 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
7798 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
7799 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
7800 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
7802 /* Invalid swapeffects. */
7803 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
7804 {FALSE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
7806 /* 3 is the highest allowed backbuffer count. */
7807 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
7808 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
7809 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
7810 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
7811 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
7814 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7815 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7816 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7817 ok(!!d3d, "Failed to create a D3D object.\n");
7818 if (!(device = create_device(d3d, window, NULL)))
7820 skip("Failed to create a D3D device, skipping tests.\n");
7821 IDirect3D8_Release(d3d);
7822 DestroyWindow(window);
7823 return;
7825 IDirect3DDevice8_Release(device);
7827 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
7828 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
7829 present_parameters_windowed.hDeviceWindow = window;
7830 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
7831 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
7832 present_parameters_windowed.Windowed = TRUE;
7833 present_parameters_windowed.BackBufferCount = 1;
7835 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
7837 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
7839 memset(&present_parameters, 0, sizeof(present_parameters));
7840 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
7841 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
7842 present_parameters.hDeviceWindow = window;
7843 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
7845 present_parameters.SwapEffect = tests[i].swap_effect;
7846 present_parameters.Windowed = tests[i].windowed;
7847 present_parameters.BackBufferCount = tests[i].backbuffer_count;
7849 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
7850 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
7851 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
7852 if (SUCCEEDED(hr))
7854 for (j = 0; j < bb_count; ++j)
7856 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7857 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#x, test %u.\n", j, hr, i);
7858 IDirect3DSurface8_Release(backbuffer);
7860 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7861 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %x, test %u.\n", hr, i);
7863 IDirect3DDevice8_Release(device);
7866 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
7867 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
7868 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
7870 memset(&present_parameters, 0, sizeof(present_parameters));
7871 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
7872 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
7873 present_parameters.hDeviceWindow = window;
7874 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
7876 present_parameters.SwapEffect = tests[i].swap_effect;
7877 present_parameters.Windowed = tests[i].windowed;
7878 present_parameters.BackBufferCount = tests[i].backbuffer_count;
7880 hr = IDirect3DDevice8_Reset(device, &present_parameters);
7881 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
7883 if (FAILED(hr))
7885 hr = IDirect3DDevice8_Reset(device, &present_parameters_windowed);
7886 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
7888 else
7890 for (j = 0; j < bb_count; ++j)
7892 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7893 todo_wine_if (j)
7894 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#x, test %u.\n", j, hr, i);
7895 if (SUCCEEDED(hr))
7896 IDirect3DSurface8_Release(backbuffer);
7898 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7899 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %x, test %u.\n", hr, i);
7901 IDirect3DDevice8_Release(device);
7904 IDirect3D8_Release(d3d);
7905 DestroyWindow(window);
7908 static void test_check_device_format(void)
7910 IDirect3D8 *d3d;
7911 HRESULT hr;
7913 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7914 ok(!!d3d, "Failed to create a D3D object.\n");
7916 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7917 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
7918 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7919 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7920 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
7921 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7922 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7923 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
7924 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7926 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7927 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
7928 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7929 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7930 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
7931 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7932 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7933 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
7934 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7936 IDirect3D8_Release(d3d);
7939 static void test_miptree_layout(void)
7941 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
7942 IDirect3DCubeTexture8 *texture_cube;
7943 IDirect3DTexture8 *texture_2d;
7944 IDirect3DDevice8 *device;
7945 D3DLOCKED_RECT map_desc;
7946 BYTE *base = NULL;
7947 IDirect3D8 *d3d;
7948 D3DCAPS8 caps;
7949 UINT refcount;
7950 HWND window;
7951 HRESULT hr;
7953 static const struct
7955 D3DFORMAT format;
7956 const char *name;
7958 formats[] =
7960 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
7961 {D3DFMT_A8, "D3DFMT_A8"},
7962 {D3DFMT_L8, "D3DFMT_L8"},
7963 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
7964 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
7966 static const struct
7968 D3DPOOL pool;
7969 const char *name;
7971 pools[] =
7973 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
7974 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
7975 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
7978 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7979 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7980 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7981 ok(!!d3d, "Failed to create a D3D object.\n");
7982 if (!(device = create_device(d3d, window, NULL)))
7984 skip("Failed to create a D3D device, skipping tests.\n");
7985 goto done;
7988 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7989 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7991 base_dimension = 257;
7992 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
7994 skip("Using power of two base dimension.\n");
7995 base_dimension = 256;
7998 for (format_idx = 0; format_idx < sizeof(formats) / sizeof(*formats); ++format_idx)
8000 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8001 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
8003 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
8004 continue;
8007 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
8009 hr = IDirect3DDevice8_CreateTexture(device, base_dimension, base_dimension, 0, 0,
8010 formats[format_idx].format, pools[pool_idx].pool, &texture_2d);
8011 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
8012 pools[pool_idx].name, formats[format_idx].name, hr);
8014 level_count = IDirect3DTexture8_GetLevelCount(texture_2d);
8015 for (i = 0, offset = 0; i < level_count; ++i)
8017 hr = IDirect3DTexture8_LockRect(texture_2d, i, &map_desc, NULL, 0);
8018 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
8019 pools[pool_idx].name, formats[format_idx].name, i, hr);
8021 if (!i)
8022 base = map_desc.pBits;
8023 else
8024 ok(map_desc.pBits == base + offset,
8025 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
8026 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
8027 offset += (base_dimension >> i) * map_desc.Pitch;
8029 hr = IDirect3DTexture8_UnlockRect(texture_2d, i);
8030 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
8031 pools[pool_idx].name, formats[format_idx].name, i, hr);
8034 IDirect3DTexture8_Release(texture_2d);
8037 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8038 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
8040 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
8041 continue;
8044 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
8046 hr = IDirect3DDevice8_CreateCubeTexture(device, base_dimension, 0, 0,
8047 formats[format_idx].format, pools[pool_idx].pool, &texture_cube);
8048 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
8049 pools[pool_idx].name, formats[format_idx].name, hr);
8051 level_count = IDirect3DCubeTexture8_GetLevelCount(texture_cube);
8052 for (i = 0, offset = 0; i < 6; ++i)
8054 for (j = 0; j < level_count; ++j)
8056 hr = IDirect3DCubeTexture8_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
8057 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
8058 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
8060 if (!i && !j)
8061 base = map_desc.pBits;
8062 else
8063 ok(map_desc.pBits == base + offset,
8064 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
8065 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
8066 offset += (base_dimension >> j) * map_desc.Pitch;
8068 hr = IDirect3DCubeTexture8_UnlockRect(texture_cube, i, j);
8069 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
8070 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
8072 offset = (offset + 15) & ~15;
8075 IDirect3DCubeTexture8_Release(texture_cube);
8079 refcount = IDirect3DDevice8_Release(device);
8080 ok(!refcount, "Device has %u references left.\n", refcount);
8081 done:
8082 IDirect3D8_Release(d3d);
8083 DestroyWindow(window);
8086 static void test_render_target_device_mismatch(void)
8088 IDirect3DDevice8 *device, *device2;
8089 IDirect3DSurface8 *surface, *rt;
8090 IDirect3D8 *d3d;
8091 UINT refcount;
8092 HWND window;
8093 HRESULT hr;
8095 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
8096 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8097 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8098 ok(!!d3d, "Failed to create a D3D object.\n");
8099 if (!(device = create_device(d3d, window, NULL)))
8101 skip("Failed to create a D3D device.\n");
8102 IDirect3D8_Release(d3d);
8103 DestroyWindow(window);
8104 return;
8107 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
8108 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8110 device2 = create_device(d3d, window, NULL);
8111 ok(!!device2, "Failed to create a D3D device.\n");
8113 hr = IDirect3DDevice8_CreateRenderTarget(device2, 640, 480,
8114 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &surface);
8115 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8117 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
8118 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8120 IDirect3DSurface8_Release(surface);
8122 hr = IDirect3DDevice8_GetRenderTarget(device2, &surface);
8123 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8125 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
8126 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8128 IDirect3DSurface8_Release(surface);
8130 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
8131 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8132 todo_wine ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
8133 IDirect3DSurface8_Release(surface);
8134 IDirect3DSurface8_Release(rt);
8136 refcount = IDirect3DDevice8_Release(device);
8137 ok(!refcount, "Device has %u references left.\n", refcount);
8138 refcount = IDirect3DDevice8_Release(device2);
8139 ok(!refcount, "Device has %u references left.\n", refcount);
8140 IDirect3D8_Release(d3d);
8141 DestroyWindow(window);
8144 START_TEST(device)
8146 HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
8147 WNDCLASSA wc = {0};
8148 IDirect3D8 *d3d8;
8149 DEVMODEW current_mode;
8151 if (!d3d8_handle)
8153 skip("Could not load d3d8.dll\n");
8154 return;
8157 memset(&current_mode, 0, sizeof(current_mode));
8158 current_mode.dmSize = sizeof(current_mode);
8159 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
8160 registry_mode.dmSize = sizeof(registry_mode);
8161 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
8162 if (current_mode.dmPelsWidth != registry_mode.dmPelsWidth
8163 || current_mode.dmPelsHeight != registry_mode.dmPelsHeight)
8165 skip("Current mode does not match registry mode, skipping test.\n");
8166 return;
8169 wc.lpfnWndProc = DefWindowProcA;
8170 wc.lpszClassName = "d3d8_test_wc";
8171 RegisterClassA(&wc);
8173 ValidateVertexShader = (void *)GetProcAddress(d3d8_handle, "ValidateVertexShader");
8174 ValidatePixelShader = (void *)GetProcAddress(d3d8_handle, "ValidatePixelShader");
8176 if (!(d3d8 = Direct3DCreate8(D3D_SDK_VERSION)))
8178 skip("could not create D3D8\n");
8179 return;
8181 IDirect3D8_Release(d3d8);
8183 test_fpu_setup();
8184 test_display_formats();
8185 test_display_modes();
8186 test_shader_versions();
8187 test_swapchain();
8188 test_refcount();
8189 test_mipmap_levels();
8190 test_checkdevicemultisampletype();
8191 test_invalid_multisample();
8192 test_cursor();
8193 test_cursor_pos();
8194 test_states();
8195 test_reset();
8196 test_scene();
8197 test_shader();
8198 test_limits();
8199 test_lights();
8200 test_ApplyStateBlock();
8201 test_render_zero_triangles();
8202 test_depth_stencil_reset();
8203 test_wndproc();
8204 test_wndproc_windowed();
8205 test_depth_stencil_size();
8206 test_window_style();
8207 test_unsupported_shaders();
8208 test_mode_change();
8209 test_device_window_reset();
8210 test_reset_resources();
8211 depth_blit_test();
8212 test_set_rt_vp_scissor();
8213 test_validate_vs();
8214 test_validate_ps();
8215 test_volume_get_container();
8216 test_vb_lock_flags();
8217 test_texture_stage_states();
8218 test_cube_textures();
8219 test_get_set_texture();
8220 test_image_surface_pool();
8221 test_surface_get_container();
8222 test_lockrect_invalid();
8223 test_private_data();
8224 test_surface_dimensions();
8225 test_surface_format_null();
8226 test_surface_double_unlock();
8227 test_surface_blocks();
8228 test_set_palette();
8229 test_swvp_buffer();
8230 test_managed_buffer();
8231 test_npot_textures();
8232 test_volume_locking();
8233 test_update_volumetexture();
8234 test_create_rt_ds_fail();
8235 test_volume_blocks();
8236 test_lockbox_invalid();
8237 test_pixel_format();
8238 test_begin_end_state_block();
8239 test_shader_constant_apply();
8240 test_resource_type();
8241 test_mipmap_lock();
8242 test_writeonly_resource();
8243 test_lost_device();
8244 test_resource_priority();
8245 test_swapchain_parameters();
8246 test_check_device_format();
8247 test_miptree_layout();
8248 test_render_target_device_mismatch();
8250 UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));