d3d8/tests: Add a test for resource creation with D3DFMT_UNKNOWN.
[wine.git] / dlls / d3d8 / tests / device.c
blobda67fb3fb4349f9d855f9a220c4f62aa011ac6f7
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_a->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 HRESULT hr, expected_hr;
4812 IDirect3D8 *d3d8;
4813 unsigned int i, r;
4814 ULONG refcount;
4815 HWND window;
4816 BYTE *base;
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;
4879 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4880 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
4881 base = locked_rect.pBits;
4882 hr = IDirect3DSurface8_UnlockRect(surface);
4883 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4884 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
4885 hr = IDirect3DSurface8_UnlockRect(surface);
4886 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
4888 for (i = 0; i < (sizeof(valid) / sizeof(*valid)); ++i)
4890 const RECT *rect = &valid[i];
4892 locked_rect.pBits = (BYTE *)0xdeadbeef;
4893 locked_rect.Pitch = 0xdeadbeef;
4895 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
4896 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
4897 wine_dbgstr_rect(rect), hr, resources[r].name);
4899 offset = (BYTE *)locked_rect.pBits - base;
4900 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
4901 ok(offset == expected_offset,
4902 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4903 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
4905 hr = IDirect3DSurface8_UnlockRect(surface);
4906 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s\n", hr, resources[r].name);
4908 if (texture)
4910 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, rect, 0);
4911 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
4912 wine_dbgstr_rect(rect), hr, resources[r].name);
4914 offset = (BYTE *)locked_rect.pBits - base;
4915 ok(offset == expected_offset,
4916 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4917 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
4919 hr = IDirect3DTexture8_UnlockRect(texture, 0);
4920 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4922 if (cube_texture)
4924 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0, &locked_rect, rect, 0);
4925 ok(SUCCEEDED(hr), "Failed to lock surface with rect %s, hr %#x, type %s.\n",
4926 wine_dbgstr_rect(rect), hr, resources[r].name);
4928 offset = (BYTE *)locked_rect.pBits - base;
4929 ok(offset == expected_offset,
4930 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4931 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
4933 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
4934 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4938 for (i = 0; i < (sizeof(invalid) / sizeof(*invalid)); ++i)
4940 const RECT *rect = &invalid[i];
4942 locked_rect.pBits = (void *)0xdeadbeef;
4943 locked_rect.Pitch = 1;
4944 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, rect, 0);
4945 if (resources[r].validate)
4946 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
4947 hr, wine_dbgstr_rect(rect), resources[r].name);
4948 else
4949 ok(SUCCEEDED(hr), "Got unexpected hr %#x for rect %s, type %s.\n",
4950 hr, wine_dbgstr_rect(rect), resources[r].name);
4952 if (SUCCEEDED(hr))
4954 offset = (BYTE *)locked_rect.pBits - base;
4955 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
4956 ok(offset == expected_offset,
4957 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
4958 offset, expected_offset,wine_dbgstr_rect(rect), resources[r].name);
4960 hr = IDirect3DSurface8_UnlockRect(surface);
4961 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4963 else
4965 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
4966 locked_rect.pBits, resources[r].name);
4967 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
4968 locked_rect.Pitch, resources[r].name);
4972 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4973 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n",
4974 hr, resources[r].name);
4975 locked_rect.pBits = (void *)0xdeadbeef;
4976 locked_rect.Pitch = 1;
4977 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
4978 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
4979 if (resources[r].clear)
4981 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
4982 locked_rect.pBits, resources[r].name);
4983 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
4984 locked_rect.Pitch, resources[r].name);
4986 else
4988 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
4989 locked_rect.pBits, resources[r].name);
4990 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
4991 locked_rect.Pitch, resources[r].name);
4993 hr = IDirect3DSurface8_UnlockRect(surface);
4994 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
4996 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
4997 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
4998 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
4999 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[0], 0);
5000 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5001 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5002 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &valid[1], 0);
5003 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5004 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5005 hr = IDirect3DSurface8_UnlockRect(surface);
5006 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
5008 IDirect3DSurface8_Release(surface);
5009 if (texture)
5011 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5012 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
5013 hr, resources[r].name);
5014 locked_rect.pBits = (void *)0xdeadbeef;
5015 locked_rect.Pitch = 1;
5016 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
5017 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5018 ok(locked_rect.pBits == (void *)0xdeadbeef, "Got unexpected pBits %p, type %s.\n",
5019 locked_rect.pBits, resources[r].name);
5020 ok(locked_rect.Pitch == 1, "Got unexpected Pitch %u, type %s.\n",
5021 locked_rect.Pitch, resources[r].name);
5022 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5023 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5024 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5025 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5026 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5027 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5029 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5030 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
5031 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5032 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[0], 0);
5033 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5034 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5035 hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, &valid[1], 0);
5036 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5037 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5038 hr = IDirect3DTexture8_UnlockRect(texture, 0);
5039 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5041 IDirect3DTexture8_Release(texture);
5044 if (cube_texture)
5046 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5047 &locked_rect, NULL, 0);
5048 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
5049 hr, resources[r].name);
5050 locked_rect.pBits = (void *)0xdeadbeef;
5051 locked_rect.Pitch = 1;
5052 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5053 &locked_rect, NULL, 0);
5054 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5055 ok(!locked_rect.pBits, "Got unexpected pBits %p, type %s.\n",
5056 locked_rect.pBits, resources[r].name);
5057 ok(!locked_rect.Pitch, "Got unexpected Pitch %u, type %s.\n",
5058 locked_rect.Pitch, resources[r].name);
5059 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5060 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5061 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5062 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5063 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5064 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
5066 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5067 &locked_rect, &valid[0], 0);
5068 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
5069 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5070 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5071 &locked_rect, &valid[0], 0);
5072 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5073 hr, wine_dbgstr_rect(&valid[0]), resources[r].name);
5074 hr = IDirect3DCubeTexture8_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
5075 &locked_rect, &valid[1], 0);
5076 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
5077 hr, wine_dbgstr_rect(&valid[1]), resources[r].name);
5078 hr = IDirect3DCubeTexture8_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
5079 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
5081 IDirect3DTexture8_Release(cube_texture);
5085 refcount = IDirect3DDevice8_Release(device);
5086 ok(!refcount, "Device has %u references left.\n", refcount);
5087 IDirect3D8_Release(d3d8);
5088 DestroyWindow(window);
5091 static void test_private_data(void)
5093 ULONG refcount, expected_refcount;
5094 IDirect3DTexture8 *texture;
5095 IDirect3DSurface8 *surface, *surface2;
5096 IDirect3DDevice8 *device;
5097 IDirect3D8 *d3d8;
5098 IUnknown *ptr;
5099 HWND window;
5100 HRESULT hr;
5101 DWORD size;
5102 DWORD data[4] = {1, 2, 3, 4};
5103 static const GUID d3d8_private_data_test_guid2 =
5105 0x2e5afac2,
5106 0x87b5,
5107 0x4c10,
5108 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
5111 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5112 0, 0, 640, 480, 0, 0, 0, 0);
5113 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5114 ok(!!d3d8, "Failed to create a D3D object.\n");
5115 if (!(device = create_device(d3d8, window, NULL)))
5117 skip("Failed to create a D3D device, skipping tests.\n");
5118 IDirect3D8_Release(d3d8);
5119 DestroyWindow(window);
5120 return;
5123 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_A8R8G8B8, &surface);
5124 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
5126 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5127 device, 0, D3DSPD_IUNKNOWN);
5128 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5129 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5130 device, 5, D3DSPD_IUNKNOWN);
5131 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5132 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5133 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
5134 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5136 /* A failing SetPrivateData call does not clear the old data with the same tag. */
5137 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
5138 sizeof(device), D3DSPD_IUNKNOWN);
5139 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5140 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, device,
5141 sizeof(device) * 2, D3DSPD_IUNKNOWN);
5142 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5143 size = sizeof(ptr);
5144 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5145 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
5146 IUnknown_Release(ptr);
5147 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5148 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5150 refcount = get_refcount((IUnknown *)device);
5151 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5152 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5153 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5154 expected_refcount = refcount + 1;
5155 refcount = get_refcount((IUnknown *)device);
5156 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5157 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5158 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5159 expected_refcount = refcount - 1;
5160 refcount = get_refcount((IUnknown *)device);
5161 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5163 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5164 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5165 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5166 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5167 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5168 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5169 refcount = get_refcount((IUnknown *)device);
5170 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5172 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid,
5173 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
5174 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5175 size = 2 * sizeof(ptr);
5176 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5177 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5178 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5179 expected_refcount = refcount + 2;
5180 refcount = get_refcount((IUnknown *)device);
5181 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5182 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
5183 IUnknown_Release(ptr);
5184 expected_refcount--;
5186 ptr = (IUnknown *)0xdeadbeef;
5187 size = 1;
5188 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
5189 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5190 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5191 size = 2 * sizeof(ptr);
5192 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, NULL, &size);
5193 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5194 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5195 refcount = get_refcount((IUnknown *)device);
5196 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5197 size = 1;
5198 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, &ptr, &size);
5199 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
5200 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
5201 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
5202 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, NULL, NULL);
5203 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5204 size = 0xdeadbabe;
5205 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid2, &ptr, &size);
5206 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5207 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
5208 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
5209 /* GetPrivateData with size = NULL causes an access violation on Windows if the
5210 * requested data exists. */
5212 /* Destroying the surface frees the held reference. */
5213 IDirect3DSurface8_Release(surface);
5214 expected_refcount = refcount - 2;
5215 refcount = get_refcount((IUnknown *)device);
5216 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
5218 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
5219 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5220 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5221 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
5222 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
5223 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
5225 hr = IDirect3DTexture8_SetPrivateData(texture, &d3d8_private_data_test_guid, data, sizeof(data), 0);
5226 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5228 memset(data, 0, sizeof(data));
5229 size = sizeof(data);
5230 hr = IDirect3DSurface8_GetPrivateData(surface, &d3d8_private_data_test_guid, data, &size);
5231 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5232 hr = IDirect3DTexture8_GetPrivateData(texture, &d3d8_private_data_test_guid, data, &size);
5233 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
5234 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
5235 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
5237 hr = IDirect3DTexture8_FreePrivateData(texture, &d3d8_private_data_test_guid);
5238 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5240 hr = IDirect3DSurface8_SetPrivateData(surface, &d3d8_private_data_test_guid, data, sizeof(data), 0);
5241 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
5242 hr = IDirect3DSurface8_GetPrivateData(surface2, &d3d8_private_data_test_guid, data, &size);
5243 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5244 hr = IDirect3DSurface8_FreePrivateData(surface, &d3d8_private_data_test_guid);
5245 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
5247 IDirect3DSurface8_Release(surface2);
5248 IDirect3DSurface8_Release(surface);
5249 IDirect3DTexture8_Release(texture);
5251 refcount = IDirect3DDevice8_Release(device);
5252 ok(!refcount, "Device has %u references left.\n", refcount);
5253 IDirect3D8_Release(d3d8);
5254 DestroyWindow(window);
5257 static void test_surface_dimensions(void)
5259 IDirect3DSurface8 *surface;
5260 IDirect3DDevice8 *device;
5261 IDirect3D8 *d3d8;
5262 ULONG refcount;
5263 HWND window;
5264 HRESULT hr;
5266 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5267 0, 0, 640, 480, 0, 0, 0, 0);
5268 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5269 ok(!!d3d8, "Failed to create a D3D object.\n");
5270 if (!(device = create_device(d3d8, window, NULL)))
5272 skip("Failed to create a D3D device, skipping tests.\n");
5273 IDirect3D8_Release(d3d8);
5274 DestroyWindow(window);
5275 return;
5278 hr = IDirect3DDevice8_CreateImageSurface(device, 0, 1, D3DFMT_A8R8G8B8, &surface);
5279 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5280 hr = IDirect3DDevice8_CreateImageSurface(device, 1, 0, D3DFMT_A8R8G8B8, &surface);
5281 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5283 refcount = IDirect3DDevice8_Release(device);
5284 ok(!refcount, "Device has %u references left.\n", refcount);
5285 IDirect3D8_Release(d3d8);
5286 DestroyWindow(window);
5289 static void test_surface_format_null(void)
5291 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
5292 IDirect3DTexture8 *texture;
5293 IDirect3DSurface8 *surface;
5294 IDirect3DSurface8 *rt, *ds;
5295 D3DLOCKED_RECT locked_rect;
5296 IDirect3DDevice8 *device;
5297 D3DSURFACE_DESC desc;
5298 IDirect3D8 *d3d;
5299 ULONG refcount;
5300 HWND window;
5301 HRESULT hr;
5303 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5304 ok(!!d3d, "Failed to create a D3D object.\n");
5306 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5307 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
5308 if (hr != D3D_OK)
5310 skip("No D3DFMT_NULL support, skipping test.\n");
5311 IDirect3D8_Release(d3d);
5312 return;
5315 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5316 0, 0, 640, 480, 0, 0, 0, 0);
5317 if (!(device = create_device(d3d, window, NULL)))
5319 skip("Failed to create a D3D device, skipping tests.\n");
5320 IDirect3D8_Release(d3d);
5321 DestroyWindow(window);
5322 return;
5325 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5326 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
5327 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
5329 hr = IDirect3D8_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5330 D3DFMT_NULL, D3DFMT_D24S8);
5331 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
5333 hr = IDirect3DDevice8_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
5334 D3DMULTISAMPLE_NONE, TRUE, &surface);
5335 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5337 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
5338 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
5340 hr = IDirect3DDevice8_GetDepthStencilSurface(device, &ds);
5341 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
5343 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
5344 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5346 hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
5347 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
5349 hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
5350 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5352 IDirect3DSurface8_Release(rt);
5353 IDirect3DSurface8_Release(ds);
5355 hr = IDirect3DSurface8_GetDesc(surface, &desc);
5356 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
5357 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
5358 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
5360 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
5361 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
5362 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
5363 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
5365 hr = IDirect3DSurface8_UnlockRect(surface);
5366 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5368 IDirect3DSurface8_Release(surface);
5370 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
5371 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture);
5372 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5373 IDirect3DTexture8_Release(texture);
5375 refcount = IDirect3DDevice8_Release(device);
5376 ok(!refcount, "Device has %u references left.\n", refcount);
5377 IDirect3D8_Release(d3d);
5378 DestroyWindow(window);
5381 static void test_surface_double_unlock(void)
5383 static const D3DPOOL pools[] =
5385 D3DPOOL_DEFAULT,
5386 D3DPOOL_SYSTEMMEM,
5388 IDirect3DSurface8 *surface;
5389 IDirect3DDevice8 *device;
5390 D3DLOCKED_RECT lr;
5391 IDirect3D8 *d3d;
5392 unsigned int i;
5393 ULONG refcount;
5394 HWND window;
5395 HRESULT hr;
5397 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5398 0, 0, 640, 480, 0, 0, 0, 0);
5399 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5400 ok(!!d3d, "Failed to create a D3D object.\n");
5401 if (!(device = create_device(d3d, window, NULL)))
5403 skip("Failed to create a D3D device, skipping tests.\n");
5404 IDirect3D8_Release(d3d);
5405 DestroyWindow(window);
5406 return;
5409 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
5411 switch (pools[i])
5413 case D3DPOOL_DEFAULT:
5414 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5415 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
5416 if (FAILED(hr))
5418 skip("D3DFMT_X8R8G8B8 render targets not supported, skipping double unlock DEFAULT pool test.\n");
5419 continue;
5422 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64, D3DFMT_X8R8G8B8,
5423 D3DMULTISAMPLE_NONE, TRUE, &surface);
5424 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5425 break;
5427 case D3DPOOL_SYSTEMMEM:
5428 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64, D3DFMT_X8R8G8B8, &surface);
5429 ok(SUCCEEDED(hr), "Failed to create image surface, hr %#x.\n", hr);
5430 break;
5432 default:
5433 break;
5436 hr = IDirect3DSurface8_UnlockRect(surface);
5437 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5438 hr = IDirect3DSurface8_LockRect(surface, &lr, NULL, 0);
5439 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
5440 hr = IDirect3DSurface8_UnlockRect(surface);
5441 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
5442 hr = IDirect3DSurface8_UnlockRect(surface);
5443 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
5445 IDirect3DSurface8_Release(surface);
5448 refcount = IDirect3DDevice8_Release(device);
5449 ok(!refcount, "Device has %u references left.\n", refcount);
5450 IDirect3D8_Release(d3d);
5451 DestroyWindow(window);
5454 static void test_surface_blocks(void)
5456 static const struct
5458 D3DFORMAT fmt;
5459 const char *name;
5460 unsigned int block_width;
5461 unsigned int block_height;
5462 BOOL broken;
5463 BOOL create_size_checked, core_fmt;
5465 formats[] =
5467 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
5468 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
5469 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
5470 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
5471 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
5472 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
5473 * which doesn't match the format spec. On newer Nvidia cards
5474 * they have the correct 4x4 block size */
5475 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
5476 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
5477 /* Windows drivers generally enforce block-aligned locks for
5478 * YUY2 and UYVY. The notable exception is the AMD r500 driver
5479 * in d3d8. The same driver checks the sizes in d3d9. */
5480 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, TRUE, FALSE, TRUE },
5481 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, TRUE, FALSE, TRUE },
5483 static const struct
5485 D3DPOOL pool;
5486 const char *name;
5487 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
5488 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
5489 BOOL success;
5491 pools[] =
5493 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
5494 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
5495 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
5496 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
5498 static struct
5500 D3DRESOURCETYPE rtype;
5501 const char *type_name;
5502 D3DPOOL pool;
5503 const char *pool_name;
5504 BOOL need_driver_support, need_runtime_support;
5506 create_tests[] =
5508 /* D3d8 only supports sysmem surfaces, which are created via CreateImageSurface. Other tests confirm
5509 * that they are D3DPOOL_SYSTEMMEM surfaces, but their creation restriction behaves like the scratch
5510 * pool in d3d9. */
5511 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE, TRUE },
5513 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
5514 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
5515 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
5516 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5518 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE },
5519 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE },
5520 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE },
5521 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
5523 IDirect3DTexture8 *texture;
5524 IDirect3DCubeTexture8 *cube_texture;
5525 IDirect3DSurface8 *surface;
5526 D3DLOCKED_RECT locked_rect;
5527 IDirect3DDevice8 *device;
5528 unsigned int i, j, k, w, h;
5529 IDirect3D8 *d3d;
5530 ULONG refcount;
5531 HWND window;
5532 HRESULT hr;
5533 RECT rect;
5534 BOOL tex_pow2, cube_pow2;
5535 D3DCAPS8 caps;
5536 static const RECT invalid[] =
5538 {60, 60, 60, 68}, /* 0 height */
5539 {60, 60, 68, 60}, /* 0 width */
5540 {68, 60, 60, 68}, /* left > right */
5541 {60, 68, 68, 60}, /* top > bottom */
5542 {-8, 60, 0, 68}, /* left < surface */
5543 {60, -8, 68, 0}, /* top < surface */
5544 {-16, 60, -8, 68}, /* right < surface */
5545 {60, -16, 68, -8}, /* bottom < surface */
5546 {60, 60, 136, 68}, /* right > surface */
5547 {60, 60, 68, 136}, /* bottom > surface */
5548 {136, 60, 144, 68}, /* left > surface */
5549 {60, 136, 68, 144}, /* top > surface */
5552 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5553 0, 0, 640, 480, 0, 0, 0, 0);
5554 d3d = Direct3DCreate8(D3D_SDK_VERSION);
5555 ok(!!d3d, "Failed to create a D3D object.\n");
5556 if (!(device = create_device(d3d, window, NULL)))
5558 skip("Failed to create a D3D device, skipping tests.\n");
5559 IDirect3D8_Release(d3d);
5560 DestroyWindow(window);
5561 return;
5564 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5565 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
5566 tex_pow2 = caps.TextureCaps & D3DPTEXTURECAPS_POW2;
5567 if (tex_pow2)
5568 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
5569 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
5571 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
5573 BOOL tex_support, cube_support, surface_support, format_known;
5575 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5576 0, D3DRTYPE_TEXTURE, formats[i].fmt);
5577 tex_support = SUCCEEDED(hr);
5578 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5579 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
5580 cube_support = SUCCEEDED(hr);
5581 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5582 0, D3DRTYPE_SURFACE, formats[i].fmt);
5583 surface_support = SUCCEEDED(hr);
5585 /* Scratch pool in general allows texture creation even if the driver does
5586 * not support the format. If the format is an extension format that is not
5587 * known to the runtime, like ATI2N, some driver support is required for
5588 * this to work.
5590 * It is also possible that Windows Vista and Windows 7 d3d8 runtimes know
5591 * about ATI2N. I cannot check this because all my Vista+ machines support
5592 * ATI2N in hardware, but none of my WinXP machines do. */
5593 format_known = tex_support || cube_support || surface_support;
5595 for (w = 1; w <= 8; w++)
5597 for (h = 1; h <= 8; h++)
5599 BOOL block_aligned = TRUE;
5600 BOOL size_is_pow2;
5602 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
5603 block_aligned = FALSE;
5605 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
5607 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
5609 BOOL support, pow2;
5610 HRESULT expect_hr;
5611 BOOL may_succeed = FALSE;
5612 IUnknown **check_null;
5614 if (!formats[i].core_fmt)
5616 /* AMD warns against creating ATI2N textures smaller than
5617 * the block size because the runtime cannot calculate the
5618 * correct texture size. Generalize this for all extension
5619 * formats. */
5620 if (w < formats[i].block_width || h < formats[i].block_height)
5621 continue;
5624 texture = (IDirect3DTexture8 *)0xdeadbeef;
5625 cube_texture = (IDirect3DCubeTexture8 *)0xdeadbeef;
5626 surface = (IDirect3DSurface8 *)0xdeadbeef;
5628 switch (create_tests[j].rtype)
5630 case D3DRTYPE_TEXTURE:
5631 check_null = (IUnknown **)&texture;
5632 hr = IDirect3DDevice8_CreateTexture(device, w, h, 1, 0,
5633 formats[i].fmt, create_tests[j].pool, &texture);
5634 support = tex_support;
5635 pow2 = tex_pow2;
5636 break;
5638 case D3DRTYPE_CUBETEXTURE:
5639 if (w != h)
5640 continue;
5641 check_null = (IUnknown **)&cube_texture;
5642 hr = IDirect3DDevice8_CreateCubeTexture(device, w, 1, 0,
5643 formats[i].fmt, create_tests[j].pool, &cube_texture);
5644 support = cube_support;
5645 pow2 = cube_pow2;
5646 break;
5648 case D3DRTYPE_SURFACE:
5649 check_null = (IUnknown **)&surface;
5650 hr = IDirect3DDevice8_CreateImageSurface(device, w, h,
5651 formats[i].fmt, &surface);
5652 support = surface_support;
5653 pow2 = FALSE;
5654 break;
5656 default:
5657 pow2 = FALSE;
5658 support = FALSE;
5659 check_null = NULL;
5660 break;
5663 if (create_tests[j].need_driver_support && !support)
5664 expect_hr = D3DERR_INVALIDCALL;
5665 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
5666 expect_hr = D3DERR_INVALIDCALL;
5667 else if (formats[i].create_size_checked && !block_aligned)
5668 expect_hr = D3DERR_INVALIDCALL;
5669 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
5670 expect_hr = D3DERR_INVALIDCALL;
5671 else
5672 expect_hr = D3D_OK;
5674 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
5675 may_succeed = TRUE;
5677 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
5678 * does not support it. Accept scratch creation of extension formats on
5679 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
5680 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
5681 * support it. */
5682 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
5683 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
5684 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
5686 if (FAILED(hr))
5687 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
5688 else
5689 IUnknown_Release(*check_null);
5694 hr = IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5695 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
5696 if (FAILED(hr))
5698 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
5699 continue;
5702 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5704 hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1,
5705 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
5706 formats[i].fmt, pools[j].pool, &texture);
5707 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
5708 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
5709 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
5710 IDirect3DTexture8_Release(texture);
5712 if (formats[i].block_width > 1)
5714 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
5715 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5716 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5717 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5718 SUCCEEDED(hr) ? "succeeded" : "failed",
5719 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5720 if (SUCCEEDED(hr))
5722 hr = IDirect3DSurface8_UnlockRect(surface);
5723 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5726 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
5727 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5728 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5729 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5730 SUCCEEDED(hr) ? "succeeded" : "failed",
5731 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5732 if (SUCCEEDED(hr))
5734 hr = IDirect3DSurface8_UnlockRect(surface);
5735 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5739 if (formats[i].block_height > 1)
5741 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
5742 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5743 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5744 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5745 SUCCEEDED(hr) ? "succeeded" : "failed",
5746 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5747 if (SUCCEEDED(hr))
5749 hr = IDirect3DSurface8_UnlockRect(surface);
5750 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5753 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
5754 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5755 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
5756 "Partial block lock %s, expected %s, format %s, pool %s.\n",
5757 SUCCEEDED(hr) ? "succeeded" : "failed",
5758 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
5759 if (SUCCEEDED(hr))
5761 hr = IDirect3DSurface8_UnlockRect(surface);
5762 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5766 for (k = 0; k < sizeof(invalid) / sizeof(*invalid); ++k)
5768 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &invalid[k], 0);
5769 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
5770 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
5771 formats[i].name, pools[j].name, k);
5772 if (SUCCEEDED(hr))
5774 hr = IDirect3DSurface8_UnlockRect(surface);
5775 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5779 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
5780 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, &rect, 0);
5781 ok(hr == D3D_OK, "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
5782 hr = IDirect3DSurface8_UnlockRect(surface);
5783 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
5785 IDirect3DSurface8_Release(surface);
5788 if (formats[i].block_width == 1 && formats[i].block_height == 1)
5789 continue;
5790 if (!formats[i].core_fmt)
5791 continue;
5793 hr = IDirect3DDevice8_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
5794 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture);
5795 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
5797 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, NULL, 0);
5798 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5799 hr = IDirect3DTexture8_UnlockRect(texture, 1);
5800 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5802 rect.left = 0;
5803 rect.top = 0;
5804 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
5805 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
5806 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
5807 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5808 hr = IDirect3DTexture8_UnlockRect(texture, 1);
5809 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
5811 rect.right = formats[i].block_width;
5812 rect.bottom = formats[i].block_height;
5813 hr = IDirect3DTexture8_LockRect(texture, 1, &locked_rect, &rect, 0);
5814 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5815 if (SUCCEEDED(hr))
5816 IDirect3DTexture8_UnlockRect(texture, 1);
5818 IDirect3DTexture8_Release(texture);
5821 refcount = IDirect3DDevice8_Release(device);
5822 ok(!refcount, "Device has %u references left.\n", refcount);
5823 IDirect3D8_Release(d3d);
5824 DestroyWindow(window);
5827 static void test_set_palette(void)
5829 IDirect3DDevice8 *device;
5830 IDirect3D8 *d3d8;
5831 UINT refcount;
5832 HWND window;
5833 HRESULT hr;
5834 PALETTEENTRY pal[256];
5835 unsigned int i;
5836 D3DCAPS8 caps;
5838 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5839 0, 0, 640, 480, 0, 0, 0, 0);
5840 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5841 ok(!!d3d8, "Failed to create a D3D object.\n");
5842 if (!(device = create_device(d3d8, window, NULL)))
5844 skip("Failed to create a D3D device, skipping tests.\n");
5845 IDirect3D8_Release(d3d8);
5846 DestroyWindow(window);
5847 return;
5850 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
5852 pal[i].peRed = i;
5853 pal[i].peGreen = i;
5854 pal[i].peBlue = i;
5855 pal[i].peFlags = 0xff;
5857 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5858 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
5860 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
5861 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5862 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
5864 pal[i].peRed = i;
5865 pal[i].peGreen = i;
5866 pal[i].peBlue = i;
5867 pal[i].peFlags = i;
5869 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
5871 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5872 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
5874 else
5876 hr = IDirect3DDevice8_SetPaletteEntries(device, 0, pal);
5877 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
5880 refcount = IDirect3DDevice8_Release(device);
5881 ok(!refcount, "Device has %u references left.\n", refcount);
5882 IDirect3D8_Release(d3d8);
5883 DestroyWindow(window);
5886 static void test_swvp_buffer(void)
5888 IDirect3DDevice8 *device;
5889 IDirect3D8 *d3d8;
5890 UINT refcount;
5891 HWND window;
5892 HRESULT hr;
5893 unsigned int i;
5894 IDirect3DVertexBuffer8 *buffer;
5895 static const unsigned int bufsize = 1024;
5896 D3DVERTEXBUFFER_DESC desc;
5897 struct device_desc device_desc;
5898 struct
5900 float x, y, z;
5901 } *ptr, *ptr2;
5903 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
5904 0, 0, 640, 480, 0, 0, 0, 0);
5905 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5906 ok(!!d3d8, "Failed to create a D3D object.\n");
5908 device_desc.device_window = window;
5909 device_desc.width = 640;
5910 device_desc.height = 480;
5911 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
5912 if (!(device = create_device(d3d8, window, &device_desc)))
5914 skip("Failed to create a D3D device, skipping tests.\n");
5915 IDirect3D8_Release(d3d8);
5916 DestroyWindow(window);
5917 return;
5920 hr = IDirect3DDevice8_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
5921 D3DPOOL_DEFAULT, &buffer);
5922 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
5923 hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
5924 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
5925 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
5926 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
5927 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
5929 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
5930 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
5931 for (i = 0; i < bufsize; i++)
5933 ptr[i].x = i * 1.0f;
5934 ptr[i].y = i * 2.0f;
5935 ptr[i].z = i * 3.0f;
5937 hr = IDirect3DVertexBuffer8_Unlock(buffer);
5938 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
5940 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
5941 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
5942 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
5943 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
5944 hr = IDirect3DDevice8_BeginScene(device);
5945 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5946 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
5947 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5948 hr = IDirect3DDevice8_EndScene(device);
5949 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5951 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, bufsize * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
5952 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
5953 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
5954 for (i = 0; i < bufsize; i++)
5956 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
5958 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
5959 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
5960 break;
5963 hr = IDirect3DVertexBuffer8_Unlock(buffer);
5964 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
5966 IDirect3DVertexBuffer8_Release(buffer);
5967 refcount = IDirect3DDevice8_Release(device);
5968 ok(!refcount, "Device has %u references left.\n", refcount);
5969 IDirect3D8_Release(d3d8);
5970 DestroyWindow(window);
5973 static void test_managed_buffer(void)
5975 static const unsigned int vertex_count = 1024;
5976 IDirect3DVertexBuffer8 *buffer;
5977 D3DVERTEXBUFFER_DESC desc;
5978 IDirect3DDevice8 *device;
5979 struct vec3 *ptr, *ptr2;
5980 IDirect3D8 *d3d8;
5981 unsigned int i;
5982 UINT refcount;
5983 HWND window;
5984 HRESULT hr;
5986 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
5987 0, 0, 640, 480, 0, 0, 0, 0);
5988 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
5989 ok(!!d3d8, "Failed to create a D3D object.\n");
5990 if (!(device = create_device(d3d8, window, NULL)))
5992 skip("Failed to create a D3D device, skipping tests.\n");
5993 IDirect3D8_Release(d3d8);
5994 DestroyWindow(window);
5995 return;
5998 hr = IDirect3DDevice8_CreateVertexBuffer(device, vertex_count * sizeof(*ptr), 0, 0, D3DPOOL_MANAGED, &buffer);
5999 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
6000 hr = IDirect3DVertexBuffer8_GetDesc(buffer, &desc);
6001 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
6002 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
6003 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
6005 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr), (BYTE **)&ptr, D3DLOCK_DISCARD);
6006 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6007 for (i = 0; i < vertex_count; ++i)
6009 ptr[i].x = i * 1.0f;
6010 ptr[i].y = i * 2.0f;
6011 ptr[i].z = i * 3.0f;
6013 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6014 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6016 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
6017 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6018 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*ptr));
6019 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
6020 hr = IDirect3DDevice8_BeginScene(device);
6021 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6022 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
6023 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6024 hr = IDirect3DDevice8_EndScene(device);
6025 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6027 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (BYTE **)&ptr2, D3DLOCK_DISCARD);
6028 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
6029 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
6030 for (i = 0; i < vertex_count; ++i)
6032 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
6034 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
6035 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
6036 break;
6039 hr = IDirect3DVertexBuffer8_Unlock(buffer);
6040 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
6042 IDirect3DVertexBuffer8_Release(buffer);
6043 refcount = IDirect3DDevice8_Release(device);
6044 ok(!refcount, "Device has %u references left.\n", refcount);
6045 IDirect3D8_Release(d3d8);
6046 DestroyWindow(window);
6049 static void test_npot_textures(void)
6051 IDirect3DDevice8 *device = NULL;
6052 IDirect3D8 *d3d8;
6053 ULONG refcount;
6054 HWND window = NULL;
6055 HRESULT hr;
6056 D3DCAPS8 caps;
6057 IDirect3DTexture8 *texture;
6058 IDirect3DCubeTexture8 *cube_texture;
6059 IDirect3DVolumeTexture8 *volume_texture;
6060 struct
6062 D3DPOOL pool;
6063 const char *pool_name;
6064 HRESULT hr;
6066 pools[] =
6068 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
6069 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
6070 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
6071 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
6073 unsigned int i, levels;
6074 BOOL tex_pow2, cube_pow2, vol_pow2;
6076 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6077 0, 0, 640, 480, 0, 0, 0, 0);
6078 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6079 ok(!!d3d8, "Failed to create a D3D object.\n");
6080 if (!(device = create_device(d3d8, window, NULL)))
6082 skip("Failed to create a D3D device, skipping tests.\n");
6083 goto done;
6086 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6087 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6088 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
6089 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
6090 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6091 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
6092 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
6094 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
6096 for (levels = 0; levels <= 2; levels++)
6098 HRESULT expected;
6100 hr = IDirect3DDevice8_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
6101 pools[i].pool, &texture);
6102 if (!tex_pow2)
6104 expected = D3D_OK;
6106 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
6108 if (levels == 1)
6109 expected = D3D_OK;
6110 else
6111 expected = pools[i].hr;
6113 else
6115 expected = pools[i].hr;
6117 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
6118 pools[i].pool_name, levels, hr, expected);
6120 if (SUCCEEDED(hr))
6121 IDirect3DTexture8_Release(texture);
6124 hr = IDirect3DDevice8_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8,
6125 pools[i].pool, &cube_texture);
6126 if (tex_pow2)
6128 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6129 pools[i].pool_name, hr, pools[i].hr);
6131 else
6133 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
6134 pools[i].pool_name, hr, D3D_OK);
6137 if (SUCCEEDED(hr))
6138 IDirect3DCubeTexture8_Release(cube_texture);
6140 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8,
6141 pools[i].pool, &volume_texture);
6142 if (tex_pow2)
6144 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6145 pools[i].pool_name, hr, pools[i].hr);
6147 else
6149 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
6150 pools[i].pool_name, hr, D3D_OK);
6153 if (SUCCEEDED(hr))
6154 IDirect3DVolumeTexture8_Release(volume_texture);
6157 done:
6158 if (device)
6160 refcount = IDirect3DDevice8_Release(device);
6161 ok(!refcount, "Device has %u references left.\n", refcount);
6163 IDirect3D8_Release(d3d8);
6164 DestroyWindow(window);
6168 static void test_volume_locking(void)
6170 IDirect3DDevice8 *device;
6171 IDirect3D8 *d3d8;
6172 HWND window;
6173 HRESULT hr;
6174 IDirect3DVolumeTexture8 *texture;
6175 unsigned int i;
6176 D3DLOCKED_BOX locked_box;
6177 ULONG refcount;
6178 D3DCAPS8 caps;
6179 static const struct
6181 D3DPOOL pool;
6182 DWORD usage;
6183 HRESULT create_hr, lock_hr;
6185 tests[] =
6187 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
6188 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6189 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
6190 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
6191 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
6192 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6193 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
6194 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
6197 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6198 0, 0, 640, 480, 0, 0, 0, 0);
6199 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6200 ok(!!d3d8, "Failed to create a D3D object.\n");
6201 if (!(device = create_device(d3d8, window, NULL)))
6203 skip("Failed to create a D3D device, skipping tests.\n");
6204 IDirect3D8_Release(d3d8);
6205 DestroyWindow(window);
6206 return;
6209 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6210 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6211 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6213 skip("Volume textures not supported, skipping test.\n");
6214 goto out;
6217 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6219 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
6220 D3DFMT_A8R8G8B8, tests[i].pool, &texture);
6221 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
6222 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
6223 if (FAILED(hr))
6224 continue;
6226 locked_box.pBits = (void *)0xdeadbeef;
6227 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6228 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
6229 if (SUCCEEDED(hr))
6231 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6232 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6234 else
6236 ok (locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
6238 IDirect3DVolumeTexture8_Release(texture);
6241 out:
6242 refcount = IDirect3DDevice8_Release(device);
6243 ok(!refcount, "Device has %u references left.\n", refcount);
6244 IDirect3D8_Release(d3d8);
6245 DestroyWindow(window);
6248 static void test_update_volumetexture(void)
6250 IDirect3DDevice8 *device;
6251 IDirect3D8 *d3d8;
6252 HWND window;
6253 HRESULT hr;
6254 IDirect3DVolumeTexture8 *src, *dst;
6255 unsigned int i;
6256 D3DLOCKED_BOX locked_box;
6257 ULONG refcount;
6258 D3DCAPS8 caps;
6259 static const struct
6261 D3DPOOL src_pool, dst_pool;
6262 HRESULT hr;
6264 tests[] =
6266 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6267 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6268 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
6269 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
6271 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6272 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6273 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6274 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
6276 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6277 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6278 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6279 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
6281 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6282 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6283 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6284 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
6286 static const struct
6288 UINT src_size, dst_size;
6289 UINT src_lvl, dst_lvl;
6290 D3DFORMAT src_fmt, dst_fmt;
6292 tests2[] =
6294 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6295 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6296 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6297 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6298 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
6299 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
6300 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
6301 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
6304 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6305 0, 0, 640, 480, 0, 0, 0, 0);
6306 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6307 ok(!!d3d8, "Failed to create a D3D object.\n");
6308 if (!(device = create_device(d3d8, window, NULL)))
6310 skip("Failed to create a D3D device, skipping tests.\n");
6311 IDirect3D8_Release(d3d8);
6312 DestroyWindow(window);
6313 return;
6316 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6317 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6318 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
6320 skip("Volume textures not supported, skipping test.\n");
6321 goto out;
6324 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
6326 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6327 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
6329 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
6330 D3DFMT_A8R8G8B8, tests[i].src_pool, &src);
6331 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6332 hr = IDirect3DDevice8_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
6333 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst);
6334 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6336 hr = IDirect3DVolumeTexture8_LockBox(src, 0, &locked_box, NULL, 0);
6337 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6338 *((DWORD *)locked_box.pBits) = 0x11223344;
6339 hr = IDirect3DVolumeTexture8_UnlockBox(src, 0);
6340 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6342 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src, (IDirect3DBaseTexture8 *)dst);
6343 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
6344 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
6346 if (SUCCEEDED(hr))
6348 DWORD content = *((DWORD *)locked_box.pBits);
6349 hr = IDirect3DVolumeTexture8_LockBox(dst, 0, &locked_box, NULL, 0);
6350 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6351 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
6352 hr = IDirect3DVolumeTexture8_UnlockBox(dst, 0);
6353 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6355 IDirect3DVolumeTexture8_Release(src);
6356 IDirect3DVolumeTexture8_Release(dst);
6359 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
6361 skip("Mipmapped volume maps not supported.\n");
6362 goto out;
6365 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
6367 hr = IDirect3DDevice8_CreateVolumeTexture(device,
6368 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
6369 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src);
6370 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6371 hr = IDirect3DDevice8_CreateVolumeTexture(device,
6372 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
6373 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst);
6374 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
6376 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)src, (IDirect3DBaseTexture8 *)dst);
6377 todo_wine_if (FAILED(hr))
6378 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
6380 IDirect3DVolumeTexture8_Release(src);
6381 IDirect3DVolumeTexture8_Release(dst);
6384 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
6385 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
6386 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
6387 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
6388 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
6390 * I'm not adding tests for this behavior until an application needs it. */
6392 out:
6393 refcount = IDirect3DDevice8_Release(device);
6394 ok(!refcount, "Device has %u references left.\n", refcount);
6395 IDirect3D8_Release(d3d8);
6396 DestroyWindow(window);
6399 static void test_create_rt_ds_fail(void)
6401 IDirect3DDevice8 *device;
6402 HWND window;
6403 HRESULT hr;
6404 ULONG refcount;
6405 IDirect3D8 *d3d8;
6406 IDirect3DSurface8 *surface;
6408 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6409 0, 0, 640, 480, 0, 0, 0, 0);
6410 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6411 ok(!!d3d8, "Failed to create a D3D object.\n");
6412 if (!(device = create_device(d3d8, window, NULL)))
6414 skip("Failed to create a D3D device, skipping tests.\n");
6415 IDirect3D8_Release(d3d8);
6416 DestroyWindow(window);
6417 return;
6420 /* Output pointer == NULL segfaults on Windows. */
6422 surface = (IDirect3DSurface8 *)0xdeadbeef;
6423 hr = IDirect3DDevice8_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
6424 D3DMULTISAMPLE_NONE, FALSE, &surface);
6425 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target 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 surface = (IDirect3DSurface8 *)0xdeadbeef;
6431 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
6432 D3DMULTISAMPLE_NONE, &surface);
6433 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
6434 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
6435 if (SUCCEEDED(hr))
6436 IDirect3DSurface8_Release(surface);
6438 refcount = IDirect3DDevice8_Release(device);
6439 ok(!refcount, "Device has %u references left.\n", refcount);
6440 IDirect3D8_Release(d3d8);
6441 DestroyWindow(window);
6444 static void test_volume_blocks(void)
6446 IDirect3DDevice8 *device;
6447 IDirect3D8 *d3d8;
6448 UINT refcount;
6449 HWND window;
6450 HRESULT hr;
6451 D3DCAPS8 caps;
6452 IDirect3DVolumeTexture8 *texture;
6453 unsigned int w, h, d, i, j;
6454 static const struct
6456 D3DFORMAT fmt;
6457 const char *name;
6458 unsigned int block_width;
6459 unsigned int block_height;
6460 unsigned int block_depth;
6461 unsigned int block_size;
6462 unsigned int broken;
6463 BOOL create_size_checked, core_fmt;
6465 formats[] =
6467 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
6468 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
6469 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
6470 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
6471 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
6472 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
6473 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
6474 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
6475 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
6476 * which doesn't match the format spec. On newer Nvidia cards
6477 * it has the correct 4x4 block size.
6478 * ATI1N volume textures are only supported by AMD GPUs right
6479 * now and locking offsets seem just wrong. */
6480 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
6481 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
6482 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
6483 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
6485 static const struct
6487 D3DPOOL pool;
6488 const char *name;
6489 BOOL need_driver_support, need_runtime_support;
6491 create_tests[] =
6493 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
6494 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
6495 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
6496 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
6498 static const struct
6500 unsigned int x, y, z, x2, y2, z2;
6502 offset_tests[] =
6504 {0, 0, 0, 8, 8, 8},
6505 {0, 0, 3, 8, 8, 8},
6506 {0, 4, 0, 8, 8, 8},
6507 {0, 4, 3, 8, 8, 8},
6508 {4, 0, 0, 8, 8, 8},
6509 {4, 0, 3, 8, 8, 8},
6510 {4, 4, 0, 8, 8, 8},
6511 {4, 4, 3, 8, 8, 8},
6513 D3DBOX box;
6514 D3DLOCKED_BOX locked_box;
6515 BYTE *base;
6516 INT expected_row_pitch, expected_slice_pitch;
6517 BOOL support;
6518 BOOL pow2;
6519 unsigned int offset, expected_offset;
6521 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
6522 0, 0, 640, 480, 0, 0, 0, 0);
6523 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6524 ok(!!d3d8, "Failed to create a D3D object.\n");
6525 if (!(device = create_device(d3d8, window, NULL)))
6527 skip("Failed to create a D3D device, skipping tests.\n");
6528 IDirect3D8_Release(d3d8);
6529 DestroyWindow(window);
6530 return;
6532 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
6533 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
6534 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
6536 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
6538 hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6539 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
6540 support = SUCCEEDED(hr);
6542 /* Test creation restrictions */
6543 for (w = 1; w <= 8; w++)
6545 for (h = 1; h <= 8; h++)
6547 for (d = 1; d <= 8; d++)
6549 HRESULT expect_hr;
6550 BOOL size_is_pow2;
6551 BOOL block_aligned = TRUE;
6553 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
6554 block_aligned = FALSE;
6556 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
6558 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
6560 BOOL may_succeed = FALSE;
6562 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
6563 expect_hr = D3DERR_INVALIDCALL;
6564 else if (formats[i].create_size_checked && !block_aligned)
6565 expect_hr = D3DERR_INVALIDCALL;
6566 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
6567 expect_hr = D3DERR_INVALIDCALL;
6568 else if (create_tests[j].need_driver_support && !support)
6569 expect_hr = D3DERR_INVALIDCALL;
6570 else
6571 expect_hr = D3D_OK;
6573 texture = (IDirect3DVolumeTexture8 *)0xdeadbeef;
6574 hr = IDirect3DDevice8_CreateVolumeTexture(device, w, h, d, 1, 0,
6575 formats[i].fmt, create_tests[j].pool, &texture);
6577 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
6578 * does not support it. Accept scratch creation of extension formats on
6579 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
6580 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
6581 * support it. */
6582 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
6583 may_succeed = TRUE;
6585 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
6586 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
6587 hr, formats[i].name, create_tests[j].name, w, h, d);
6589 if (FAILED(hr))
6590 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
6591 else
6592 IDirect3DVolumeTexture8_Release(texture);
6598 if (!support && !formats[i].core_fmt)
6599 continue;
6601 hr = IDirect3DDevice8_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
6602 formats[i].fmt, D3DPOOL_SCRATCH, &texture);
6603 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6605 /* Test lockrect offset */
6606 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
6608 unsigned int bytes_per_pixel;
6609 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
6611 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6612 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6614 base = locked_box.pBits;
6615 if (formats[i].broken == 1)
6617 expected_row_pitch = bytes_per_pixel * 24;
6619 else if (formats[i].broken == 2)
6621 expected_row_pitch = 24;
6623 else
6625 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
6626 * formats[i].block_size;
6628 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
6629 locked_box.RowPitch, formats[i].name, expected_row_pitch);
6631 if (formats[i].broken)
6633 expected_slice_pitch = expected_row_pitch * 8;
6635 else
6637 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
6638 * expected_row_pitch;
6640 ok(locked_box.SlicePitch == expected_slice_pitch,
6641 "Got unexpected slice pitch %d for format %s, expected %d.\n",
6642 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
6644 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6645 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
6647 box.Left = offset_tests[j].x;
6648 box.Top = offset_tests[j].y;
6649 box.Front = offset_tests[j].z;
6650 box.Right = offset_tests[j].x2;
6651 box.Bottom = offset_tests[j].y2;
6652 box.Back = offset_tests[j].z2;
6653 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6654 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
6656 offset = (BYTE *)locked_box.pBits - base;
6657 if (formats[i].broken == 1)
6659 expected_offset = box.Front * expected_slice_pitch
6660 + box.Top * expected_row_pitch
6661 + box.Left * bytes_per_pixel;
6663 else if (formats[i].broken == 2)
6665 expected_offset = box.Front * expected_slice_pitch
6666 + box.Top * expected_row_pitch
6667 + box.Left;
6669 else
6671 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
6672 + (box.Top / formats[i].block_height) * expected_row_pitch
6673 + (box.Left / formats[i].block_width) * formats[i].block_size;
6675 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
6676 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
6678 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6679 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6682 /* Test partial block locks */
6683 box.Front = 0;
6684 box.Back = 1;
6685 if (formats[i].block_width > 1)
6687 box.Left = formats[i].block_width >> 1;
6688 box.Top = 0;
6689 box.Right = formats[i].block_width;
6690 box.Bottom = formats[i].block_height;
6691 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6692 ok(FAILED(hr) || broken(formats[i].broken),
6693 "Partial block lock succeeded, expected failure, format %s.\n",
6694 formats[i].name);
6695 if (SUCCEEDED(hr))
6697 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6698 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6701 box.Left = 0;
6702 box.Top = 0;
6703 box.Right = formats[i].block_width >> 1;
6704 box.Bottom = formats[i].block_height;
6705 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6706 ok(FAILED(hr) || broken(formats[i].broken),
6707 "Partial block lock succeeded, expected failure, format %s.\n",
6708 formats[i].name);
6709 if (SUCCEEDED(hr))
6711 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6712 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6716 if (formats[i].block_height > 1)
6718 box.Left = 0;
6719 box.Top = formats[i].block_height >> 1;
6720 box.Right = formats[i].block_width;
6721 box.Bottom = formats[i].block_height;
6722 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6723 ok(FAILED(hr) || broken(formats[i].broken),
6724 "Partial block lock succeeded, expected failure, format %s.\n",
6725 formats[i].name);
6726 if (SUCCEEDED(hr))
6728 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6729 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6732 box.Left = 0;
6733 box.Top = 0;
6734 box.Right = formats[i].block_width;
6735 box.Bottom = formats[i].block_height >> 1;
6736 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6737 ok(FAILED(hr) || broken(formats[i].broken),
6738 "Partial block lock succeeded, expected failure, format %s.\n",
6739 formats[i].name);
6740 if (SUCCEEDED(hr))
6742 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6743 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6747 /* Test full block lock */
6748 box.Left = 0;
6749 box.Top = 0;
6750 box.Right = formats[i].block_width;
6751 box.Bottom = formats[i].block_height;
6752 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &box, 0);
6753 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6754 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6755 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6757 IDirect3DVolumeTexture8_Release(texture);
6759 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
6760 * does not allocate surfaces smaller than the blocksize properly. */
6761 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
6763 hr = IDirect3DDevice8_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
6764 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture);
6766 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
6767 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, NULL, 0);
6768 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
6769 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6770 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6772 box.Left = box.Top = box.Front = 0;
6773 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
6774 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
6775 box.Back = 1;
6776 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
6777 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
6778 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6779 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6781 box.Right = formats[i].block_width;
6782 box.Bottom = formats[i].block_height;
6783 hr = IDirect3DVolumeTexture8_LockBox(texture, 1, &locked_box, &box, 0);
6784 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6785 if (SUCCEEDED(hr))
6786 IDirect3DVolumeTexture8_UnlockBox(texture, 1);
6788 IDirect3DVolumeTexture8_Release(texture);
6792 refcount = IDirect3DDevice8_Release(device);
6793 ok(!refcount, "Device has %u references left.\n", refcount);
6794 IDirect3D8_Release(d3d8);
6795 DestroyWindow(window);
6798 static void test_lockbox_invalid(void)
6800 static const struct
6802 D3DBOX box;
6803 HRESULT result;
6805 test_data[] =
6807 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
6808 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
6809 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
6810 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
6811 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
6812 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
6813 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
6814 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
6815 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
6816 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
6817 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
6818 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
6819 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
6820 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
6822 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
6823 IDirect3DVolumeTexture8 *texture = NULL;
6824 D3DLOCKED_BOX locked_box;
6825 IDirect3DDevice8 *device;
6826 IDirect3D8 *d3d;
6827 unsigned int i;
6828 ULONG refcount;
6829 HWND window;
6830 BYTE *base;
6831 HRESULT hr;
6833 window = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
6834 0, 0, 640, 480, 0, 0, 0, 0);
6835 d3d = Direct3DCreate8(D3D_SDK_VERSION);
6836 ok(!!d3d, "Failed to create a D3D object.\n");
6837 if (!(device = create_device(d3d, window, NULL)))
6839 skip("Failed to create a D3D device, skipping tests.\n");
6840 IDirect3D8_Release(d3d);
6841 DestroyWindow(window);
6842 return;
6845 hr = IDirect3DDevice8_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
6846 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture);
6847 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
6848 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6849 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6850 base = locked_box.pBits;
6851 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6852 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6854 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
6856 unsigned int offset, expected_offset;
6857 const D3DBOX *box = &test_data[i].box;
6859 locked_box.pBits = (BYTE *)0xdeadbeef;
6860 locked_box.RowPitch = 0xdeadbeef;
6861 locked_box.SlicePitch = 0xdeadbeef;
6863 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, box, 0);
6864 /* Unlike surfaces, volumes properly check the box even in Windows XP */
6865 ok(hr == test_data[i].result,
6866 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
6867 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
6868 test_data[i].result);
6869 if (FAILED(hr))
6870 continue;
6872 offset = (BYTE *)locked_box.pBits - base;
6873 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
6874 ok(offset == expected_offset,
6875 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
6876 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
6878 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6879 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6882 /* locked_box = NULL throws an exception on Windows */
6883 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6884 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
6885 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, NULL, 0);
6886 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6887 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6888 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6889 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6890 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6892 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
6893 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
6894 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
6895 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
6896 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
6897 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
6898 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
6899 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
6900 hr = IDirect3DVolumeTexture8_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
6901 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
6902 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
6903 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
6904 hr = IDirect3DVolumeTexture8_UnlockBox(texture, 0);
6905 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
6907 IDirect3DVolumeTexture8_Release(texture);
6908 refcount = IDirect3DDevice8_Release(device);
6909 ok(!refcount, "Device has %u references left.\n", refcount);
6910 IDirect3D8_Release(d3d);
6911 DestroyWindow(window);
6914 static void test_pixel_format(void)
6916 HWND hwnd, hwnd2 = NULL;
6917 HDC hdc, hdc2 = NULL;
6918 HMODULE gl = NULL;
6919 int format, test_format;
6920 PIXELFORMATDESCRIPTOR pfd;
6921 IDirect3D8 *d3d8 = NULL;
6922 IDirect3DDevice8 *device = NULL;
6923 HRESULT hr;
6924 static const float point[3] = {0.0, 0.0, 0.0};
6926 hwnd = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
6927 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6928 if (!hwnd)
6930 skip("Failed to create window\n");
6931 return;
6934 hwnd2 = CreateWindowA("d3d8_test_wc", "d3d8_test", WS_OVERLAPPEDWINDOW,
6935 100, 100, 160, 160, NULL, NULL, NULL, NULL);
6937 hdc = GetDC(hwnd);
6938 if (!hdc)
6940 skip("Failed to get DC\n");
6941 goto cleanup;
6944 if (hwnd2)
6945 hdc2 = GetDC(hwnd2);
6947 gl = LoadLibraryA("opengl32.dll");
6948 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
6950 format = GetPixelFormat(hdc);
6951 ok(format == 0, "new window has pixel format %d\n", format);
6953 ZeroMemory(&pfd, sizeof(pfd));
6954 pfd.nSize = sizeof(pfd);
6955 pfd.nVersion = 1;
6956 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
6957 pfd.iPixelType = PFD_TYPE_RGBA;
6958 pfd.iLayerType = PFD_MAIN_PLANE;
6959 format = ChoosePixelFormat(hdc, &pfd);
6960 if (format <= 0)
6962 skip("no pixel format available\n");
6963 goto cleanup;
6966 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
6968 skip("failed to set pixel format\n");
6969 goto cleanup;
6972 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
6974 skip("failed to set pixel format on second window\n");
6975 if (hdc2)
6977 ReleaseDC(hwnd2, hdc2);
6978 hdc2 = NULL;
6982 d3d8 = Direct3DCreate8(D3D_SDK_VERSION);
6983 ok(!!d3d8, "Failed to create a D3D object.\n");
6985 test_format = GetPixelFormat(hdc);
6986 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6988 if (!(device = create_device(d3d8, hwnd, NULL)))
6990 skip("Failed to create device\n");
6991 goto cleanup;
6994 test_format = GetPixelFormat(hdc);
6995 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
6997 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
6998 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
7000 test_format = GetPixelFormat(hdc);
7001 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7003 hr = IDirect3DDevice8_BeginScene(device);
7004 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
7006 test_format = GetPixelFormat(hdc);
7007 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7009 hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
7010 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7012 test_format = GetPixelFormat(hdc);
7013 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7015 hr = IDirect3DDevice8_EndScene(device);
7016 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
7018 test_format = GetPixelFormat(hdc);
7019 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7021 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, 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 if (hdc2)
7029 hr = IDirect3DDevice8_Present(device, NULL, NULL, hwnd2, NULL);
7030 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
7032 test_format = GetPixelFormat(hdc);
7033 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
7035 test_format = GetPixelFormat(hdc2);
7036 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
7039 cleanup:
7040 if (device)
7042 UINT refcount = IDirect3DDevice8_Release(device);
7043 ok(!refcount, "Device has %u references left.\n", refcount);
7045 if (d3d8) IDirect3D8_Release(d3d8);
7046 if (gl) FreeLibrary(gl);
7047 if (hdc) ReleaseDC(hwnd, hdc);
7048 if (hdc2) ReleaseDC(hwnd2, hdc2);
7049 if (hwnd) DestroyWindow(hwnd);
7050 if (hwnd2) DestroyWindow(hwnd2);
7053 static void test_begin_end_state_block(void)
7055 IDirect3DDevice8 *device;
7056 DWORD stateblock;
7057 IDirect3D8 *d3d;
7058 ULONG refcount;
7059 HWND window;
7060 HRESULT hr;
7062 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7063 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7064 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7065 ok(!!d3d, "Failed to create a D3D object.\n");
7066 if (!(device = create_device(d3d, window, NULL)))
7068 skip("Failed to create a D3D device, skipping tests.\n");
7069 IDirect3D8_Release(d3d);
7070 DestroyWindow(window);
7071 return;
7074 /* Should succeed. */
7075 hr = IDirect3DDevice8_BeginStateBlock(device);
7076 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
7078 /* Calling BeginStateBlock() while recording should return
7079 * D3DERR_INVALIDCALL. */
7080 hr = IDirect3DDevice8_BeginStateBlock(device);
7081 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7083 /* Should succeed. */
7084 stateblock = 0xdeadbeef;
7085 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7086 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
7087 ok(!!stateblock && stateblock != 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
7088 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
7090 /* Calling EndStateBlock() while not recording should return
7091 * D3DERR_INVALIDCALL. stateblock should not be touched. */
7092 stateblock = 0xdeadbeef;
7093 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7094 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7095 ok(stateblock == 0xdeadbeef, "Got unexpected stateblock %#x.\n", stateblock);
7097 refcount = IDirect3DDevice8_Release(device);
7098 ok(!refcount, "Device has %u references left.\n", refcount);
7099 IDirect3D8_Release(d3d);
7100 DestroyWindow(window);
7103 static void test_shader_constant_apply(void)
7105 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
7106 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
7107 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
7108 DWORD vs_version, ps_version;
7109 IDirect3DDevice8 *device;
7110 DWORD stateblock;
7111 IDirect3D8 *d3d;
7112 ULONG refcount;
7113 D3DCAPS8 caps;
7114 float ret[4];
7115 HWND window;
7116 HRESULT hr;
7118 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7119 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7120 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7121 ok(!!d3d, "Failed to create a D3D object.\n");
7122 if (!(device = create_device(d3d, window, NULL)))
7124 skip("Failed to create a D3D device, skipping tests.\n");
7125 IDirect3D8_Release(d3d);
7126 DestroyWindow(window);
7127 return;
7130 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7131 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7132 vs_version = caps.VertexShaderVersion & 0xffff;
7133 ps_version = caps.PixelShaderVersion & 0xffff;
7135 if (vs_version)
7137 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, initial, 1);
7138 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7139 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, initial, 1);
7140 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7142 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7143 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7144 ok(!memcmp(ret, initial, sizeof(initial)),
7145 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7146 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7147 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7148 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7149 ok(!memcmp(ret, initial, sizeof(initial)),
7150 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7151 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7153 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, vs_const, 1);
7154 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7156 if (ps_version)
7158 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, initial, 1);
7159 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7160 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, initial, 1);
7161 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7163 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7164 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7165 ok(!memcmp(ret, initial, sizeof(initial)),
7166 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7167 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7168 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7169 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7170 ok(!memcmp(ret, initial, sizeof(initial)),
7171 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7172 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7174 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, ps_const, 1);
7175 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7178 hr = IDirect3DDevice8_BeginStateBlock(device);
7179 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
7181 if (vs_version)
7183 hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, vs_const, 1);
7184 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
7186 if (ps_version)
7188 hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, ps_const, 1);
7189 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
7192 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
7193 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
7195 if (vs_version)
7197 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7198 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7199 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7200 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7201 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7202 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7203 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7204 ok(!memcmp(ret, initial, sizeof(initial)),
7205 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7206 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7208 if (ps_version)
7210 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7211 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7212 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7213 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7214 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7215 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7216 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7217 ok(!memcmp(ret, initial, sizeof(initial)),
7218 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7219 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
7222 /* Apply doesn't overwrite constants that aren't explicitly set on the
7223 * source stateblock. */
7224 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
7225 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
7227 if (vs_version)
7229 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
7230 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7231 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7232 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7233 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7234 hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
7235 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
7236 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
7237 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7238 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
7240 if (ps_version)
7242 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
7243 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7244 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7245 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7246 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7247 hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
7248 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
7249 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
7250 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
7251 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
7254 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
7255 refcount = IDirect3DDevice8_Release(device);
7256 ok(!refcount, "Device has %u references left.\n", refcount);
7257 IDirect3D8_Release(d3d);
7258 DestroyWindow(window);
7261 static void test_resource_type(void)
7263 IDirect3DDevice8 *device;
7264 IDirect3DSurface8 *surface;
7265 IDirect3DTexture8 *texture;
7266 IDirect3DCubeTexture8 *cube_texture;
7267 IDirect3DVolume8 *volume;
7268 IDirect3DVolumeTexture8 *volume_texture;
7269 D3DSURFACE_DESC surface_desc;
7270 D3DVOLUME_DESC volume_desc;
7271 D3DRESOURCETYPE type;
7272 IDirect3D8 *d3d;
7273 ULONG refcount;
7274 HWND window;
7275 HRESULT hr;
7276 D3DCAPS8 caps;
7278 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7279 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7280 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7281 ok(!!d3d, "Failed to create a D3D object.\n");
7282 if (!(device = create_device(d3d, window, NULL)))
7284 skip("Failed to create a D3D device, skipping tests.\n");
7285 IDirect3D8_Release(d3d);
7286 DestroyWindow(window);
7287 return;
7290 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7291 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7293 hr = IDirect3DDevice8_CreateImageSurface(device, 4, 4, D3DFMT_X8R8G8B8, &surface);
7294 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7295 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7296 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7297 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7298 surface_desc.Type);
7299 IDirect3DSurface8_Release(surface);
7301 hr = IDirect3DDevice8_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
7302 D3DPOOL_SYSTEMMEM, &texture);
7303 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7304 type = IDirect3DTexture8_GetType(texture);
7305 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
7307 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
7308 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7309 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7310 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7311 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7312 surface_desc.Type);
7313 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
7314 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
7315 hr = IDirect3DTexture8_GetLevelDesc(texture, 0, &surface_desc);
7316 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7317 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7318 surface_desc.Type);
7319 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
7320 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
7321 IDirect3DSurface8_Release(surface);
7323 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 2, &surface);
7324 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7325 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7326 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7327 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7328 surface_desc.Type);
7329 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
7330 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
7331 hr = IDirect3DTexture8_GetLevelDesc(texture, 2, &surface_desc);
7332 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7333 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7334 surface_desc.Type);
7335 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
7336 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
7337 IDirect3DSurface8_Release(surface);
7338 IDirect3DTexture8_Release(texture);
7340 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7342 hr = IDirect3DDevice8_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
7343 D3DPOOL_SYSTEMMEM, &cube_texture);
7344 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
7345 type = IDirect3DCubeTexture8_GetType(cube_texture);
7346 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
7348 hr = IDirect3DCubeTexture8_GetCubeMapSurface(cube_texture,
7349 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7350 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
7351 hr = IDirect3DSurface8_GetDesc(surface, &surface_desc);
7352 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
7353 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7354 surface_desc.Type);
7355 hr = IDirect3DCubeTexture8_GetLevelDesc(cube_texture, 0, &surface_desc);
7356 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7357 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
7358 surface_desc.Type);
7359 IDirect3DSurface8_Release(surface);
7360 IDirect3DCubeTexture8_Release(cube_texture);
7362 else
7363 skip("Cube maps not supported.\n");
7365 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
7367 hr = IDirect3DDevice8_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
7368 D3DPOOL_SYSTEMMEM, &volume_texture);
7369 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
7370 type = IDirect3DVolumeTexture8_GetType(volume_texture);
7371 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
7373 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 0, &volume);
7374 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
7375 /* IDirect3DVolume8 is not an IDirect3DResource8 and has no GetType method. */
7376 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
7377 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
7378 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7379 volume_desc.Type);
7380 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
7381 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
7382 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
7383 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 0, &volume_desc);
7384 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7385 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7386 volume_desc.Type);
7387 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
7388 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
7389 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
7390 IDirect3DVolume8_Release(volume);
7392 hr = IDirect3DVolumeTexture8_GetVolumeLevel(volume_texture, 2, &volume);
7393 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
7394 hr = IDirect3DVolume8_GetDesc(volume, &volume_desc);
7395 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
7396 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7397 volume_desc.Type);
7398 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
7399 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
7400 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
7401 hr = IDirect3DVolumeTexture8_GetLevelDesc(volume_texture, 2, &volume_desc);
7402 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
7403 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
7404 volume_desc.Type);
7405 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
7406 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
7407 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
7408 IDirect3DVolume8_Release(volume);
7409 IDirect3DVolumeTexture8_Release(volume_texture);
7411 else
7412 skip("Mipmapped volume maps not supported.\n");
7414 refcount = IDirect3DDevice8_Release(device);
7415 ok(!refcount, "Device has %u references left.\n", refcount);
7416 IDirect3D8_Release(d3d);
7417 DestroyWindow(window);
7420 static void test_mipmap_lock(void)
7422 IDirect3DDevice8 *device;
7423 IDirect3DSurface8 *surface, *surface2, *surface_dst, *surface_dst2;
7424 IDirect3DTexture8 *texture, *texture_dst;
7425 IDirect3D8 *d3d;
7426 ULONG refcount;
7427 HWND window;
7428 HRESULT hr;
7429 D3DLOCKED_RECT locked_rect;
7431 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7432 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7433 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7434 ok(!!d3d, "Failed to create a D3D object.\n");
7435 if (!(device = create_device(d3d, window, NULL)))
7437 skip("Failed to create a D3D device, skipping tests.\n");
7438 IDirect3D8_Release(d3d);
7439 DestroyWindow(window);
7440 return;
7443 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
7444 D3DPOOL_DEFAULT, &texture_dst);
7445 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7446 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 0, &surface_dst);
7447 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7448 hr = IDirect3DTexture8_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
7449 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7451 hr = IDirect3DDevice8_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
7452 D3DPOOL_SYSTEMMEM, &texture);
7453 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7454 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &surface);
7455 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7456 hr = IDirect3DTexture8_GetSurfaceLevel(texture, 1, &surface2);
7457 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7459 hr = IDirect3DSurface8_LockRect(surface, &locked_rect, NULL, 0);
7460 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7461 hr = IDirect3DSurface8_LockRect(surface2, &locked_rect, NULL, 0);
7462 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7463 hr = IDirect3DSurface8_UnlockRect(surface);
7464 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7466 hr = IDirect3DDevice8_CopyRects(device, surface, NULL, 0, surface_dst, NULL);
7467 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
7468 hr = IDirect3DDevice8_CopyRects(device, surface2, NULL, 0, surface_dst2, NULL);
7469 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7471 /* Apparently there's no validation on the container. */
7472 hr = IDirect3DDevice8_UpdateTexture(device, (IDirect3DBaseTexture8 *)texture,
7473 (IDirect3DBaseTexture8 *)texture_dst);
7474 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
7476 hr = IDirect3DSurface8_UnlockRect(surface2);
7477 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7479 IDirect3DSurface8_Release(surface_dst2);
7480 IDirect3DSurface8_Release(surface_dst);
7481 IDirect3DSurface8_Release(surface2);
7482 IDirect3DSurface8_Release(surface);
7483 IDirect3DTexture8_Release(texture_dst);
7484 IDirect3DTexture8_Release(texture);
7486 refcount = IDirect3DDevice8_Release(device);
7487 ok(!refcount, "Device has %u references left.\n", refcount);
7488 IDirect3D8_Release(d3d);
7489 DestroyWindow(window);
7492 static void test_writeonly_resource(void)
7494 IDirect3D8 *d3d;
7495 IDirect3DDevice8 *device;
7496 IDirect3DVertexBuffer8 *buffer;
7497 ULONG refcount;
7498 HWND window;
7499 HRESULT hr;
7500 BYTE *ptr;
7501 static const struct
7503 struct vec3 pos;
7505 quad[] =
7507 {{-1.0f, -1.0f, 0.0f}},
7508 {{-1.0f, 1.0f, 0.0f}},
7509 {{ 1.0f, -1.0f, 0.0f}},
7510 {{ 1.0f, 1.0f, 0.0f}}
7513 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7514 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7515 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7516 ok(!!d3d, "Failed to create a D3D object.\n");
7517 if (!(device = create_device(d3d, window, NULL)))
7519 skip("Failed to create a D3D device, skipping tests.\n");
7520 IDirect3D8_Release(d3d);
7521 DestroyWindow(window);
7522 return;
7525 hr = IDirect3DDevice8_CreateVertexBuffer(device, sizeof(quad),
7526 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer);
7527 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
7529 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
7530 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7531 memcpy(ptr, quad, sizeof(quad));
7532 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7533 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7534 hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*quad));
7535 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
7536 hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ);
7537 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
7539 hr = IDirect3DDevice8_BeginScene(device);
7540 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
7541 hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7542 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
7543 hr = IDirect3DDevice8_EndScene(device);
7544 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
7546 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, 0);
7547 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7548 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7549 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7550 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7552 hr = IDirect3DVertexBuffer8_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
7553 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
7554 ok (!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
7555 hr = IDirect3DVertexBuffer8_Unlock(buffer);
7556 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
7558 refcount = IDirect3DVertexBuffer8_Release(buffer);
7559 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
7560 refcount = IDirect3DDevice8_Release(device);
7561 ok(!refcount, "Device has %u references left.\n", refcount);
7562 IDirect3D8_Release(d3d);
7563 DestroyWindow(window);
7566 static void test_lost_device(void)
7568 struct device_desc device_desc;
7569 IDirect3DDevice8 *device;
7570 IDirect3D8 *d3d;
7571 ULONG refcount;
7572 HWND window;
7573 HRESULT hr;
7574 BOOL ret;
7576 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7577 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7578 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7579 ok(!!d3d, "Failed to create a D3D object.\n");
7580 device_desc.device_window = window;
7581 device_desc.width = registry_mode.dmPelsWidth;
7582 device_desc.height = registry_mode.dmPelsHeight;
7583 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
7584 if (!(device = create_device(d3d, window, &device_desc)))
7586 skip("Failed to create a D3D device, skipping tests.\n");
7587 goto done;
7590 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7591 if (hr == D3DERR_DEVICELOST)
7593 win_skip("Broken TestCooperativeLevel(), skipping test.\n");
7594 IDirect3DDevice8_Release(device);
7595 goto done;
7597 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7598 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7599 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7601 ret = SetForegroundWindow(GetDesktopWindow());
7602 ok(ret, "Failed to set foreground window.\n");
7603 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7604 /* The device is not lost on Windows 10. */
7605 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7606 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7607 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7609 ret = ShowWindow(window, SW_RESTORE);
7610 ok(ret, "Failed to restore window.\n");
7611 ret = SetForegroundWindow(window);
7612 ok(ret, "Failed to set foreground window.\n");
7613 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7614 ok(hr == D3DERR_DEVICENOTRESET || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7615 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7616 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
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 device_desc.flags = 0;
7626 hr = reset_device(device, &device_desc);
7627 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7628 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7629 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7630 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7631 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7633 ret = SetForegroundWindow(GetDesktopWindow());
7634 ok(ret, "Failed to set foreground window.\n");
7635 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7636 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7637 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7638 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7640 ret = ShowWindow(window, SW_RESTORE);
7641 ok(ret, "Failed to restore window.\n");
7642 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7643 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7644 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7645 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7647 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
7648 hr = reset_device(device, &device_desc);
7649 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7650 hr = IDirect3DDevice8_TestCooperativeLevel(device);
7651 /* The device is not lost on Windows 10. */
7652 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7653 hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
7654 todo_wine ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7656 ret = SetForegroundWindow(GetDesktopWindow());
7657 ok(ret, "Failed to set foreground window.\n");
7658 hr = reset_device(device, &device_desc);
7659 ok(hr == D3DERR_DEVICELOST || broken(hr == D3D_OK), "Got unexpected hr %#x.\n", hr);
7660 ret = ShowWindow(window, SW_RESTORE);
7661 ok(ret, "Failed to restore window.\n");
7662 ret = SetForegroundWindow(window);
7663 ok(ret, "Failed to set foreground window.\n");
7664 hr = reset_device(device, &device_desc);
7665 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7667 refcount = IDirect3DDevice8_Release(device);
7668 ok(!refcount, "Device has %u references left.\n", refcount);
7669 done:
7670 IDirect3D8_Release(d3d);
7671 DestroyWindow(window);
7674 static void test_resource_priority(void)
7676 IDirect3DDevice8 *device;
7677 IDirect3DTexture8 *texture;
7678 IDirect3DVertexBuffer8 *buffer;
7679 IDirect3D8 *d3d;
7680 ULONG refcount;
7681 HWND window;
7682 HRESULT hr;
7683 static const struct
7685 D3DPOOL pool;
7686 const char *name;
7687 BOOL can_set_priority;
7689 test_data[] =
7691 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
7692 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
7693 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
7694 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
7696 unsigned int i;
7697 DWORD priority;
7699 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7700 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7701 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7702 ok(!!d3d, "Failed to create a D3D object.\n");
7703 if (!(device = create_device(d3d, window, NULL)))
7705 skip("Failed to create a D3D device, skipping tests.\n");
7706 IDirect3D8_Release(d3d);
7707 DestroyWindow(window);
7708 return;
7711 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
7713 hr = IDirect3DDevice8_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
7714 test_data[i].pool, &texture);
7715 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
7717 priority = IDirect3DTexture8_GetPriority(texture);
7718 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7719 priority = IDirect3DTexture8_SetPriority(texture, 1);
7720 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7721 priority = IDirect3DTexture8_GetPriority(texture);
7722 if (test_data[i].can_set_priority)
7724 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7725 priority = IDirect3DTexture8_SetPriority(texture, 0);
7726 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7728 else
7729 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7731 IDirect3DTexture8_Release(texture);
7733 if (test_data[i].pool != D3DPOOL_SCRATCH)
7735 hr = IDirect3DDevice8_CreateVertexBuffer(device, 256, 0, 0,
7736 test_data[i].pool, &buffer);
7737 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
7739 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
7740 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7741 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 1);
7742 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7743 priority = IDirect3DVertexBuffer8_GetPriority(buffer);
7744 if (test_data[i].can_set_priority)
7746 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7747 priority = IDirect3DVertexBuffer8_SetPriority(buffer, 0);
7748 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7750 else
7751 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
7753 IDirect3DVertexBuffer8_Release(buffer);
7757 refcount = IDirect3DDevice8_Release(device);
7758 ok(!refcount, "Device has %u references left.\n", refcount);
7759 IDirect3D8_Release(d3d);
7760 DestroyWindow(window);
7763 static void test_swapchain_parameters(void)
7765 IDirect3DDevice8 *device;
7766 IDirect3D8 *d3d;
7767 IDirect3DSurface8 *backbuffer;
7768 HWND window;
7769 HRESULT hr;
7770 unsigned int i, j;
7771 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0};
7772 static const struct
7774 BOOL windowed;
7775 UINT backbuffer_count;
7776 D3DSWAPEFFECT swap_effect;
7777 HRESULT hr;
7779 tests[] =
7781 /* Swap effect 0 is not allowed. */
7782 {TRUE, 1, 0, D3DERR_INVALIDCALL},
7783 {FALSE, 1, 0, D3DERR_INVALIDCALL},
7785 /* All (non-ex) swap effects are allowed in
7786 * windowed and fullscreen mode. */
7787 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
7788 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
7789 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
7790 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
7791 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
7793 /* Only one backbuffer in copy mode. Reset allows it for
7794 * some reason. */
7795 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
7796 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
7797 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
7798 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
7799 {TRUE, 0, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
7800 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC, D3D_OK},
7801 {TRUE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
7802 {FALSE, 2, D3DSWAPEFFECT_COPY_VSYNC, D3DERR_INVALIDCALL},
7804 /* Ok with the others, in fullscreen and windowed mode. */
7805 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
7806 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
7807 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
7808 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
7810 /* Invalid swapeffects. */
7811 {TRUE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
7812 {FALSE, 1, D3DSWAPEFFECT_COPY_VSYNC + 1, D3DERR_INVALIDCALL},
7814 /* 3 is the highest allowed backbuffer count. */
7815 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
7816 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
7817 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
7818 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
7819 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
7822 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7823 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7824 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7825 ok(!!d3d, "Failed to create a D3D object.\n");
7826 if (!(device = create_device(d3d, window, NULL)))
7828 skip("Failed to create a D3D device, skipping tests.\n");
7829 IDirect3D8_Release(d3d);
7830 DestroyWindow(window);
7831 return;
7833 IDirect3DDevice8_Release(device);
7835 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
7836 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
7837 present_parameters_windowed.hDeviceWindow = window;
7838 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
7839 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
7840 present_parameters_windowed.Windowed = TRUE;
7841 present_parameters_windowed.BackBufferCount = 1;
7843 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
7845 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
7847 memset(&present_parameters, 0, sizeof(present_parameters));
7848 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
7849 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
7850 present_parameters.hDeviceWindow = window;
7851 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
7853 present_parameters.SwapEffect = tests[i].swap_effect;
7854 present_parameters.Windowed = tests[i].windowed;
7855 present_parameters.BackBufferCount = tests[i].backbuffer_count;
7857 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
7858 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
7859 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
7860 if (SUCCEEDED(hr))
7862 for (j = 0; j < bb_count; ++j)
7864 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7865 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#x, test %u.\n", j, hr, i);
7866 IDirect3DSurface8_Release(backbuffer);
7868 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7869 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %x, test %u.\n", hr, i);
7871 IDirect3DDevice8_Release(device);
7874 hr = IDirect3D8_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
7875 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
7876 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
7878 memset(&present_parameters, 0, sizeof(present_parameters));
7879 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
7880 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
7881 present_parameters.hDeviceWindow = window;
7882 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
7884 present_parameters.SwapEffect = tests[i].swap_effect;
7885 present_parameters.Windowed = tests[i].windowed;
7886 present_parameters.BackBufferCount = tests[i].backbuffer_count;
7888 hr = IDirect3DDevice8_Reset(device, &present_parameters);
7889 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
7891 if (FAILED(hr))
7893 hr = IDirect3DDevice8_Reset(device, &present_parameters_windowed);
7894 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
7896 else
7898 for (j = 0; j < bb_count; ++j)
7900 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7901 todo_wine_if (j)
7902 ok(SUCCEEDED(hr), "Failed to get backbuffer %u, hr %#x, test %u.\n", j, hr, i);
7903 if (SUCCEEDED(hr))
7904 IDirect3DSurface8_Release(backbuffer);
7906 hr = IDirect3DDevice8_GetBackBuffer(device, j, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7907 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %x, test %u.\n", hr, i);
7909 IDirect3DDevice8_Release(device);
7912 IDirect3D8_Release(d3d);
7913 DestroyWindow(window);
7916 static void test_check_device_format(void)
7918 IDirect3D8 *d3d;
7919 HRESULT hr;
7921 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7922 ok(!!d3d, "Failed to create a D3D object.\n");
7924 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7925 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
7926 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7927 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7928 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
7929 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7930 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7931 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
7932 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7934 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7935 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
7936 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7937 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7938 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
7939 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7940 hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7941 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
7942 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7944 IDirect3D8_Release(d3d);
7947 static void test_miptree_layout(void)
7949 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
7950 IDirect3DCubeTexture8 *texture_cube;
7951 IDirect3DTexture8 *texture_2d;
7952 IDirect3DDevice8 *device;
7953 D3DLOCKED_RECT map_desc;
7954 BYTE *base = NULL;
7955 IDirect3D8 *d3d;
7956 D3DCAPS8 caps;
7957 UINT refcount;
7958 HWND window;
7959 HRESULT hr;
7961 static const struct
7963 D3DFORMAT format;
7964 const char *name;
7966 formats[] =
7968 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
7969 {D3DFMT_A8, "D3DFMT_A8"},
7970 {D3DFMT_L8, "D3DFMT_L8"},
7971 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
7972 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
7974 static const struct
7976 D3DPOOL pool;
7977 const char *name;
7979 pools[] =
7981 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
7982 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
7983 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
7986 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
7987 0, 0, 640, 480, NULL, NULL, NULL, NULL);
7988 d3d = Direct3DCreate8(D3D_SDK_VERSION);
7989 ok(!!d3d, "Failed to create a D3D object.\n");
7990 if (!(device = create_device(d3d, window, NULL)))
7992 skip("Failed to create a D3D device, skipping tests.\n");
7993 goto done;
7996 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
7997 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7999 base_dimension = 257;
8000 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
8002 skip("Using power of two base dimension.\n");
8003 base_dimension = 256;
8006 for (format_idx = 0; format_idx < sizeof(formats) / sizeof(*formats); ++format_idx)
8008 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8009 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
8011 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
8012 continue;
8015 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
8017 hr = IDirect3DDevice8_CreateTexture(device, base_dimension, base_dimension, 0, 0,
8018 formats[format_idx].format, pools[pool_idx].pool, &texture_2d);
8019 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
8020 pools[pool_idx].name, formats[format_idx].name, hr);
8022 level_count = IDirect3DTexture8_GetLevelCount(texture_2d);
8023 for (i = 0, offset = 0; i < level_count; ++i)
8025 hr = IDirect3DTexture8_LockRect(texture_2d, i, &map_desc, NULL, 0);
8026 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
8027 pools[pool_idx].name, formats[format_idx].name, i, hr);
8029 if (!i)
8030 base = map_desc.pBits;
8031 else
8032 ok(map_desc.pBits == base + offset,
8033 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
8034 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
8035 offset += (base_dimension >> i) * map_desc.Pitch;
8037 hr = IDirect3DTexture8_UnlockRect(texture_2d, i);
8038 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
8039 pools[pool_idx].name, formats[format_idx].name, i, hr);
8042 IDirect3DTexture8_Release(texture_2d);
8045 if (FAILED(hr = IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8046 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
8048 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
8049 continue;
8052 for (pool_idx = 0; pool_idx < sizeof(pools) / sizeof(*pools); ++pool_idx)
8054 hr = IDirect3DDevice8_CreateCubeTexture(device, base_dimension, 0, 0,
8055 formats[format_idx].format, pools[pool_idx].pool, &texture_cube);
8056 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
8057 pools[pool_idx].name, formats[format_idx].name, hr);
8059 level_count = IDirect3DCubeTexture8_GetLevelCount(texture_cube);
8060 for (i = 0, offset = 0; i < 6; ++i)
8062 for (j = 0; j < level_count; ++j)
8064 hr = IDirect3DCubeTexture8_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
8065 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
8066 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
8068 if (!i && !j)
8069 base = map_desc.pBits;
8070 else
8071 ok(map_desc.pBits == base + offset,
8072 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
8073 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
8074 offset += (base_dimension >> j) * map_desc.Pitch;
8076 hr = IDirect3DCubeTexture8_UnlockRect(texture_cube, i, j);
8077 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
8078 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
8080 offset = (offset + 15) & ~15;
8083 IDirect3DCubeTexture8_Release(texture_cube);
8087 refcount = IDirect3DDevice8_Release(device);
8088 ok(!refcount, "Device has %u references left.\n", refcount);
8089 done:
8090 IDirect3D8_Release(d3d);
8091 DestroyWindow(window);
8094 static void test_render_target_device_mismatch(void)
8096 IDirect3DDevice8 *device, *device2;
8097 IDirect3DSurface8 *surface, *rt;
8098 IDirect3D8 *d3d;
8099 UINT refcount;
8100 HWND window;
8101 HRESULT hr;
8103 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
8104 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8105 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8106 ok(!!d3d, "Failed to create a D3D object.\n");
8107 if (!(device = create_device(d3d, window, NULL)))
8109 skip("Failed to create a D3D device.\n");
8110 IDirect3D8_Release(d3d);
8111 DestroyWindow(window);
8112 return;
8115 hr = IDirect3DDevice8_GetRenderTarget(device, &rt);
8116 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8118 device2 = create_device(d3d, window, NULL);
8119 ok(!!device2, "Failed to create a D3D device.\n");
8121 hr = IDirect3DDevice8_CreateRenderTarget(device2, 640, 480,
8122 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, FALSE, &surface);
8123 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8125 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
8126 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8128 IDirect3DSurface8_Release(surface);
8130 hr = IDirect3DDevice8_GetRenderTarget(device2, &surface);
8131 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8133 hr = IDirect3DDevice8_SetRenderTarget(device, surface, NULL);
8134 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8136 IDirect3DSurface8_Release(surface);
8138 hr = IDirect3DDevice8_GetRenderTarget(device, &surface);
8139 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
8140 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
8141 IDirect3DSurface8_Release(surface);
8142 IDirect3DSurface8_Release(rt);
8144 refcount = IDirect3DDevice8_Release(device);
8145 ok(!refcount, "Device has %u references left.\n", refcount);
8146 refcount = IDirect3DDevice8_Release(device2);
8147 ok(!refcount, "Device has %u references left.\n", refcount);
8148 IDirect3D8_Release(d3d);
8149 DestroyWindow(window);
8152 static void test_format_unknown(void)
8154 IDirect3DDevice8 *device;
8155 IDirect3D8 *d3d;
8156 UINT refcount;
8157 HWND window;
8158 void *iface;
8159 HRESULT hr;
8161 window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW,
8162 0, 0, 640, 480, NULL, NULL, NULL, NULL);
8163 d3d = Direct3DCreate8(D3D_SDK_VERSION);
8164 ok(!!d3d, "Failed to create a D3D object.\n");
8165 if (!(device = create_device(d3d, window, NULL)))
8167 skip("Failed to create a D3D device.\n");
8168 IDirect3D8_Release(d3d);
8169 DestroyWindow(window);
8170 return;
8173 if (SUCCEEDED(IDirect3D8_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
8174 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_P8)))
8176 skip("P8 textures are supported, skipping some tests.\n");
8178 else
8180 iface = (void *)0xdeadbeef;
8181 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64,
8182 D3DFMT_P8, D3DMULTISAMPLE_NONE, FALSE, (IDirect3DSurface8 **)&iface);
8183 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8184 ok(!iface, "Got unexpected iface %p.\n", iface);
8186 iface = (void *)0xdeadbeef;
8187 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 64, 64,
8188 D3DFMT_P8, D3DMULTISAMPLE_NONE, (IDirect3DSurface8 **)&iface);
8189 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8190 ok(!iface, "Got unexpected iface %p.\n", iface);
8192 iface = (void *)0xdeadbeef;
8193 hr = IDirect3DDevice8_CreateTexture(device, 64, 64, 1, 0,
8194 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DTexture8 **)&iface);
8195 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8196 ok(!iface, "Got unexpected iface %p.\n", iface);
8198 iface = (void *)0xdeadbeef;
8199 hr = IDirect3DDevice8_CreateCubeTexture(device, 64, 1, 0,
8200 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DCubeTexture8 **)&iface);
8201 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8202 ok(!iface, "Got unexpected iface %p.\n", iface);
8204 iface = (void *)0xdeadbeef;
8205 hr = IDirect3DDevice8_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
8206 D3DFMT_P8, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture8 **)&iface);
8207 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8208 ok(!iface, "Got unexpected iface %p.\n", iface);
8211 iface = (void *)0xdeadbeef;
8212 hr = IDirect3DDevice8_CreateRenderTarget(device, 64, 64,
8213 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, FALSE, (IDirect3DSurface8 **)&iface);
8214 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8215 todo_wine ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8217 iface = (void *)0xdeadbeef;
8218 hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 64, 64,
8219 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, (IDirect3DSurface8 **)&iface);
8220 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8221 todo_wine ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8223 iface = (void *)0xdeadbeef;
8224 hr = IDirect3DDevice8_CreateImageSurface(device, 64, 64,
8225 D3DFMT_UNKNOWN, (IDirect3DSurface8 **)&iface);
8226 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8227 ok(!iface, "Got unexpected iface %p.\n", iface);
8229 iface = (void *)0xdeadbeef;
8230 hr = IDirect3DDevice8_CreateTexture(device, 64, 64, 1, 0,
8231 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture8 **)&iface);
8232 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8233 todo_wine ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8235 iface = (void *)0xdeadbeef;
8236 hr = IDirect3DDevice8_CreateCubeTexture(device, 64, 1, 0,
8237 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture8 **)&iface);
8238 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8239 todo_wine ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8241 iface = (void *)0xdeadbeef;
8242 hr = IDirect3DDevice8_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
8243 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture8 **)&iface);
8244 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8245 todo_wine ok(iface == (void *)0xdeadbeef, "Got unexpected iface %p.\n", iface);
8247 refcount = IDirect3DDevice8_Release(device);
8248 ok(!refcount, "Device has %u references left.\n", refcount);
8249 IDirect3D8_Release(d3d);
8250 DestroyWindow(window);
8253 START_TEST(device)
8255 HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
8256 WNDCLASSA wc = {0};
8257 IDirect3D8 *d3d8;
8258 DEVMODEW current_mode;
8260 if (!d3d8_handle)
8262 skip("Could not load d3d8.dll\n");
8263 return;
8266 memset(&current_mode, 0, sizeof(current_mode));
8267 current_mode.dmSize = sizeof(current_mode);
8268 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
8269 registry_mode.dmSize = sizeof(registry_mode);
8270 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
8271 if (current_mode.dmPelsWidth != registry_mode.dmPelsWidth
8272 || current_mode.dmPelsHeight != registry_mode.dmPelsHeight)
8274 skip("Current mode does not match registry mode, skipping test.\n");
8275 return;
8278 wc.lpfnWndProc = DefWindowProcA;
8279 wc.lpszClassName = "d3d8_test_wc";
8280 RegisterClassA(&wc);
8282 ValidateVertexShader = (void *)GetProcAddress(d3d8_handle, "ValidateVertexShader");
8283 ValidatePixelShader = (void *)GetProcAddress(d3d8_handle, "ValidatePixelShader");
8285 if (!(d3d8 = Direct3DCreate8(D3D_SDK_VERSION)))
8287 skip("could not create D3D8\n");
8288 return;
8290 IDirect3D8_Release(d3d8);
8292 test_fpu_setup();
8293 test_display_formats();
8294 test_display_modes();
8295 test_shader_versions();
8296 test_swapchain();
8297 test_refcount();
8298 test_mipmap_levels();
8299 test_checkdevicemultisampletype();
8300 test_invalid_multisample();
8301 test_cursor();
8302 test_cursor_pos();
8303 test_states();
8304 test_reset();
8305 test_scene();
8306 test_shader();
8307 test_limits();
8308 test_lights();
8309 test_ApplyStateBlock();
8310 test_render_zero_triangles();
8311 test_depth_stencil_reset();
8312 test_wndproc();
8313 test_wndproc_windowed();
8314 test_depth_stencil_size();
8315 test_window_style();
8316 test_unsupported_shaders();
8317 test_mode_change();
8318 test_device_window_reset();
8319 test_reset_resources();
8320 depth_blit_test();
8321 test_set_rt_vp_scissor();
8322 test_validate_vs();
8323 test_validate_ps();
8324 test_volume_get_container();
8325 test_vb_lock_flags();
8326 test_texture_stage_states();
8327 test_cube_textures();
8328 test_get_set_texture();
8329 test_image_surface_pool();
8330 test_surface_get_container();
8331 test_lockrect_invalid();
8332 test_private_data();
8333 test_surface_dimensions();
8334 test_surface_format_null();
8335 test_surface_double_unlock();
8336 test_surface_blocks();
8337 test_set_palette();
8338 test_swvp_buffer();
8339 test_managed_buffer();
8340 test_npot_textures();
8341 test_volume_locking();
8342 test_update_volumetexture();
8343 test_create_rt_ds_fail();
8344 test_volume_blocks();
8345 test_lockbox_invalid();
8346 test_pixel_format();
8347 test_begin_end_state_block();
8348 test_shader_constant_apply();
8349 test_resource_type();
8350 test_mipmap_lock();
8351 test_writeonly_resource();
8352 test_lost_device();
8353 test_resource_priority();
8354 test_swapchain_parameters();
8355 test_check_device_format();
8356 test_miptree_layout();
8357 test_render_target_device_mismatch();
8358 test_format_unknown();
8360 UnregisterClassA("d3d8_test_wc", GetModuleHandleA(NULL));