wined3d: Require exclusive GPU access for rendertarget and depth/stencil resources.
[wine.git] / dlls / d3d9 / tests / device.c
blobf3b9a0ae26e00d5a57fa2f5ea1bd3d36e9f2b844
1 /*
2 * Copyright (C) 2006 Ivan Gyurdiev
3 * Copyright (C) 2006 Vitaliy Margolen
4 * Copyright (C) 2006 Chris Robinson
5 * Copyright 2006-2008, 2010-2011, 2013 Stefan Dösinger for CodeWeavers
6 * Copyright 2005, 2006, 2007 Henri Verbeet
7 * Copyright 2013-2014 Henri Verbeet for CodeWeavers
8 * Copyright (C) 2008 Rico Schüller
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WINVER 0x0602 /* for CURSOR_SUPPRESSED */
26 #define COBJMACROS
27 #include <d3d9.h>
28 #include "wine/test.h"
30 struct vec3
32 float x, y, z;
35 #define CREATE_DEVICE_FULLSCREEN 0x01
36 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
37 #define CREATE_DEVICE_FPU_PRESERVE 0x04
38 #define CREATE_DEVICE_SWVP_ONLY 0x08
39 #define CREATE_DEVICE_MIXED_ONLY 0x10
40 #define CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT 0x20
41 #define CREATE_DEVICE_LOCKABLE_BACKBUFFER 0x40
43 struct device_desc
45 HWND device_window;
46 unsigned int width;
47 unsigned int height;
48 DWORD flags;
51 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
52 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
54 static DEVMODEW registry_mode;
56 static const DWORD simple_vs[] =
58 0xfffe0101, /* vs_1_1 */
59 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
60 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
61 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
62 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
63 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
64 0x0000ffff, /* end */
67 static const DWORD simple_ps[] =
69 0xffff0101, /* ps_1_1 */
70 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
71 0x00000042, 0xb00f0000, /* tex t0 */
72 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
73 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
74 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
75 0x0000ffff, /* end */
78 static int get_refcount(IUnknown *object)
80 IUnknown_AddRef( object );
81 return IUnknown_Release( object );
84 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
86 unsigned int element_count, i;
87 D3DVERTEXELEMENT9 *elements;
88 BOOL equal = TRUE;
89 HRESULT hr;
91 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
92 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
93 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
94 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
95 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
97 for (i = 0; i < element_count; ++i)
99 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
101 equal = FALSE;
102 break;
106 if (!equal)
108 for (i = 0; i < element_count; ++i)
110 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
111 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
112 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
116 HeapFree(GetProcessHeap(), 0, elements);
117 return equal;
120 static HWND create_window(void)
122 RECT r = {0, 0, 640, 480};
124 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
126 return CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
127 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
130 /* try to make sure pending X events have been processed before continuing */
131 static void flush_events(void)
133 MSG msg;
134 int diff = 200;
135 int min_timeout = 100;
136 DWORD time = GetTickCount() + diff;
138 while (diff > 0)
140 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
141 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
142 diff = time - GetTickCount();
146 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
148 D3DPRESENT_PARAMETERS present_parameters = {0};
149 IDirect3DDevice9 *device;
150 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
152 present_parameters.BackBufferWidth = 640;
153 present_parameters.BackBufferHeight = 480;
154 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
155 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
156 present_parameters.hDeviceWindow = focus_window;
157 present_parameters.Windowed = TRUE;
158 present_parameters.EnableAutoDepthStencil = TRUE;
159 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
161 if (desc)
163 present_parameters.BackBufferWidth = desc->width;
164 present_parameters.BackBufferHeight = desc->height;
165 if (desc->flags & CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT)
166 present_parameters.BackBufferFormat = D3DFMT_UNKNOWN;
167 present_parameters.hDeviceWindow = desc->device_window;
168 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
169 if (desc->flags & CREATE_DEVICE_LOCKABLE_BACKBUFFER)
170 present_parameters.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
171 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
172 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
173 else if (desc->flags & CREATE_DEVICE_MIXED_ONLY)
174 behavior_flags = D3DCREATE_MIXED_VERTEXPROCESSING;
175 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
176 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
177 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
178 behavior_flags |= D3DCREATE_FPU_PRESERVE;
181 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
182 behavior_flags, &present_parameters, &device)))
183 return device;
185 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
186 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
187 behavior_flags, &present_parameters, &device)))
188 return device;
190 if (desc && (desc->flags & (CREATE_DEVICE_SWVP_ONLY | CREATE_DEVICE_MIXED_ONLY)))
191 return NULL;
192 behavior_flags = (behavior_flags
193 & ~(D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING))
194 | D3DCREATE_HARDWARE_VERTEXPROCESSING;
196 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
197 behavior_flags, &present_parameters, &device)))
198 return device;
200 return NULL;
203 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
205 D3DPRESENT_PARAMETERS present_parameters = {0};
207 present_parameters.BackBufferWidth = 640;
208 present_parameters.BackBufferHeight = 480;
209 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
210 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
211 present_parameters.hDeviceWindow = NULL;
212 present_parameters.Windowed = TRUE;
213 present_parameters.EnableAutoDepthStencil = TRUE;
214 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
216 if (desc)
218 present_parameters.BackBufferWidth = desc->width;
219 present_parameters.BackBufferHeight = desc->height;
220 present_parameters.hDeviceWindow = desc->device_window;
221 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
224 return IDirect3DDevice9_Reset(device, &present_parameters);
227 #define CHECK_CALL(r,c,d,rc) \
228 if (SUCCEEDED(r)) {\
229 int tmp1 = get_refcount( (IUnknown *)d ); \
230 int rc_new = rc; \
231 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
232 } else {\
233 trace("%s failed: %08x\n", c, r); \
236 #define CHECK_RELEASE(obj,d,rc) \
237 if (obj) { \
238 int tmp1, rc_new = rc; \
239 IUnknown_Release( (IUnknown*)obj ); \
240 tmp1 = get_refcount( (IUnknown *)d ); \
241 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
244 #define CHECK_REFCOUNT(obj,rc) \
246 int rc_new = rc; \
247 int count = get_refcount( (IUnknown *)obj ); \
248 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
251 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
253 int rc_new = rc; \
254 int count = IUnknown_Release( (IUnknown *)obj ); \
255 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
258 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
260 int rc_new = rc; \
261 int count = IUnknown_AddRef( (IUnknown *)obj ); \
262 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
265 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
267 void *container_ptr = (void *)0x1337c0d3; \
268 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
269 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
270 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
271 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
274 static void test_get_set_vertex_declaration(void)
276 IDirect3DVertexDeclaration9 *declaration, *tmp;
277 ULONG refcount, expected_refcount;
278 IDirect3DDevice9 *device;
279 IDirect3D9 *d3d;
280 HWND window;
281 HRESULT hr;
283 static const D3DVERTEXELEMENT9 simple_decl[] =
285 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
286 D3DDECL_END()
289 window = create_window();
290 d3d = Direct3DCreate9(D3D_SDK_VERSION);
291 ok(!!d3d, "Failed to create a D3D object.\n");
292 if (!(device = create_device(d3d, window, NULL)))
294 skip("Failed to create a D3D device, skipping tests.\n");
295 goto done;
298 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
299 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
301 /* SetVertexDeclaration() should not touch the declaration's refcount. */
302 expected_refcount = get_refcount((IUnknown *)declaration);
303 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
304 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
305 refcount = get_refcount((IUnknown *)declaration);
306 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
308 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
309 tmp = NULL;
310 expected_refcount = refcount + 1;
311 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
312 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
313 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
314 refcount = get_refcount((IUnknown *)declaration);
315 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
316 IDirect3DVertexDeclaration9_Release(tmp);
318 IDirect3DVertexDeclaration9_Release(declaration);
319 refcount = IDirect3DDevice9_Release(device);
320 ok(!refcount, "Device has %u references left.\n", refcount);
321 done:
322 IDirect3D9_Release(d3d);
323 DestroyWindow(window);
326 static void test_get_declaration(void)
328 unsigned int element_count, expected_element_count;
329 IDirect3DVertexDeclaration9 *declaration;
330 D3DVERTEXELEMENT9 *elements;
331 IDirect3DDevice9 *device;
332 IDirect3D9 *d3d;
333 ULONG refcount;
334 HWND window;
335 HRESULT hr;
337 static const D3DVERTEXELEMENT9 simple_decl[] =
339 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
340 D3DDECL_END()
343 window = create_window();
344 d3d = Direct3DCreate9(D3D_SDK_VERSION);
345 ok(!!d3d, "Failed to create a D3D object.\n");
346 if (!(device = create_device(d3d, window, NULL)))
348 skip("Failed to create a D3D device, skipping tests.\n");
349 goto done;
352 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
353 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
355 /* First test only getting the number of elements. */
356 element_count = 0x1337c0de;
357 expected_element_count = ARRAY_SIZE(simple_decl);
358 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
359 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
360 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
361 element_count, expected_element_count);
363 element_count = 0;
364 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
365 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
366 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
367 element_count, expected_element_count);
369 /* Also test the returned data. */
370 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
372 element_count = 0x1337c0de;
373 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
374 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
375 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
376 element_count, expected_element_count);
377 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
378 "Original and returned vertexdeclarations are not the same.\n");
380 memset(elements, 0, sizeof(simple_decl));
382 element_count = 0;
383 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
384 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
385 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
386 element_count, expected_element_count);
387 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
388 "Original and returned vertexdeclarations are not the same.\n");
390 HeapFree(GetProcessHeap(), 0, elements);
391 IDirect3DVertexDeclaration9_Release(declaration);
392 refcount = IDirect3DDevice9_Release(device);
393 ok(!refcount, "Device has %u references left.\n", refcount);
394 done:
395 IDirect3D9_Release(d3d);
396 DestroyWindow(window);
399 static void test_fvf_decl_conversion(void)
401 IDirect3DVertexDeclaration9 *default_decl;
402 IDirect3DVertexDeclaration9 *declaration;
403 IDirect3DDevice9 *device;
404 IDirect3D9 *d3d;
405 ULONG refcount;
406 unsigned int i;
407 HWND window;
408 HRESULT hr;
410 static const D3DVERTEXELEMENT9 default_elements[] =
412 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
413 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
414 D3DDECL_END()
416 /* Test conversions from vertex declaration to an FVF. For some reason
417 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
418 * forced to 0 - maybe this is configuration specific. */
419 static const struct
421 D3DVERTEXELEMENT9 elements[7];
422 DWORD fvf;
423 BOOL todo;
425 decl_to_fvf_tests[] =
427 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
428 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
429 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
430 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
431 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
432 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
433 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
434 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
435 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
436 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
437 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
438 /* No FVF mapping available. */
439 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
440 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
441 /* Try empty declaration. */
442 {{ D3DDECL_END()}, 0, FALSE},
443 /* Make sure textures of different sizes work. */
444 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
445 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
446 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
447 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
448 /* Make sure the TEXCOORD index works correctly - try several textures. */
451 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
452 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
453 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
454 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
455 D3DDECL_END(),
456 }, 0, FALSE,
458 /* Now try a combination test. */
461 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
462 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
463 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
464 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
465 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
466 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
467 D3DDECL_END(),
468 }, 0, FALSE,
471 /* Test conversions from FVF to a vertex declaration. These seem to always
472 * occur internally. A new declaration object is created if necessary. */
473 static const struct
475 DWORD fvf;
476 D3DVERTEXELEMENT9 elements[7];
478 fvf_to_decl_tests[] =
480 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
481 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
482 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
484 D3DFVF_XYZB5,
486 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
487 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
488 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
489 D3DDECL_END(),
493 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
495 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
496 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
497 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
498 D3DDECL_END(),
502 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
504 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
505 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
506 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
507 D3DDECL_END(),
511 D3DFVF_XYZB1,
513 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
514 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
515 D3DDECL_END(),
519 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
521 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
522 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
523 D3DDECL_END(),
527 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
529 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
530 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
531 D3DDECL_END(),
535 D3DFVF_XYZB2,
537 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
538 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
539 D3DDECL_END(),
543 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
545 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
546 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
547 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
548 D3DDECL_END(),
552 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
554 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
555 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
556 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
557 D3DDECL_END(),
561 D3DFVF_XYZB3,
563 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
564 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
565 D3DDECL_END(),
569 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
571 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
572 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
573 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
574 D3DDECL_END(),
578 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
580 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
581 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
582 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
583 D3DDECL_END(),
587 D3DFVF_XYZB4,
589 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
590 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
591 D3DDECL_END(),
595 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
597 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
598 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
599 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
600 D3DDECL_END(),
604 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
606 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
607 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
608 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
609 D3DDECL_END(),
612 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
613 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
614 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
615 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
616 /* Make sure textures of different sizes work. */
618 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
619 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
622 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
623 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
626 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
627 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
630 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
631 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
633 /* Make sure the TEXCOORD index works correctly - try several textures. */
635 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
636 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
638 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
639 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
640 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
641 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
642 D3DDECL_END(),
645 /* Now try a combination test. */
647 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
648 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
650 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
651 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
652 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
653 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
654 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
655 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
656 D3DDECL_END(),
661 window = create_window();
662 d3d = Direct3DCreate9(D3D_SDK_VERSION);
663 ok(!!d3d, "Failed to create a D3D object.\n");
664 if (!(device = create_device(d3d, window, NULL)))
666 skip("Failed to create a D3D device, skipping tests.\n");
667 goto done;
670 for (i = 0; i < ARRAY_SIZE(decl_to_fvf_tests); ++i)
672 DWORD fvf = 0xdeadbeef;
673 HRESULT hr;
675 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
676 * back to 0. */
677 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
678 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
680 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
681 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
682 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
683 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
685 /* Check the FVF. */
686 hr = IDirect3DDevice9_GetFVF(device, &fvf);
687 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
689 todo_wine_if (decl_to_fvf_tests[i].todo)
690 ok(fvf == decl_to_fvf_tests[i].fvf,
691 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
692 i, fvf, decl_to_fvf_tests[i].fvf);
694 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
695 IDirect3DVertexDeclaration9_Release(declaration);
698 /* Create a default declaration and FVF that does not match any of the
699 * tests. */
700 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
701 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
703 for (i = 0; i < ARRAY_SIZE(fvf_to_decl_tests); ++i)
705 /* Set a default declaration to make sure it is changed. */
706 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
707 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
709 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
710 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
712 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
713 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
714 ok(!!declaration && declaration != default_decl,
715 "Test %u: Got unexpected declaration %p.\n", i, declaration);
716 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
717 "Test %u: Declaration does not match.\n", i);
718 IDirect3DVertexDeclaration9_Release(declaration);
721 /* Setting the FVF to 0 should result in no change to the default decl. */
722 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
723 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
724 hr = IDirect3DDevice9_SetFVF(device, 0);
725 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
726 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
727 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
728 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
729 IDirect3DVertexDeclaration9_Release(declaration);
731 IDirect3DVertexDeclaration9_Release(default_decl);
732 refcount = IDirect3DDevice9_Release(device);
733 ok(!refcount, "Device has %u references left.\n", refcount);
734 done:
735 IDirect3D9_Release(d3d);
736 DestroyWindow(window);
739 /* Check whether a declaration converted from FVF is shared.
740 * Check whether refcounts behave as expected. */
741 static void test_fvf_decl_management(void)
743 IDirect3DVertexDeclaration9 *declaration1;
744 IDirect3DVertexDeclaration9 *declaration2;
745 IDirect3DVertexDeclaration9 *declaration3;
746 IDirect3DVertexDeclaration9 *declaration4;
747 IDirect3DDevice9 *device;
748 IDirect3D9 *d3d;
749 ULONG refcount;
750 HWND window;
751 HRESULT hr;
753 static const D3DVERTEXELEMENT9 test_elements1[] =
754 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
755 static const D3DVERTEXELEMENT9 test_elements2[] =
756 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
758 window = create_window();
759 d3d = Direct3DCreate9(D3D_SDK_VERSION);
760 ok(!!d3d, "Failed to create a D3D object.\n");
761 if (!(device = create_device(d3d, window, NULL)))
763 skip("Failed to create a D3D device, skipping tests.\n");
764 goto done;
767 /* Clear down any current vertex declaration. */
768 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
769 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
770 /* Conversion. */
771 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
772 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
773 /* Get converted decl (#1). */
774 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
775 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
776 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
777 /* Get converted decl again (#2). */
778 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
779 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
780 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
782 /* Conversion. */
783 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
784 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
785 /* Get converted decl (#3). */
786 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
787 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
788 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
789 /* The contents should correspond to the second conversion. */
790 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
791 /* Re-Check if the first decl was overwritten by the new Get(). */
792 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
794 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
795 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
796 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
797 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
798 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
800 refcount = get_refcount((IUnknown*)declaration1);
801 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
802 refcount = get_refcount((IUnknown*)declaration2);
803 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
804 refcount = get_refcount((IUnknown*)declaration3);
805 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
806 refcount = get_refcount((IUnknown*)declaration4);
807 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
809 IDirect3DVertexDeclaration9_Release(declaration4);
810 IDirect3DVertexDeclaration9_Release(declaration3);
811 IDirect3DVertexDeclaration9_Release(declaration2);
812 IDirect3DVertexDeclaration9_Release(declaration1);
814 refcount = IDirect3DDevice9_Release(device);
815 ok(!refcount, "Device has %u references left.\n", refcount);
816 done:
817 IDirect3D9_Release(d3d);
818 DestroyWindow(window);
821 static void test_vertex_declaration_alignment(void)
823 IDirect3DVertexDeclaration9 *declaration;
824 IDirect3DDevice9 *device;
825 IDirect3D9 *d3d;
826 unsigned int i;
827 ULONG refcount;
828 HWND window;
829 HRESULT hr;
831 static const struct
833 D3DVERTEXELEMENT9 elements[3];
834 HRESULT hr;
836 test_data[] =
840 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
841 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
842 D3DDECL_END(),
843 }, D3D_OK,
847 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
848 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
849 D3DDECL_END(),
850 }, E_FAIL,
854 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
855 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
856 D3DDECL_END(),
857 }, E_FAIL,
861 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
862 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
863 D3DDECL_END(),
864 }, E_FAIL,
868 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
869 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
870 D3DDECL_END(),
871 }, D3D_OK,
875 window = create_window();
876 d3d = Direct3DCreate9(D3D_SDK_VERSION);
877 ok(!!d3d, "Failed to create a D3D object.\n");
878 if (!(device = create_device(d3d, window, NULL)))
880 skip("Failed to create a D3D device, skipping tests.\n");
881 goto done;
884 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
886 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
887 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
888 if (SUCCEEDED(hr))
889 IDirect3DVertexDeclaration9_Release(declaration);
892 refcount = IDirect3DDevice9_Release(device);
893 ok(!refcount, "Device has %u references left.\n", refcount);
894 done:
895 IDirect3D9_Release(d3d);
896 DestroyWindow(window);
899 static void test_unused_declaration_type(void)
901 IDirect3DVertexDeclaration9 *declaration;
902 IDirect3DDevice9 *device;
903 IDirect3D9 *d3d;
904 unsigned int i;
905 ULONG refcount;
906 HWND window;
907 HRESULT hr;
909 static const D3DVERTEXELEMENT9 test_elements[][3] =
912 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
913 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
914 D3DDECL_END(),
917 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
918 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
919 D3DDECL_END(),
922 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
923 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
924 D3DDECL_END(),
927 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
928 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
929 D3DDECL_END(),
932 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
933 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
934 D3DDECL_END(),
937 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
938 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
939 D3DDECL_END(),
942 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
943 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
944 D3DDECL_END(),
948 window = create_window();
949 d3d = Direct3DCreate9(D3D_SDK_VERSION);
950 ok(!!d3d, "Failed to create a D3D object.\n");
951 if (!(device = create_device(d3d, window, NULL)))
953 skip("Failed to create a D3D device, skipping tests.\n");
954 goto done;
957 for (i = 0; i < ARRAY_SIZE(test_elements); ++i)
959 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
960 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
963 refcount = IDirect3DDevice9_Release(device);
964 ok(!refcount, "Device has %u references left.\n", refcount);
965 done:
966 IDirect3D9_Release(d3d);
967 DestroyWindow(window);
970 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
972 IDirect3DBaseTexture9* texture = NULL;
973 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
974 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
976 if (SUCCEEDED(hr)) {
977 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
978 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
979 } else
980 trace("CreateTexture failed: %08x\n", hr);
982 if (texture) IDirect3DBaseTexture9_Release( texture );
985 static void test_mipmap_levels(void)
987 IDirect3DDevice9 *device;
988 IDirect3D9 *d3d;
989 ULONG refcount;
990 HWND window;
992 window = create_window();
993 ok(!!window, "Failed to create a window.\n");
994 d3d = Direct3DCreate9(D3D_SDK_VERSION);
995 ok(!!d3d, "Failed to create a D3D object.\n");
996 if (!(device = create_device(d3d, window, NULL)))
998 skip("Failed to create a 3D device, skipping test.\n");
999 goto cleanup;
1002 check_mipmap_levels(device, 32, 32, 6);
1003 check_mipmap_levels(device, 256, 1, 9);
1004 check_mipmap_levels(device, 1, 256, 9);
1005 check_mipmap_levels(device, 1, 1, 1);
1007 refcount = IDirect3DDevice9_Release(device);
1008 ok(!refcount, "Device has %u references left.\n", refcount);
1009 cleanup:
1010 IDirect3D9_Release(d3d);
1011 DestroyWindow(window);
1014 static void test_checkdevicemultisampletype(void)
1016 DWORD quality_levels;
1017 IDirect3D9 *d3d;
1018 HWND window;
1019 HRESULT hr;
1021 window = create_window();
1022 ok(!!window, "Failed to create a window.\n");
1023 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1024 ok(!!d3d, "Failed to create a D3D object.\n");
1026 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1027 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL) == D3DERR_NOTAVAILABLE)
1029 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
1030 goto cleanup;
1033 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1034 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE, NULL);
1035 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1036 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1037 65536, TRUE, D3DMULTISAMPLE_NONE, NULL);
1038 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1040 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1041 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, NULL);
1042 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1044 quality_levels = 0;
1045 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1046 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1047 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1048 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1049 quality_levels = 0;
1050 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1051 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1052 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1053 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1055 quality_levels = 0;
1056 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1057 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, NULL);
1058 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1059 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1060 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels);
1061 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1062 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1064 quality_levels = 0;
1065 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1066 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1067 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1068 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1069 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels);
1070 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1071 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1073 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1074 quality_levels = 0;
1075 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1076 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1077 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1078 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1079 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, &quality_levels);
1080 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1081 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1083 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1084 D3DFMT_X8R8G8B8, TRUE, 65536, NULL);
1085 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1087 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1088 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1089 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1091 cleanup:
1092 IDirect3D9_Release(d3d);
1093 DestroyWindow(window);
1096 static void test_invalid_multisample(void)
1098 IDirect3DDevice9 *device;
1099 IDirect3DSurface9 *rt;
1100 DWORD quality_levels;
1101 IDirect3D9 *d3d;
1102 BOOL available;
1103 ULONG refcount;
1104 HWND window;
1105 HRESULT hr;
1107 window = create_window();
1108 ok(!!window, "Failed to create a window.\n");
1109 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1110 ok(!!d3d, "Failed to create a D3D object.\n");
1112 if (!(device = create_device(d3d, window, NULL)))
1114 skip("Failed to create a 3D device, skipping test.\n");
1115 goto cleanup;
1118 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1119 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels));
1120 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1121 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, 0, FALSE, &rt, NULL);
1122 if (available)
1124 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1125 IDirect3DSurface9_Release(rt);
1126 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1127 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, quality_levels, FALSE, &rt, NULL);
1128 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1130 else
1132 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1135 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1136 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels));
1137 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1138 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &rt, NULL);
1139 if (available)
1141 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1142 IDirect3DSurface9_Release(rt);
1143 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1144 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels, FALSE, &rt, NULL);
1145 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1147 else
1149 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1152 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1153 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1154 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1155 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1156 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1157 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, 0, FALSE, &rt, NULL);
1158 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1160 refcount = IDirect3DDevice9_Release(device);
1161 ok(!refcount, "Device has %u references left.\n", refcount);
1162 cleanup:
1163 IDirect3D9_Release(d3d);
1164 DestroyWindow(window);
1167 static void test_swapchain(void)
1169 IDirect3DSwapChain9 *swapchain0;
1170 IDirect3DSwapChain9 *swapchain1;
1171 IDirect3DSwapChain9 *swapchain2;
1172 IDirect3DSwapChain9 *swapchain3;
1173 IDirect3DSwapChain9 *swapchainX;
1174 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1175 D3DPRESENT_PARAMETERS d3dpp;
1176 IDirect3DDevice9 *device;
1177 IDirect3D9 *d3d;
1178 ULONG refcount;
1179 HWND window, window2;
1180 HRESULT hr;
1181 struct device_desc device_desc;
1183 window = create_window();
1184 ok(!!window, "Failed to create a window.\n");
1185 window2 = create_window();
1186 ok(!!window2, "Failed to create a window.\n");
1187 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1188 ok(!!d3d, "Failed to create a D3D object.\n");
1189 if (!(device = create_device(d3d, window, NULL)))
1191 skip("Failed to create a 3D device, skipping test.\n");
1192 goto cleanup;
1195 /* Get the implicit swapchain */
1196 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1197 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1198 /* Check if the back buffer count was modified */
1199 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1200 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1201 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1202 IDirect3DSwapChain9_Release(swapchain0);
1204 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1205 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1206 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1207 backbuffer = (void *)0xdeadbeef;
1208 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1209 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1210 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1211 backbuffer = (void *)0xdeadbeef;
1212 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1213 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1214 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1216 /* Check if there is a back buffer */
1217 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1218 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1219 ok(backbuffer != NULL, "The back buffer is NULL\n");
1220 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1222 /* The back buffer type value is ignored. */
1223 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1224 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1225 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1226 IDirect3DSurface9_Release(stereo_buffer);
1227 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1228 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1229 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1230 IDirect3DSurface9_Release(stereo_buffer);
1231 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1232 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1233 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1234 IDirect3DSurface9_Release(stereo_buffer);
1236 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1237 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1238 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1239 IDirect3DSurface9_Release(stereo_buffer);
1240 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1241 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1242 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1243 IDirect3DSurface9_Release(stereo_buffer);
1244 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1245 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1246 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1247 IDirect3DSurface9_Release(stereo_buffer);
1249 /* Try to get a nonexistent swapchain */
1250 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1251 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1252 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1253 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1255 /* Create a bunch of swapchains */
1256 d3dpp.BackBufferCount = 0;
1257 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1258 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1259 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1261 d3dpp.BackBufferCount = 1;
1262 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1263 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1265 d3dpp.BackBufferCount = 2;
1266 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1267 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1268 if(SUCCEEDED(hr)) {
1269 /* Swapchain 3, created with backbuffercount 2 */
1270 backbuffer = (void *) 0xdeadbeef;
1271 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1272 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1273 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1274 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1276 backbuffer = (void *) 0xdeadbeef;
1277 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1278 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1279 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1280 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1282 backbuffer = (void *) 0xdeadbeef;
1283 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1284 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1285 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1286 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1288 backbuffer = (void *) 0xdeadbeef;
1289 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1290 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1291 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1292 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1295 /* Check the back buffers of the swapchains */
1296 /* Swapchain 1, created with backbuffercount 0 */
1297 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1298 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1299 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1300 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1302 backbuffer = (void *) 0xdeadbeef;
1303 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1304 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1305 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1306 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1308 /* Swapchain 2 - created with backbuffercount 1 */
1309 backbuffer = (void *) 0xdeadbeef;
1310 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1311 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1312 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1313 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1315 backbuffer = (void *) 0xdeadbeef;
1316 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1317 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1318 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1319 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1321 backbuffer = (void *) 0xdeadbeef;
1322 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1323 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1324 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1325 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1327 /* Try getSwapChain on a manually created swapchain
1328 * it should fail, apparently GetSwapChain only returns implicit swapchains
1330 swapchainX = (void *) 0xdeadbeef;
1331 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1332 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1333 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1334 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1336 IDirect3DSwapChain9_Release(swapchain3);
1337 IDirect3DSwapChain9_Release(swapchain2);
1338 IDirect3DSwapChain9_Release(swapchain1);
1340 d3dpp.Windowed = FALSE;
1341 d3dpp.hDeviceWindow = window;
1342 d3dpp.BackBufferCount = 1;
1343 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1344 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1345 d3dpp.hDeviceWindow = window2;
1346 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1347 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1349 device_desc.width = registry_mode.dmPelsWidth;
1350 device_desc.height = registry_mode.dmPelsHeight;
1351 device_desc.device_window = window;
1352 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1353 hr = reset_device(device, &device_desc);
1354 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1356 d3dpp.hDeviceWindow = window;
1357 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1358 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1359 d3dpp.hDeviceWindow = window2;
1360 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1361 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1362 d3dpp.Windowed = TRUE;
1363 d3dpp.hDeviceWindow = window;
1364 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1365 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1366 d3dpp.hDeviceWindow = window2;
1367 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1368 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1370 refcount = IDirect3DDevice9_Release(device);
1371 ok(!refcount, "Device has %u references left.\n", refcount);
1372 cleanup:
1373 IDirect3D9_Release(d3d);
1374 DestroyWindow(window2);
1375 DestroyWindow(window);
1378 static void test_refcount(void)
1380 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1381 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1382 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1383 IDirect3DVertexShader9 *pVertexShader = NULL;
1384 IDirect3DPixelShader9 *pPixelShader = NULL;
1385 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1386 IDirect3DTexture9 *pTexture = NULL;
1387 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1388 IDirect3DVolume9 *pVolumeLevel = NULL;
1389 IDirect3DSurface9 *pStencilSurface = NULL;
1390 IDirect3DSurface9 *pOffscreenSurface = NULL;
1391 IDirect3DSurface9 *pRenderTarget = NULL;
1392 IDirect3DSurface9 *pRenderTarget2 = NULL;
1393 IDirect3DSurface9 *pRenderTarget3 = NULL;
1394 IDirect3DSurface9 *pTextureLevel = NULL;
1395 IDirect3DSurface9 *pBackBuffer = NULL;
1396 IDirect3DStateBlock9 *pStateBlock = NULL;
1397 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1398 IDirect3DSwapChain9 *pSwapChain = NULL;
1399 IDirect3DQuery9 *pQuery = NULL;
1400 D3DPRESENT_PARAMETERS d3dpp;
1401 IDirect3DDevice9 *device;
1402 ULONG refcount = 0, tmp;
1403 IDirect3D9 *d3d, *d3d2;
1404 HWND window;
1405 HRESULT hr;
1407 D3DVERTEXELEMENT9 decl[] =
1409 D3DDECL_END()
1412 window = create_window();
1413 ok(!!window, "Failed to create a window.\n");
1414 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1415 ok(!!d3d, "Failed to create a D3D object.\n");
1417 CHECK_REFCOUNT(d3d, 1);
1419 if (!(device = create_device(d3d, window, NULL)))
1421 skip("Failed to create a 3D device, skipping test.\n");
1422 goto cleanup;
1425 refcount = get_refcount((IUnknown *)device);
1426 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1428 CHECK_REFCOUNT(d3d, 2);
1430 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1431 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1433 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1434 CHECK_REFCOUNT(d3d, 3);
1435 CHECK_RELEASE_REFCOUNT(d3d, 2);
1438 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1439 * - the container is the device OR swapchain
1440 * - they hold a reference to the device
1441 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1442 * - they are not freed if refcount reaches 0.
1443 * - the refcount is not forwarded to the container.
1445 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1446 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1447 if (pSwapChain)
1449 CHECK_REFCOUNT(pSwapChain, 1);
1451 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1452 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1453 CHECK_REFCOUNT(pSwapChain, 1);
1454 if (pRenderTarget)
1456 CHECK_SURFACE_CONTAINER(pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1457 CHECK_REFCOUNT(pRenderTarget, 1);
1459 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1460 CHECK_REFCOUNT(device, refcount);
1461 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1462 CHECK_REFCOUNT(device, refcount);
1464 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1465 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1466 CHECK_REFCOUNT(pRenderTarget, 2);
1467 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1468 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1469 CHECK_REFCOUNT(device, --refcount);
1471 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1472 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1473 CHECK_REFCOUNT(device, ++refcount);
1474 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1475 CHECK_REFCOUNT(device, --refcount);
1476 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1477 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1480 /* Render target and back buffer are identical. */
1481 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1482 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1483 if (pBackBuffer)
1485 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1486 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1487 pRenderTarget, pBackBuffer);
1488 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1489 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1490 pBackBuffer = NULL;
1492 CHECK_REFCOUNT(device, --refcount);
1494 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1495 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1496 CHECK_REFCOUNT(pSwapChain, 1);
1497 if (pStencilSurface)
1499 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1500 CHECK_REFCOUNT( pStencilSurface, 1);
1502 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1503 CHECK_REFCOUNT(device, refcount);
1504 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1505 CHECK_REFCOUNT(device, refcount);
1507 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1508 CHECK_REFCOUNT(device, --refcount);
1510 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1511 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1512 CHECK_REFCOUNT(device, ++refcount);
1513 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1514 CHECK_REFCOUNT(device, --refcount);
1515 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1516 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1517 pStencilSurface = NULL;
1520 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1521 CHECK_REFCOUNT(device, --refcount);
1522 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1523 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1525 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1526 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1527 CHECK_REFCOUNT(device, ++refcount);
1528 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1529 CHECK_REFCOUNT(device, --refcount);
1530 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1531 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1532 pSwapChain = NULL;
1535 /* Buffers */
1536 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1537 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1538 if(pIndexBuffer)
1540 tmp = get_refcount((IUnknown *)pIndexBuffer);
1542 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1543 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1544 hr = IDirect3DDevice9_SetIndices(device, NULL);
1545 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1548 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1549 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1550 if(pVertexBuffer)
1552 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1553 UINT offset = ~0;
1554 UINT stride = ~0;
1556 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1558 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1559 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1560 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1561 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1563 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1564 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1565 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1566 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1567 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1569 /* Shaders */
1570 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1571 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1572 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1573 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1574 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1575 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1576 /* Textures */
1577 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1578 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1579 if (pTexture)
1581 tmp = get_refcount( (IUnknown *)pTexture );
1583 /* SetTexture should not increase refcounts */
1584 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1585 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1586 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1587 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1589 /* This should not increment device refcount */
1590 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1591 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1592 /* But should increment texture's refcount */
1593 CHECK_REFCOUNT( pTexture, tmp+1 );
1594 /* Because the texture and surface refcount are identical */
1595 if (pTextureLevel)
1597 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1598 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1599 CHECK_REFCOUNT ( pTexture , tmp+2 );
1600 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1601 CHECK_REFCOUNT ( pTexture , tmp+1 );
1602 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1603 CHECK_REFCOUNT ( pTextureLevel, tmp );
1606 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1607 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1608 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1609 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1610 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1611 if (pVolumeTexture)
1613 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1615 /* This should not increment device refcount */
1616 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1617 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1618 /* But should increment volume texture's refcount */
1619 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1620 /* Because the volume texture and volume refcount are identical */
1621 if (pVolumeLevel)
1623 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1624 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1625 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1626 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1627 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1628 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1629 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1632 /* Surfaces */
1633 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1634 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1635 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1636 CHECK_REFCOUNT( pStencilSurface, 1 );
1637 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1638 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1639 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1640 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1641 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1642 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1643 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1644 CHECK_REFCOUNT( pRenderTarget3, 1 );
1645 /* Misc */
1646 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1647 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1649 memset(&d3dpp, 0, sizeof(d3dpp));
1650 d3dpp.Windowed = TRUE;
1651 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1652 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1653 d3dpp.EnableAutoDepthStencil = TRUE;
1654 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1655 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1656 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1657 if (pSwapChain)
1659 /* check implicit back buffer */
1660 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1661 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1662 CHECK_REFCOUNT(pSwapChain, 1);
1663 if (pBackBuffer)
1665 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1666 CHECK_REFCOUNT(pBackBuffer, 1);
1667 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1668 CHECK_REFCOUNT(device, --refcount);
1670 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1671 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1672 CHECK_REFCOUNT(device, ++refcount);
1673 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1674 CHECK_REFCOUNT(device, --refcount);
1675 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1676 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1677 pBackBuffer = NULL;
1679 CHECK_REFCOUNT(pSwapChain, 1);
1681 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1682 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1684 hr = IDirect3DDevice9_BeginStateBlock(device);
1685 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1686 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1687 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1689 /* The implicit render target is not freed if refcount reaches 0.
1690 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1691 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1692 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1693 if (pRenderTarget2)
1695 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1696 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1697 pRenderTarget, pRenderTarget2);
1698 CHECK_REFCOUNT(device, --refcount);
1699 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1700 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1701 pRenderTarget2 = NULL;
1703 pRenderTarget = NULL;
1705 cleanup:
1706 CHECK_RELEASE(device, device, --refcount);
1708 /* Buffers */
1709 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1710 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1711 /* Shaders */
1712 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1713 CHECK_RELEASE(pVertexShader, device, --refcount);
1714 CHECK_RELEASE(pPixelShader, device, --refcount);
1715 /* Textures */
1716 CHECK_RELEASE(pTextureLevel, device, --refcount);
1717 CHECK_RELEASE(pCubeTexture, device, --refcount);
1718 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1719 /* Surfaces */
1720 CHECK_RELEASE(pStencilSurface, device, --refcount);
1721 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1722 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1723 /* Misc */
1724 CHECK_RELEASE(pStateBlock, device, --refcount);
1725 CHECK_RELEASE(pSwapChain, device, --refcount);
1726 CHECK_RELEASE(pQuery, device, --refcount);
1727 /* This will destroy device - cannot check the refcount here */
1728 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1729 CHECK_RELEASE_REFCOUNT(d3d, 0);
1730 DestroyWindow(window);
1733 static void test_cursor(void)
1735 IDirect3DSurface9 *cursor = NULL;
1736 IDirect3DDevice9 *device;
1737 CURSORINFO info;
1738 IDirect3D9 *d3d;
1739 ULONG refcount;
1740 HCURSOR cur;
1741 HWND window;
1742 HRESULT hr;
1743 BOOL ret;
1745 window = create_window();
1746 ok(!!window, "Failed to create a window.\n");
1748 ret = SetCursorPos(50, 50);
1749 ok(ret, "Failed to set cursor position.\n");
1750 flush_events();
1751 memset(&info, 0, sizeof(info));
1752 info.cbSize = sizeof(info);
1753 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1754 cur = info.hCursor;
1756 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1757 ok(!!d3d, "Failed to create a D3D object.\n");
1758 if (!(device = create_device(d3d, window, NULL)))
1760 skip("Failed to create a 3D device, skipping test.\n");
1761 goto cleanup;
1764 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1765 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1766 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1768 /* Initially hidden */
1769 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1770 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1772 /* Not enabled without a surface*/
1773 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1774 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1776 /* Fails */
1777 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1778 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1780 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1781 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1783 IDirect3DSurface9_Release(cursor);
1785 memset(&info, 0, sizeof(info));
1786 info.cbSize = sizeof(info);
1787 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1788 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1789 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1791 /* Still hidden */
1792 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1793 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1795 /* Enabled now*/
1796 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1797 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1799 memset(&info, 0, sizeof(info));
1800 info.cbSize = sizeof(info);
1801 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1802 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1803 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1805 refcount = IDirect3DDevice9_Release(device);
1806 ok(!refcount, "Device has %u references left.\n", refcount);
1807 cleanup:
1808 IDirect3D9_Release(d3d);
1809 DestroyWindow(window);
1812 static void test_reset(void)
1814 HRESULT hr;
1815 RECT winrect, client_rect;
1816 D3DPRESENT_PARAMETERS d3dpp;
1817 D3DDISPLAYMODE d3ddm, d3ddm2;
1818 D3DVIEWPORT9 vp;
1819 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1820 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1821 IDirect3DSurface9 *surface;
1822 IDirect3DTexture9 *texture;
1823 IDirect3DVertexShader9 *shader;
1824 UINT i, adapter_mode_count;
1825 D3DLOCKED_RECT lockrect;
1826 IDirect3DDevice9 *device1 = NULL;
1827 IDirect3DDevice9 *device2 = NULL;
1828 IDirect3DSwapChain9 *swapchain;
1829 struct device_desc device_desc;
1830 DEVMODEW devmode;
1831 IDirect3D9 *d3d;
1832 D3DCAPS9 caps;
1833 DWORD value;
1834 HWND hwnd;
1835 LONG ret;
1836 struct
1838 UINT w;
1839 UINT h;
1840 } *modes = NULL;
1841 UINT mode_count = 0;
1843 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1844 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1845 ok(!!hwnd, "Failed to create a window.\n");
1846 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1847 ok(!!d3d, "Failed to create a D3D object.\n");
1849 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1850 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1851 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1852 for(i = 0; i < adapter_mode_count; ++i)
1854 UINT j;
1855 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1856 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1857 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1859 for (j = 0; j < mode_count; ++j)
1861 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1862 break;
1864 if (j == mode_count)
1866 modes[j].w = d3ddm2.Width;
1867 modes[j].h = d3ddm2.Height;
1868 ++mode_count;
1871 /* We use them as invalid modes */
1872 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1873 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1874 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1875 d3ddm2.Width, d3ddm2.Height);
1876 goto cleanup;
1880 if (mode_count < 2)
1882 skip("Less than 2 modes supported, skipping mode tests\n");
1883 goto cleanup;
1886 i = 0;
1887 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1889 device_desc.width = modes[i].w;
1890 device_desc.height = modes[i].h;
1891 device_desc.device_window = hwnd;
1892 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1893 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1895 skip("Failed to create a D3D device, skipping tests.\n");
1896 goto cleanup;
1898 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1899 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1901 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1902 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1904 width = GetSystemMetrics(SM_CXSCREEN);
1905 height = GetSystemMetrics(SM_CYSCREEN);
1906 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1907 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1909 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1910 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1911 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1912 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1913 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1914 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1915 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1916 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1918 i = 1;
1919 vp.X = 10;
1920 vp.Y = 20;
1921 vp.MinZ = 2;
1922 vp.MaxZ = 3;
1923 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1924 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1926 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1927 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1928 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1929 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1930 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1932 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1933 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1934 d3dpp.Windowed = FALSE;
1935 d3dpp.BackBufferWidth = modes[i].w;
1936 d3dpp.BackBufferHeight = modes[i].h;
1937 d3dpp.BackBufferFormat = d3ddm.Format;
1938 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1939 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1940 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1941 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1943 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1944 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1945 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1947 ZeroMemory(&vp, sizeof(vp));
1948 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1949 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1950 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1951 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1952 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1953 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1954 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1955 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1957 width = GetSystemMetrics(SM_CXSCREEN);
1958 height = GetSystemMetrics(SM_CYSCREEN);
1959 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1960 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1962 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1963 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1964 memset(&d3dpp, 0, sizeof(d3dpp));
1965 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1966 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1967 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1968 d3dpp.BackBufferWidth, modes[i].w);
1969 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1970 d3dpp.BackBufferHeight, modes[i].h);
1971 IDirect3DSwapChain9_Release(swapchain);
1973 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1974 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1975 d3dpp.Windowed = TRUE;
1976 d3dpp.BackBufferWidth = 400;
1977 d3dpp.BackBufferHeight = 300;
1978 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1979 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1980 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1981 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1982 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1984 width = GetSystemMetrics(SM_CXSCREEN);
1985 height = GetSystemMetrics(SM_CYSCREEN);
1986 ok(width == orig_width, "Screen width is %d\n", width);
1987 ok(height == orig_height, "Screen height is %d\n", height);
1989 ZeroMemory(&vp, sizeof(vp));
1990 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1991 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1992 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1993 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1994 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1995 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1996 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1997 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1999 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2000 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2001 memset(&d3dpp, 0, sizeof(d3dpp));
2002 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2003 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2004 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2005 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2006 IDirect3DSwapChain9_Release(swapchain);
2008 memset(&devmode, 0, sizeof(devmode));
2009 devmode.dmSize = sizeof(devmode);
2010 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2011 devmode.dmPelsWidth = modes[1].w;
2012 devmode.dmPelsHeight = modes[1].h;
2013 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2014 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2015 width = GetSystemMetrics(SM_CXSCREEN);
2016 height = GetSystemMetrics(SM_CYSCREEN);
2017 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2018 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2020 d3dpp.BackBufferWidth = 500;
2021 d3dpp.BackBufferHeight = 400;
2022 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
2023 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2024 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed, hr %#x.\n", hr);
2025 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2026 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x.\n", hr);
2028 width = GetSystemMetrics(SM_CXSCREEN);
2029 height = GetSystemMetrics(SM_CYSCREEN);
2030 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2031 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2033 ZeroMemory(&vp, sizeof(vp));
2034 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2035 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed, hr %#x.\n", hr);
2036 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
2037 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
2038 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
2039 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
2040 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
2041 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
2043 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2044 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2045 memset(&d3dpp, 0, sizeof(d3dpp));
2046 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2047 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2048 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2049 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2050 IDirect3DSwapChain9_Release(swapchain);
2052 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2053 devmode.dmPelsWidth = orig_width;
2054 devmode.dmPelsHeight = orig_height;
2055 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2056 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2057 width = GetSystemMetrics(SM_CXSCREEN);
2058 height = GetSystemMetrics(SM_CYSCREEN);
2059 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
2060 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
2062 SetRect(&winrect, 0, 0, 200, 150);
2063 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
2064 ok(SetWindowPos(hwnd, NULL, 0, 0,
2065 winrect.right-winrect.left,
2066 winrect.bottom-winrect.top,
2067 SWP_NOMOVE|SWP_NOZORDER),
2068 "SetWindowPos failed\n");
2070 /* Windows 10 gives us a different size than we requested with some DPI scaling settings (e.g. 172%). */
2071 GetClientRect(hwnd, &client_rect);
2073 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2074 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2075 d3dpp.Windowed = TRUE;
2076 d3dpp.BackBufferWidth = 0;
2077 d3dpp.BackBufferHeight = 0;
2078 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
2079 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2080 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2081 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2082 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2084 ok(d3dpp.BackBufferWidth == client_rect.right, "Got unexpected BackBufferWidth %u, expected %d.\n",
2085 d3dpp.BackBufferWidth, client_rect.right);
2086 ok(d3dpp.BackBufferHeight == client_rect.bottom, "Got unexpected BackBufferHeight %u, expected %d.\n",
2087 d3dpp.BackBufferHeight, client_rect.bottom);
2088 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2089 d3dpp.BackBufferFormat, d3ddm.Format);
2090 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2091 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2092 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2093 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2094 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
2095 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2096 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2097 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2098 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2099 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2100 d3dpp.FullScreen_RefreshRateInHz);
2101 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2103 ZeroMemory(&vp, sizeof(vp));
2104 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2105 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
2106 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
2107 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
2108 ok(vp.Width == client_rect.right, "D3DVIEWPORT->Width = %d, expected %d\n",
2109 vp.Width, client_rect.right);
2110 ok(vp.Height == client_rect.bottom, "D3DVIEWPORT->Height = %d, expected %d\n",
2111 vp.Height, client_rect.bottom);
2112 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2113 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2115 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2116 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2117 memset(&d3dpp, 0, sizeof(d3dpp));
2118 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2119 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2120 ok(d3dpp.BackBufferWidth == client_rect.right,
2121 "Got unexpected BackBufferWidth %u, expected %d.\n", d3dpp.BackBufferWidth, client_rect.right);
2122 ok(d3dpp.BackBufferHeight == client_rect.bottom,
2123 "Got unexpected BackBufferHeight %u, expected %d.\n", d3dpp.BackBufferHeight, client_rect.bottom);
2124 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2125 d3dpp.BackBufferFormat, d3ddm.Format);
2126 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2127 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2128 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2129 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2130 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
2131 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2132 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2133 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2134 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2135 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2136 d3dpp.FullScreen_RefreshRateInHz);
2137 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2138 IDirect3DSwapChain9_Release(swapchain);
2140 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2141 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2142 d3dpp.Windowed = TRUE;
2143 d3dpp.BackBufferWidth = 400;
2144 d3dpp.BackBufferHeight = 300;
2146 /* _Reset fails if there is a resource in the default pool */
2147 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
2148 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2149 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2150 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2151 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2152 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2153 IDirect3DSurface9_Release(surface);
2154 /* Reset again to get the device out of the lost state */
2155 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2156 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2157 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2158 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2160 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
2162 IDirect3DVolumeTexture9 *volume_texture;
2164 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
2165 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
2166 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
2167 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2168 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2169 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2170 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
2171 hr, D3DERR_DEVICENOTRESET);
2172 IDirect3DVolumeTexture9_Release(volume_texture);
2173 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2174 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
2175 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2176 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2178 else
2180 skip("Volume textures not supported.\n");
2183 /* Scratch, sysmem and managed pools are fine */
2184 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2185 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2186 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2187 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2188 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2189 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2190 IDirect3DSurface9_Release(surface);
2192 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2193 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2194 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2195 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2196 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2197 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2198 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2199 IDirect3DSurface9_Release(surface);
2201 /* The depth stencil should get reset to the auto depth stencil when present. */
2202 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2203 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2205 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2206 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2207 ok(surface == NULL, "Depth stencil should be NULL\n");
2209 d3dpp.EnableAutoDepthStencil = TRUE;
2210 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2211 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2212 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2214 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2215 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2216 ok(surface != NULL, "Depth stencil should not be NULL\n");
2217 if (surface) IDirect3DSurface9_Release(surface);
2219 d3dpp.EnableAutoDepthStencil = FALSE;
2220 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2221 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2223 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2224 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2225 ok(surface == NULL, "Depth stencil should be NULL\n");
2227 /* Will a sysmem or scratch survive while locked */
2228 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2229 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2230 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2231 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2232 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2233 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2234 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2235 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2236 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2237 IDirect3DSurface9_UnlockRect(surface);
2238 IDirect3DSurface9_Release(surface);
2240 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2241 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2242 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2243 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2244 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2245 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2246 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2247 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2248 IDirect3DSurface9_UnlockRect(surface);
2249 IDirect3DSurface9_Release(surface);
2251 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2252 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2253 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2254 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2255 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2256 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2257 IDirect3DTexture9_Release(texture);
2259 /* A reference held to an implicit surface causes failures as well */
2260 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2261 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2262 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2263 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2264 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2265 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2266 IDirect3DSurface9_Release(surface);
2267 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2268 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2269 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2270 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2272 /* Shaders are fine as well */
2273 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2274 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2275 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2276 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2277 IDirect3DVertexShader9_Release(shader);
2279 /* Try setting invalid modes */
2280 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2281 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2282 d3dpp.Windowed = FALSE;
2283 d3dpp.BackBufferWidth = 32;
2284 d3dpp.BackBufferHeight = 32;
2285 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2286 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2287 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2288 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2290 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2291 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2292 d3dpp.Windowed = FALSE;
2293 d3dpp.BackBufferWidth = 801;
2294 d3dpp.BackBufferHeight = 600;
2295 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2296 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2297 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2298 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2300 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2301 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2302 d3dpp.Windowed = FALSE;
2303 d3dpp.BackBufferWidth = 0;
2304 d3dpp.BackBufferHeight = 0;
2305 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2306 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2307 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2308 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2310 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2312 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2313 d3dpp.Windowed = TRUE;
2314 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2315 d3dpp.BackBufferFormat = d3ddm.Format;
2316 d3dpp.EnableAutoDepthStencil = FALSE;
2317 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2319 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2320 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2322 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2323 goto cleanup;
2326 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2327 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2329 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2330 d3dpp.Windowed = TRUE;
2331 d3dpp.BackBufferWidth = 400;
2332 d3dpp.BackBufferHeight = 300;
2333 d3dpp.EnableAutoDepthStencil = TRUE;
2334 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2336 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2337 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2339 if (FAILED(hr)) goto cleanup;
2341 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2342 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2343 ok(surface != NULL, "Depth stencil should not be NULL\n");
2344 if (surface) IDirect3DSurface9_Release(surface);
2346 cleanup:
2347 HeapFree(GetProcessHeap(), 0, modes);
2348 if (device2)
2350 UINT refcount = IDirect3DDevice9_Release(device2);
2351 ok(!refcount, "Device has %u references left.\n", refcount);
2353 if (device1)
2355 UINT refcount = IDirect3DDevice9_Release(device1);
2356 ok(!refcount, "Device has %u references left.\n", refcount);
2358 IDirect3D9_Release(d3d);
2359 DestroyWindow(hwnd);
2362 /* Test adapter display modes */
2363 static void test_display_modes(void)
2365 D3DDISPLAYMODE dmode;
2366 IDirect3D9 *d3d;
2368 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2369 ok(!!d3d, "Failed to create a D3D object.\n");
2371 #define TEST_FMT(x,r) do { \
2372 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2373 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2374 } while(0)
2376 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2377 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2378 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2379 /* D3DFMT_R5G6B5 */
2380 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2381 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2382 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2383 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2384 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2385 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2386 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2387 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2388 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2389 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2390 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2391 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2393 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2394 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2396 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2397 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2398 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2400 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2401 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2402 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2403 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2404 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2405 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2407 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2408 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2409 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2410 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2411 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2412 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2413 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2414 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2415 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2416 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2418 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2419 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2420 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2421 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2422 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2423 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2424 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2425 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2426 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2427 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2429 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2430 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2431 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2432 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2433 /* Floating point formats */
2434 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2435 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2436 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2438 /* IEEE formats */
2439 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2440 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2441 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2443 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2445 TEST_FMT(0, D3DERR_INVALIDCALL);
2447 IDirect3D9_Release(d3d);
2450 static void test_scene(void)
2452 IDirect3DSurface9 *surface1, *surface2, *surface3;
2453 IDirect3DSurface9 *backBuffer, *rt, *ds;
2454 RECT rect = {0, 0, 128, 128};
2455 IDirect3DDevice9 *device;
2456 IDirect3D9 *d3d;
2457 ULONG refcount;
2458 D3DCAPS9 caps;
2459 HWND window;
2460 HRESULT hr;
2462 window = create_window();
2463 ok(!!window, "Failed to create a window.\n");
2464 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2465 ok(!!d3d, "Failed to create a D3D object.\n");
2466 if (!(device = create_device(d3d, window, NULL)))
2468 skip("Failed to create a 3D device, skipping test.\n");
2469 goto cleanup;
2472 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2473 memset(&caps, 0, sizeof(caps));
2474 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2475 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2477 /* Test an EndScene without BeginScene. Should return an error */
2478 hr = IDirect3DDevice9_EndScene(device);
2479 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2481 /* Test a normal BeginScene / EndScene pair, this should work */
2482 hr = IDirect3DDevice9_BeginScene(device);
2483 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2484 hr = IDirect3DDevice9_EndScene(device);
2485 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2487 /* Test another EndScene without having begun a new scene. Should return an error */
2488 hr = IDirect3DDevice9_EndScene(device);
2489 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2491 /* Two nested BeginScene and EndScene calls */
2492 hr = IDirect3DDevice9_BeginScene(device);
2493 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2494 hr = IDirect3DDevice9_BeginScene(device);
2495 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2496 hr = IDirect3DDevice9_EndScene(device);
2497 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2498 hr = IDirect3DDevice9_EndScene(device);
2499 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2501 /* Create some surfaces to test stretchrect between the scenes */
2502 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2503 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2504 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2505 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2506 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2507 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2508 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2509 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2510 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2511 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2512 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2513 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2515 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2516 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2517 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2518 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2520 /* First make sure a simple StretchRect call works */
2521 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2522 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2523 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2524 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2525 if (0) /* Disabled for now because it crashes in wine */
2527 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2528 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2529 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2532 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2533 * BeginScene - Endscene pair with normal surfaces and render targets, but
2534 * not depth stencil surfaces. */
2535 hr = IDirect3DDevice9_BeginScene(device);
2536 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2538 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2539 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2540 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2541 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2542 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2543 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2544 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2546 hr = IDirect3DDevice9_EndScene(device);
2547 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2549 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2550 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2551 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2553 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2554 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2555 hr = IDirect3DDevice9_BeginScene(device);
2556 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2557 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2558 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2559 hr = IDirect3DDevice9_EndScene(device);
2560 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2562 IDirect3DSurface9_Release(rt);
2563 IDirect3DSurface9_Release(ds);
2564 IDirect3DSurface9_Release(backBuffer);
2565 IDirect3DSurface9_Release(surface1);
2566 IDirect3DSurface9_Release(surface2);
2567 IDirect3DSurface9_Release(surface3);
2568 refcount = IDirect3DDevice9_Release(device);
2569 ok(!refcount, "Device has %u references left.\n", refcount);
2570 cleanup:
2571 IDirect3D9_Release(d3d);
2572 DestroyWindow(window);
2575 static void test_limits(void)
2577 IDirect3DTexture9 *texture;
2578 IDirect3DDevice9 *device;
2579 IDirect3D9 *d3d;
2580 unsigned int i;
2581 ULONG refcount;
2582 HWND window;
2583 HRESULT hr;
2585 window = create_window();
2586 ok(!!window, "Failed to create a window.\n");
2587 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2588 ok(!!d3d, "Failed to create a D3D object.\n");
2589 if (!(device = create_device(d3d, window, NULL)))
2591 skip("Failed to create a 3D device, skipping test.\n");
2592 goto cleanup;
2595 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2596 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2598 /* There are 16 pixel samplers. We should be able to access all of them */
2599 for (i = 0; i < 16; ++i)
2601 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2602 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2603 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2604 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2605 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2606 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2609 /* Now test all 8 textures stage states */
2610 for (i = 0; i < 8; ++i)
2612 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2613 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2616 /* Investigations show that accessing higher samplers / textures stage
2617 * states does not return an error either. Writing to too high samplers
2618 * (approximately sampler 40) causes memory corruption in Windows, so
2619 * there is no bounds checking. */
2620 IDirect3DTexture9_Release(texture);
2621 refcount = IDirect3D9_Release(device);
2622 ok(!refcount, "Device has %u references left.\n", refcount);
2623 cleanup:
2624 IDirect3D9_Release(d3d);
2625 DestroyWindow(window);
2628 static void test_depthstenciltest(void)
2630 HRESULT hr;
2631 IDirect3DDevice9 *pDevice = NULL;
2632 D3DPRESENT_PARAMETERS d3dpp;
2633 D3DDISPLAYMODE d3ddm;
2634 IDirect3DSurface9 *pDepthStencil = NULL;
2635 IDirect3DSurface9 *pDepthStencil2 = NULL;
2636 IDirect3D9 *d3d;
2637 DWORD state;
2638 HWND hwnd;
2640 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2641 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2642 ok(!!hwnd, "Failed to create a window.\n");
2643 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2644 ok(!!d3d, "Failed to create a D3D object.\n");
2646 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2647 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2648 d3dpp.Windowed = TRUE;
2649 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2650 d3dpp.BackBufferWidth = 800;
2651 d3dpp.BackBufferHeight = 600;
2652 d3dpp.BackBufferFormat = d3ddm.Format;
2653 d3dpp.EnableAutoDepthStencil = TRUE;
2654 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2656 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2657 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2658 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2659 if(!pDevice)
2661 skip("Failed to create a d3d device\n");
2662 goto cleanup;
2665 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2666 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2668 /* Try to clear */
2669 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2670 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2672 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2673 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2675 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2676 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2677 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2678 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2680 /* This left the render states untouched! */
2681 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2682 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2683 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2684 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2685 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2686 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2687 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2688 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2689 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2690 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2691 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2692 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2694 /* This is supposed to fail now */
2695 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2696 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2698 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2699 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2701 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2702 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2704 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2705 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2706 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2708 /* Now it works again */
2709 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2710 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2712 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2713 if(pDevice) IDirect3D9_Release(pDevice);
2715 /* Now see if autodepthstencil disable is honored. First, without a format set */
2716 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2717 d3dpp.Windowed = TRUE;
2718 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2719 d3dpp.BackBufferWidth = 800;
2720 d3dpp.BackBufferHeight = 600;
2721 d3dpp.BackBufferFormat = d3ddm.Format;
2722 d3dpp.EnableAutoDepthStencil = FALSE;
2723 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2725 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2726 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2727 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2728 if(!pDevice)
2730 skip("Failed to create a d3d device\n");
2731 goto cleanup;
2734 pDepthStencil = NULL;
2735 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2736 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2737 if(pDepthStencil) {
2738 IDirect3DSurface9_Release(pDepthStencil);
2739 pDepthStencil = NULL;
2742 /* Check the depth test state */
2743 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2744 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2745 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2747 if(pDevice) IDirect3D9_Release(pDevice);
2749 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2750 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2751 d3dpp.Windowed = TRUE;
2752 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2753 d3dpp.BackBufferWidth = 800;
2754 d3dpp.BackBufferHeight = 600;
2755 d3dpp.BackBufferFormat = d3ddm.Format;
2756 d3dpp.EnableAutoDepthStencil = FALSE;
2757 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2759 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2760 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2761 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2762 if(!pDevice)
2764 skip("Failed to create a d3d device\n");
2765 goto cleanup;
2768 pDepthStencil = NULL;
2769 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2770 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2771 if(pDepthStencil) {
2772 IDirect3DSurface9_Release(pDepthStencil);
2773 pDepthStencil = NULL;
2776 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2777 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2778 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2780 cleanup:
2781 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2782 if (pDevice)
2784 UINT refcount = IDirect3D9_Release(pDevice);
2785 ok(!refcount, "Device has %u references left.\n", refcount);
2787 IDirect3D9_Release(d3d);
2788 DestroyWindow(hwnd);
2791 static void test_get_rt(void)
2793 IDirect3DSurface9 *backbuffer, *rt;
2794 IDirect3DDevice9 *device;
2795 IDirect3D9 *d3d9;
2796 D3DCAPS9 caps;
2797 HWND window;
2798 HRESULT hr;
2799 ULONG ref;
2800 UINT i;
2802 window = create_window();
2803 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2804 ok(!!d3d9, "Failed to create a D3D object.\n");
2805 device = create_device(d3d9, window, NULL);
2806 if (!device)
2808 skip("Failed to create a D3D device, skipping tests.\n");
2809 goto done;
2812 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2813 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2814 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2816 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2817 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2819 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2821 rt = backbuffer;
2822 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2823 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2824 ok(!rt, "Got rt %p.\n", rt);
2827 IDirect3DSurface9_Release(backbuffer);
2829 ref = IDirect3DDevice9_Release(device);
2830 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2831 done:
2832 IDirect3D9_Release(d3d9);
2833 DestroyWindow(window);
2836 static void test_draw_primitive(void)
2838 static const struct
2840 float position[3];
2841 DWORD color;
2843 quad[] =
2845 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2846 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2847 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2848 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2850 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
2851 static const D3DVERTEXELEMENT9 decl_elements[] =
2853 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2854 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2855 D3DDECL_END()
2858 IDirect3DVertexBuffer9 *vertex_buffer, *current_vb;
2859 IDirect3DIndexBuffer9 *index_buffer, *current_ib;
2860 IDirect3DVertexDeclaration9 *vertex_declaration;
2861 IDirect3DDevice9 *device;
2862 UINT offset, stride;
2863 IDirect3D9 *d3d9;
2864 ULONG refcount;
2865 HWND window;
2866 HRESULT hr;
2867 void *ptr;
2869 window = create_window();
2870 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2871 ok(!!d3d9, "Failed to create a D3D object.\n");
2872 if (!(device = create_device(d3d9, window, NULL)))
2874 skip("Failed to create a D3D device.\n");
2875 IDirect3D9_Release(d3d9);
2876 DestroyWindow(window);
2877 return;
2880 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2881 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
2883 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
2884 D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2885 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#x.\n", hr);
2886 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2887 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2888 memcpy(ptr, quad, sizeof(quad));
2889 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2890 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2891 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2892 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#x.\n", hr);
2894 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
2895 D3DPOOL_DEFAULT, &index_buffer, NULL);
2896 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#x.\n", hr);
2897 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2898 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2899 memcpy(ptr, indices, sizeof(indices));
2900 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2901 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2903 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2904 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#x.\n", hr);
2906 hr = IDirect3DDevice9_BeginScene(device);
2907 ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2909 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2910 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2912 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2913 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2915 hr = IDirect3DDevice9_GetStreamSource(device, 0, &current_vb, &offset, &stride);
2916 ok(SUCCEEDED(hr), "GetStreamSource failed, hr %#x.\n", hr);
2917 ok(current_vb == vertex_buffer, "Unexpected vb %p.\n", current_vb);
2918 ok(!offset, "Unexpected offset %u.\n", offset);
2919 ok(stride == sizeof(*quad), "Unexpected stride %u.\n", stride);
2920 IDirect3DVertexBuffer9_Release(current_vb);
2922 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2923 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2925 hr = IDirect3DDevice9_GetStreamSource(device, 0, &current_vb, &offset, &stride);
2926 ok(SUCCEEDED(hr), "GetStreamSource failed, hr %#x.\n", hr);
2927 todo_wine ok(!current_vb, "Unexpected vb %p.\n", current_vb);
2928 ok(!offset, "Unexpected offset %u.\n", offset);
2929 ok(stride == sizeof(*quad), "Unexpected stride %u.\n", stride);
2930 if (current_vb)
2931 IDirect3DVertexBuffer9_Release(current_vb);
2933 hr = IDirect3DDevice9_SetIndices(device, NULL);
2934 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2935 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2936 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2937 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2939 /* Valid index buffer, NULL vertex declaration. */
2940 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2941 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2942 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2943 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2944 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2946 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2947 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2948 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2950 hr = IDirect3DDevice9_GetIndices(device, &current_ib);
2951 ok(SUCCEEDED(hr), "GetIndices failed, hr %#x.\n", hr);
2952 todo_wine ok(!current_ib, "Unexpected index buffer %p.\n", current_vb);
2953 if (current_ib)
2954 IDirect3DIndexBuffer9_Release(current_ib);
2956 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2957 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2959 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2960 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2962 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2963 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2965 hr = IDirect3DDevice9_GetStreamSource(device, 0, &current_vb, &offset, &stride);
2966 ok(SUCCEEDED(hr), "GetStreamSource failed, hr %#x.\n", hr);
2967 ok(!current_vb, "Unexpected vb %p.\n", current_vb);
2968 ok(!offset, "Unexpected offset %u.\n", offset);
2969 ok(!stride, "Unexpected stride %u.\n", stride);
2971 /* NULL index buffer, valid vertex declaration, NULL stream source. */
2972 hr = IDirect3DDevice9_SetIndices(device, NULL);
2973 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2974 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2975 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2976 todo_wine ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2978 /* Valid index buffer and vertex declaration, NULL stream source. */
2979 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2980 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2981 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2982 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2983 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2985 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2986 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2987 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#x.\n", hr);
2989 hr = IDirect3DDevice9_EndScene(device);
2990 ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2992 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2993 ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2995 IDirect3DVertexBuffer9_Release(vertex_buffer);
2996 IDirect3DIndexBuffer9_Release(index_buffer);
2997 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2998 refcount = IDirect3DDevice9_Release(device);
2999 ok(!refcount, "Device has %u references left.\n", refcount);
3000 IDirect3D9_Release(d3d9);
3001 DestroyWindow(window);
3004 static void test_null_stream(void)
3006 IDirect3DVertexBuffer9 *buffer = NULL;
3007 IDirect3DDevice9 *device;
3008 IDirect3D9 *d3d9;
3009 ULONG refcount;
3010 HWND window;
3011 HRESULT hr;
3012 IDirect3DVertexShader9 *shader = NULL;
3013 IDirect3DVertexDeclaration9 *decl = NULL;
3014 static const DWORD shader_code[] =
3016 0xfffe0101, /* vs_1_1 */
3017 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
3018 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
3019 0x0000ffff /* end */
3021 static const D3DVERTEXELEMENT9 decl_elements[] = {
3022 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3023 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3024 D3DDECL_END()
3027 window = create_window();
3028 ok(!!window, "Failed to create a window.\n");
3029 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3030 ok(!!d3d9, "Failed to create a D3D object.\n");
3031 if (!(device = create_device(d3d9, window, NULL)))
3033 skip("Failed to create a 3D device, skipping test.\n");
3034 goto cleanup;
3037 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
3038 if(FAILED(hr)) {
3039 skip("No vertex shader support\n");
3040 goto cleanup;
3042 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3043 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
3044 if (FAILED(hr)) {
3045 skip("Vertex declaration handling not possible.\n");
3046 goto cleanup;
3048 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
3049 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
3050 if (FAILED(hr)) {
3051 skip("Vertex buffer handling not possible.\n");
3052 goto cleanup;
3055 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
3056 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3057 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
3058 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3059 hr = IDirect3DDevice9_SetVertexShader(device, shader);
3060 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
3061 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3062 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
3064 hr = IDirect3DDevice9_BeginScene(device);
3065 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3066 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
3067 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3068 hr = IDirect3DDevice9_EndScene(device);
3069 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3071 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3072 IDirect3DDevice9_SetVertexShader(device, NULL);
3073 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3075 cleanup:
3076 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
3077 if (decl) IDirect3DVertexDeclaration9_Release(decl);
3078 if (shader) IDirect3DVertexShader9_Release(shader);
3079 if (device)
3081 refcount = IDirect3DDevice9_Release(device);
3082 ok(!refcount, "Device has %u references left.\n", refcount);
3084 IDirect3D9_Release(d3d9);
3085 DestroyWindow(window);
3088 static void test_lights(void)
3090 IDirect3DDevice9 *device;
3091 IDirect3D9 *d3d9;
3092 ULONG refcount;
3093 HWND window;
3094 HRESULT hr;
3095 unsigned int i;
3096 BOOL enabled;
3097 D3DCAPS9 caps;
3099 window = create_window();
3100 ok(!!window, "Failed to create a window.\n");
3101 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3102 ok(!!d3d9, "Failed to create a D3D object.\n");
3103 if (!(device = create_device(d3d9, window, NULL)))
3105 skip("Failed to create a 3D device, skipping test.\n");
3106 goto cleanup;
3109 memset(&caps, 0, sizeof(caps));
3110 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3111 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
3113 for(i = 1; i <= caps.MaxActiveLights; i++) {
3114 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
3115 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
3116 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
3117 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
3118 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
3121 /* TODO: Test the rendering results in this situation */
3122 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
3123 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
3124 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
3125 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
3126 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
3127 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
3128 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
3130 for(i = 1; i <= caps.MaxActiveLights; i++) {
3131 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
3132 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
3135 refcount = IDirect3DDevice9_Release(device);
3136 ok(!refcount, "Device has %u references left.\n", refcount);
3137 cleanup:
3138 IDirect3D9_Release(d3d9);
3139 DestroyWindow(window);
3142 static void test_set_stream_source(void)
3144 IDirect3DVertexBuffer9 *vb;
3145 IDirect3DDevice9 *device;
3146 IDirect3D9 *d3d9;
3147 ULONG refcount;
3148 HWND window;
3149 HRESULT hr;
3151 window = create_window();
3152 ok(!!window, "Failed to create a window.\n");
3153 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3154 ok(!!d3d9, "Failed to create a D3D object.\n");
3155 if (!(device = create_device(d3d9, window, NULL)))
3157 skip("Failed to create a 3D device, skipping test.\n");
3158 goto cleanup;
3161 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
3162 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
3164 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
3165 * (Radeon 9000 verified) reject them, so accept both results. Wine
3166 * currently rejects this to be able to optimize the vbo conversion, but
3167 * writes a WARN. */
3168 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
3169 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3170 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
3171 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3172 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
3173 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3174 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
3175 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3176 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
3177 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3179 /* Try to set the NULL buffer with an offset and stride 0 */
3180 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3181 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3182 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
3183 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3184 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
3185 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3186 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
3187 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3188 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
3189 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3191 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3192 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3194 IDirect3DVertexBuffer9_Release(vb);
3195 refcount = IDirect3DDevice9_Release(device);
3196 ok(!refcount, "Device has %u references left.\n", refcount);
3197 cleanup:
3198 IDirect3D9_Release(d3d9);
3199 DestroyWindow(window);
3202 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
3203 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
3204 * a fixed number of combinations are possible in fullscreen mode. In windowed
3205 * mode more combinations are allowed due to format conversion and this is
3206 * likely driver dependent. */
3207 static void test_display_formats(void)
3209 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
3210 unsigned int backbuffer, display;
3211 unsigned int windowed;
3212 IDirect3D9 *d3d9;
3213 BOOL should_pass;
3214 BOOL has_modes;
3215 HRESULT hr;
3217 static const struct
3219 const char *name;
3220 D3DFORMAT format;
3221 D3DFORMAT alpha_format;
3222 BOOL display;
3223 BOOL windowed;
3225 formats[] =
3227 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
3228 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
3229 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
3230 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
3231 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3232 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3233 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3236 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3237 ok(!!d3d9, "Failed to create a D3D object.\n");
3239 for (display = 0; display < ARRAY_SIZE(formats); ++display)
3241 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3243 for (windowed = 0; windowed <= 1; ++windowed)
3245 for (backbuffer = 0; backbuffer < ARRAY_SIZE(formats); ++backbuffer)
3247 should_pass = FALSE;
3249 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3251 D3DFORMAT backbuffer_format;
3253 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3254 backbuffer_format = formats[display].format;
3255 else
3256 backbuffer_format = formats[backbuffer].format;
3258 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3259 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3260 if (hr == D3D_OK)
3262 if (windowed)
3264 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3265 backbuffer_format, formats[display].format);
3266 should_pass = (hr == D3D_OK);
3268 else
3269 should_pass = (formats[display].format == formats[backbuffer].format
3270 || (formats[display].alpha_format
3271 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3275 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3276 formats[display].format, formats[backbuffer].format, windowed);
3277 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3278 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3279 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3284 IDirect3D9_Release(d3d9);
3287 static void test_scissor_size(void)
3289 struct device_desc device_desc;
3290 IDirect3D9 *d3d9_ptr;
3291 unsigned int i;
3292 static struct {
3293 int winx; int winy; int backx; int backy; DWORD flags;
3294 } scts[] = { /* scissor tests */
3295 {800, 600, 640, 480, 0},
3296 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3297 {640, 480, 800, 600, 0},
3298 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3301 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3302 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3304 for (i = 0; i < ARRAY_SIZE(scts); i++)
3306 IDirect3DDevice9 *device_ptr = 0;
3307 HRESULT hr;
3308 HWND hwnd = 0;
3309 RECT scissorrect;
3311 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3312 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3314 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3316 scts[i].backx = registry_mode.dmPelsWidth;
3317 scts[i].backy = registry_mode.dmPelsHeight;
3320 device_desc.device_window = hwnd;
3321 device_desc.width = scts[i].backx;
3322 device_desc.height = scts[i].backy;
3323 device_desc.flags = scts[i].flags;
3324 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3326 skip("Failed to create a 3D device, skipping test.\n");
3327 DestroyWindow(hwnd);
3328 goto err_out;
3331 /* Check for the default scissor rect size */
3332 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3333 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3334 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3335 && scissorrect.top == 0 && scissorrect.left == 0,
3336 "Scissorrect mismatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3337 scts[i].backx, scts[i].backy);
3339 /* check the scissorrect values after a reset */
3340 device_desc.width = registry_mode.dmPelsWidth;
3341 device_desc.height = registry_mode.dmPelsHeight;
3342 device_desc.flags = scts[i].flags;
3343 hr = reset_device(device_ptr, &device_desc);
3344 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3345 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3346 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3348 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3349 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3350 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3351 && scissorrect.top == 0 && scissorrect.left == 0,
3352 "Scissorrect mismatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3353 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3355 if (device_ptr)
3357 ULONG ref;
3359 ref = IDirect3DDevice9_Release(device_ptr);
3360 DestroyWindow(hwnd);
3361 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3365 err_out:
3366 IDirect3D9_Release(d3d9_ptr);
3369 static void test_multi_device(void)
3371 IDirect3DDevice9 *device1, *device2;
3372 HWND window1, window2;
3373 IDirect3D9 *d3d9;
3374 ULONG refcount;
3376 window1 = create_window();
3377 ok(!!window1, "Failed to create a window.\n");
3378 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3379 ok(!!d3d9, "Failed to create a D3D object.\n");
3380 if (!(device1 = create_device(d3d9, window1, NULL)))
3382 skip("Failed to create a 3D device, skipping test.\n");
3383 IDirect3D9_Release(d3d9);
3384 DestroyWindow(window1);
3385 return;
3387 IDirect3D9_Release(d3d9);
3389 window2 = create_window();
3390 ok(!!window2, "Failed to create a window.\n");
3391 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3392 ok(!!d3d9, "Failed to create a D3D object.\n");
3393 device2 = create_device(d3d9, window2, NULL);
3394 IDirect3D9_Release(d3d9);
3396 refcount = IDirect3DDevice9_Release(device2);
3397 ok(!refcount, "Device has %u references left.\n", refcount);
3398 refcount = IDirect3DDevice9_Release(device1);
3399 ok(!refcount, "Device has %u references left.\n", refcount);
3400 DestroyWindow(window2);
3401 DestroyWindow(window1);
3404 static HWND filter_messages;
3406 enum message_window
3408 DEVICE_WINDOW,
3409 FOCUS_WINDOW,
3412 struct message
3414 UINT message;
3415 enum message_window window;
3416 BOOL check_wparam;
3417 WPARAM expect_wparam;
3418 HRESULT device_state;
3419 WINDOWPOS *store_wp;
3422 static const struct message *expect_messages;
3423 static HWND device_window, focus_window;
3424 static LONG windowposchanged_received, syscommand_received, wm_size_received;
3425 static IDirect3DDevice9 *focus_test_device;
3427 struct wndproc_thread_param
3429 HWND dummy_window;
3430 HANDLE window_created;
3431 HANDLE test_finished;
3432 BOOL running_in_foreground;
3435 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3437 HRESULT hr;
3439 if (filter_messages && filter_messages == hwnd)
3441 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3442 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3445 if (expect_messages)
3447 HWND w;
3449 switch (expect_messages->window)
3451 case DEVICE_WINDOW:
3452 w = device_window;
3453 break;
3455 case FOCUS_WINDOW:
3456 w = focus_window;
3457 break;
3459 default:
3460 w = NULL;
3461 break;
3464 if (hwnd == w && expect_messages->message == message)
3466 if (expect_messages->check_wparam)
3467 ok(wparam == expect_messages->expect_wparam,
3468 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3469 wparam, message, expect_messages->expect_wparam);
3471 if (expect_messages->store_wp)
3472 *expect_messages->store_wp = *(WINDOWPOS *)lparam;
3474 if (focus_test_device)
3476 hr = IDirect3DDevice9_TestCooperativeLevel(focus_test_device);
3477 /* Wined3d marks the device lost earlier than Windows (it follows ddraw
3478 * behavior. See test_wndproc before the focus_loss_messages sequence
3479 * about the D3DERR_DEVICENOTRESET behavior, */
3480 todo_wine_if(message != WM_ACTIVATEAPP || hr == D3D_OK)
3481 ok(hr == expect_messages->device_state,
3482 "Got device state %#x on message %#x, expected %#x.\n",
3483 hr, message, expect_messages->device_state);
3486 ++expect_messages;
3490 /* KDE randomly does something with the hidden window during the
3491 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3492 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3493 * just flag WM_WINDOWPOSCHANGED as bad. */
3494 if (message == WM_WINDOWPOSCHANGED)
3495 InterlockedIncrement(&windowposchanged_received);
3496 else if (message == WM_SYSCOMMAND)
3497 InterlockedIncrement(&syscommand_received);
3498 else if (message == WM_SIZE)
3499 InterlockedIncrement(&wm_size_received);
3501 return DefWindowProcA(hwnd, message, wparam, lparam);
3504 static DWORD WINAPI wndproc_thread(void *param)
3506 struct wndproc_thread_param *p = param;
3507 DWORD res;
3508 BOOL ret;
3510 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3511 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3512 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3513 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3515 ret = SetEvent(p->window_created);
3516 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3518 for (;;)
3520 MSG msg;
3522 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3523 res = WaitForSingleObject(p->test_finished, 100);
3524 if (res == WAIT_OBJECT_0) break;
3525 if (res != WAIT_TIMEOUT)
3527 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3528 break;
3532 DestroyWindow(p->dummy_window);
3534 return 0;
3537 static void test_wndproc(void)
3539 struct wndproc_thread_param thread_params;
3540 struct device_desc device_desc;
3541 IDirect3DDevice9 *device;
3542 WNDCLASSA wc = {0};
3543 IDirect3D9 *d3d9;
3544 HANDLE thread;
3545 LONG_PTR proc;
3546 ULONG ref;
3547 DWORD res, tid;
3548 HWND tmp;
3549 UINT i, adapter_mode_count;
3550 HRESULT hr;
3551 D3DDISPLAYMODE d3ddm;
3552 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3553 DEVMODEW devmode;
3554 LONG change_ret, device_style;
3555 BOOL ret;
3556 WINDOWPOS windowpos;
3558 static const struct message create_messages[] =
3560 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3561 /* Do not test wparam here. If device creation succeeds,
3562 * wparam is WA_ACTIVE. If device creation fails (testbot)
3563 * wparam is set to WA_INACTIVE on some Windows versions. */
3564 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3565 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3566 {0, 0, FALSE, 0},
3568 static const struct message focus_loss_messages[] =
3570 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3571 * not reliable on X11 WMs. When the window focus follows the
3572 * mouse pointer the message is not sent.
3573 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3574 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
3575 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3576 * not deterministic. */
3577 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
3578 /* Windows sends WM_ACTIVATE to the device window, indicating that
3579 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3580 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3581 * leaves the device window active, breaking re-activation in the
3582 * lost device test.
3583 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3584 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
3585 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED,
3586 D3DERR_DEVICENOTRESET},
3587 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, D3DERR_DEVICELOST},
3588 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3589 * not deterministic. It may be sent after the focus window handling
3590 * or before. */
3591 {0, 0, FALSE, 0, 0},
3593 static const struct message focus_loss_messages_nowc[] =
3595 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3596 * not reliable on X11 WMs. When the window focus follows the
3597 * mouse pointer the message is not sent.
3598 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3599 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0, D3DERR_DEVICENOTRESET},
3600 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE, D3DERR_DEVICELOST},
3601 {0, 0, FALSE, 0, 0},
3603 static const struct message reactivate_messages[] =
3605 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3606 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3607 /* optional WM_MOVE here if size changed */
3608 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3609 {0, 0, FALSE, 0},
3611 static const struct message reactivate_messages_nowc[] =
3613 /* We're activating the device window before activating the
3614 * focus window, so no ACTIVATEAPP message is sent. */
3615 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3616 {0, 0, FALSE, 0},
3618 static const struct message focus_loss_messages_hidden[] =
3620 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3621 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3622 {0, 0, FALSE, 0},
3624 static const struct message focus_loss_messages_filtered[] =
3626 /* WM_ACTIVATE is delivered to the window proc because it is
3627 * generated by SetForegroundWindow before the d3d routine
3628 * starts it work. Don't check for it due to focus-follows-mouse
3629 * WMs though. */
3630 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3631 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3632 {0, 0, FALSE, 0},
3634 static const struct message reactivate_messages_filtered[] =
3636 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3637 {0, 0, FALSE, 0},
3639 static const struct message sc_restore_messages[] =
3641 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3642 * processed it. Our wndproc has no way to prevent d3d from
3643 * handling the message. The second DefWindowProc call done by
3644 * our wndproc doesn't do any changes to the window because it
3645 * is already restored due to d3d's handling. */
3646 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3647 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3648 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3649 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3650 {0, 0, FALSE, 0},
3652 static const struct message sc_minimize_messages[] =
3654 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3655 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3656 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3657 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3658 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3659 {0, 0, FALSE, 0},
3661 static const struct message sc_maximize_messages[] =
3663 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3664 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3665 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3666 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3667 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3668 {0, 0, FALSE, 0},
3670 struct message mode_change_messages[] =
3672 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3673 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3674 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3675 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3676 * differs between Wine and Windows. */
3677 /* TODO 2: Windows sends a second WM_WINDOWPOSCHANGING(SWP_NOMOVE | SWP_NOSIZE
3678 * | SWP_NOACTIVATE) in this situation, suggesting a difference in their ShowWindow
3679 * implementation. This SetWindowPos call could in theory affect the Z order. Wine's
3680 * ShowWindow does not send such a message because the window is already visible. */
3681 {0, 0, FALSE, 0},
3683 struct message mode_change_messages_hidden[] =
3685 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3686 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3687 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3688 {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0},
3689 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, ~0U, &windowpos},
3690 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3691 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3692 * differs between Wine and Windows. */
3693 {0, 0, FALSE, 0},
3695 static const struct message mode_change_messages_nowc[] =
3697 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3698 {0, 0, FALSE, 0},
3700 struct
3702 DWORD create_flags;
3703 const struct message *focus_loss_messages, *reactivate_messages;
3704 const struct message *mode_change_messages, *mode_change_messages_hidden;
3705 BOOL iconic;
3707 tests[] =
3711 focus_loss_messages,
3712 reactivate_messages,
3713 mode_change_messages,
3714 mode_change_messages_hidden,
3715 TRUE
3718 CREATE_DEVICE_NOWINDOWCHANGES,
3719 focus_loss_messages_nowc,
3720 reactivate_messages_nowc,
3721 mode_change_messages_nowc,
3722 mode_change_messages_nowc,
3723 FALSE
3727 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3728 ok(!!d3d9, "Failed to create a D3D object.\n");
3730 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3731 for (i = 0; i < adapter_mode_count; ++i)
3733 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3734 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3736 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3737 continue;
3738 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3739 * refuses to create a device at these sizes. */
3740 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3741 continue;
3743 if (!user32_width)
3745 user32_width = d3ddm.Width;
3746 user32_height = d3ddm.Height;
3747 continue;
3750 /* Make sure the d3d mode is smaller in width or height and at most
3751 * equal in the other dimension than the mode passed to
3752 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3753 * the ChangeDisplaySettings parameters + 12. */
3754 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3755 continue;
3756 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3758 d3d_width = d3ddm.Width;
3759 d3d_height = d3ddm.Height;
3760 break;
3762 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3764 d3d_width = user32_width;
3765 d3d_height = user32_height;
3766 user32_width = d3ddm.Width;
3767 user32_height = d3ddm.Height;
3768 break;
3772 if (!d3d_width)
3774 skip("Could not find adequate modes, skipping mode tests.\n");
3775 IDirect3D9_Release(d3d9);
3776 return;
3779 wc.lpfnWndProc = test_proc;
3780 wc.lpszClassName = "d3d9_test_wndproc_wc";
3781 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3783 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3784 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3785 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3786 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3788 memset(&devmode, 0, sizeof(devmode));
3789 devmode.dmSize = sizeof(devmode);
3790 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3792 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3793 devmode.dmPelsWidth = user32_width;
3794 devmode.dmPelsHeight = user32_height;
3795 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3796 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3798 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3799 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3800 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3801 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3802 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3803 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3805 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3806 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3808 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3809 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3810 (LONG_PTR)test_proc, proc);
3811 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3812 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3813 (LONG_PTR)test_proc, proc);
3815 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3816 device_window, focus_window, thread_params.dummy_window);
3818 tmp = GetFocus();
3819 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3820 if (thread_params.running_in_foreground)
3822 tmp = GetForegroundWindow();
3823 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3824 thread_params.dummy_window, tmp);
3826 else
3827 skip("Not running in foreground, skip foreground window test\n");
3829 flush_events();
3831 expect_messages = create_messages;
3833 device_desc.device_window = device_window;
3834 device_desc.width = d3d_width;
3835 device_desc.height = d3d_height;
3836 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3837 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3839 skip("Failed to create a D3D device, skipping tests.\n");
3840 goto done;
3843 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3844 expect_messages->message, expect_messages->window, i);
3845 expect_messages = NULL;
3847 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3849 tmp = GetFocus();
3850 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3851 tmp = GetForegroundWindow();
3852 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3854 SetForegroundWindow(focus_window);
3855 flush_events();
3857 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3858 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3859 (LONG_PTR)test_proc, proc, i);
3861 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3862 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3863 (LONG_PTR)test_proc, i);
3865 /* Change the mode while the device is in use and then drop focus. */
3866 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3867 devmode.dmPelsWidth = user32_width;
3868 devmode.dmPelsHeight = user32_height;
3869 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3870 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3872 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3873 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3874 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3875 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3876 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3877 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3879 focus_test_device = device;
3880 expect_messages = tests[i].focus_loss_messages;
3881 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3882 * manually changing the focus. It generates the same messages, but the task
3883 * bar still shows the previous foreground window as active, and the window has
3884 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3885 * the device is difficult, see below. */
3886 SetForegroundWindow(GetDesktopWindow());
3887 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3888 expect_messages->message, expect_messages->window, i);
3889 expect_messages = NULL;
3890 tmp = GetFocus();
3891 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3892 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3893 focus_test_device = NULL;
3895 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3896 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3898 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3899 ok(ret, "Failed to get display mode.\n");
3900 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3901 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3902 devmode.dmPelsWidth, devmode.dmPelsHeight);
3904 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3905 * done before the focus window is restored. This makes sense to some extent
3906 * because minimizing the window on focus loss is the application's job if this
3907 * flag is set. */
3908 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3910 ShowWindow(device_window, SW_MINIMIZE);
3911 ShowWindow(device_window, SW_RESTORE);
3913 flush_events();
3915 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3916 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3917 * restore is triggered by the user. */
3918 expect_messages = tests[i].reactivate_messages;
3919 ShowWindow(focus_window, SW_MINIMIZE);
3920 ShowWindow(focus_window, SW_RESTORE);
3921 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3922 SetForegroundWindow(focus_window);
3923 flush_events();
3924 SetForegroundWindow(focus_window);
3925 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3926 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3927 expect_messages->message, expect_messages->window, i);
3928 expect_messages = NULL;
3930 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3931 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3933 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3934 ok(ret, "Failed to get display mode.\n");
3935 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3936 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3937 devmode.dmPelsWidth, devmode.dmPelsHeight);
3939 hr = reset_device(device, &device_desc);
3940 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3942 /* Remove the WS_VISIBLE flag to test hidden windows. This is enough to trigger d3d's hidden
3943 * window codepath, but does not actually hide the window without a SetWindowPos(SWP_FRAMECHANGED)
3944 * call. This way we avoid focus changes and random failures on focus follows mouse WMs. */
3945 device_style = GetWindowLongA(device_window, GWL_STYLE);
3946 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3947 flush_events();
3949 expect_messages = focus_loss_messages_hidden;
3950 windowposchanged_received = 0;
3951 SetForegroundWindow(GetDesktopWindow());
3952 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3953 expect_messages->message, expect_messages->window, i);
3954 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3955 expect_messages = NULL;
3956 flush_events();
3958 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3959 ok(ret, "Failed to get display mode.\n");
3960 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3961 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3963 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3964 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3965 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3966 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3967 flush_events();
3969 syscommand_received = 0;
3970 expect_messages = sc_restore_messages;
3971 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3972 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3973 expect_messages->message, expect_messages->window, i);
3974 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3975 expect_messages = NULL;
3976 flush_events();
3978 expect_messages = sc_minimize_messages;
3979 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3980 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3981 expect_messages->message, expect_messages->window, i);
3982 expect_messages = NULL;
3983 flush_events();
3985 expect_messages = sc_maximize_messages;
3986 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3987 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3988 expect_messages->message, expect_messages->window, i);
3989 expect_messages = NULL;
3990 flush_events();
3992 SetForegroundWindow(GetDesktopWindow());
3993 ShowWindow(device_window, SW_MINIMIZE);
3994 ShowWindow(device_window, SW_RESTORE);
3995 ShowWindow(focus_window, SW_MINIMIZE);
3996 ShowWindow(focus_window, SW_RESTORE);
3997 SetForegroundWindow(focus_window);
3998 flush_events();
4000 /* Releasing a device in lost state breaks follow-up tests on native. */
4001 hr = reset_device(device, &device_desc);
4002 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
4004 filter_messages = focus_window;
4006 ref = IDirect3DDevice9_Release(device);
4007 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4009 /* Fix up the mode until Wine's device release behavior is fixed. */
4010 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4011 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4013 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4014 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4015 (LONG_PTR)test_proc, proc, i);
4017 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
4018 * on native in the test below. It isn't needed anyways. Creating the third
4019 * device will show it again. */
4020 filter_messages = NULL;
4021 ShowWindow(device_window, SW_HIDE);
4022 /* Remove the maximized state from the SYSCOMMAND test while we're not
4023 * interfering with a device. */
4024 ShowWindow(focus_window, SW_SHOWNORMAL);
4025 filter_messages = focus_window;
4027 device_desc.device_window = focus_window;
4028 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4030 skip("Failed to create a D3D device, skipping tests.\n");
4031 goto done;
4033 filter_messages = NULL;
4034 SetForegroundWindow(focus_window); /* For KDE. */
4035 flush_events();
4037 expect_messages = focus_loss_messages_filtered;
4038 windowposchanged_received = 0;
4039 SetForegroundWindow(GetDesktopWindow());
4040 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4041 expect_messages->message, expect_messages->window, i);
4042 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4043 expect_messages = NULL;
4045 /* The window is iconic even though no message was sent. */
4046 ok(!IsIconic(focus_window) == !tests[i].iconic,
4047 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
4049 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4050 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
4052 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4053 ShowWindow(focus_window, SW_MINIMIZE);
4055 syscommand_received = 0;
4056 expect_messages = sc_restore_messages;
4057 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
4058 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4059 expect_messages->message, expect_messages->window, i);
4060 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
4061 expect_messages = NULL;
4062 flush_events();
4064 /* For FVWM. */
4065 ShowWindow(focus_window, SW_RESTORE);
4066 flush_events();
4068 expect_messages = sc_minimize_messages;
4069 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
4070 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4071 expect_messages->message, expect_messages->window, i);
4072 expect_messages = NULL;
4073 flush_events();
4075 expect_messages = sc_maximize_messages;
4076 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
4077 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4078 expect_messages->message, expect_messages->window, i);
4079 expect_messages = NULL;
4080 flush_events();
4082 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
4083 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
4084 SetForegroundWindow(GetDesktopWindow());
4085 flush_events();
4086 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
4087 flush_events();
4089 expect_messages = reactivate_messages_filtered;
4090 windowposchanged_received = 0;
4091 SetForegroundWindow(focus_window);
4092 flush_events();
4093 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4094 expect_messages->message, expect_messages->window, i);
4095 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
4096 ok(!windowposchanged_received || broken(1),
4097 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4098 expect_messages = NULL;
4100 filter_messages = focus_window;
4101 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4102 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
4104 hr = reset_device(device, &device_desc);
4105 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4107 ref = IDirect3DDevice9_Release(device);
4108 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4110 device_desc.device_window = device_window;
4111 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4113 skip("Failed to create a D3D device, skipping tests.\n");
4114 goto done;
4116 filter_messages = NULL;
4117 flush_events();
4119 device_desc.width = user32_width;
4120 device_desc.height = user32_height;
4122 expect_messages = tests[i].mode_change_messages;
4123 filter_messages = focus_window;
4124 hr = reset_device(device, &device_desc);
4125 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4126 filter_messages = NULL;
4128 /* The WINDOWPOS structure passed to the first WM_WINDOWPOSCHANGING differs between windows versions.
4129 * Prior to Win10 17.03 it is consistent with a MoveWindow(0, 0, width, height) call. Since Windows
4130 * 10 17.03 it has x = 0, y = 0, width = 0, height = 0, flags = SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE
4131 * | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER (0x1837). Visually
4132 * it is clear that the window has not been resized. In previous Windows version the window is resized. */
4134 flush_events();
4135 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4136 expect_messages->message, expect_messages->window, i);
4138 /* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
4139 device_style = GetWindowLongA(device_window, GWL_STYLE);
4140 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
4142 flush_events();
4143 device_desc.width = d3d_width;
4144 device_desc.height = d3d_height;
4145 memset(&windowpos, 0, sizeof(windowpos));
4147 expect_messages = tests[i].mode_change_messages_hidden;
4148 filter_messages = focus_window;
4149 hr = reset_device(device, &device_desc);
4150 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4151 filter_messages = NULL;
4153 flush_events();
4154 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4155 expect_messages->message, expect_messages->window, i);
4157 if (!(tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES))
4159 ok(windowpos.hwnd == device_window && !windowpos.hwndInsertAfter
4160 && !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
4161 && windowpos.flags == (SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE),
4162 "Got unexpected WINDOWPOS hwnd=%p, insertAfter=%p, x=%d, y=%d, cx=%d, cy=%d, flags=%x\n",
4163 windowpos.hwnd, windowpos.hwndInsertAfter, windowpos.x, windowpos.y, windowpos.cx,
4164 windowpos.cy, windowpos.flags);
4167 device_style = GetWindowLongA(device_window, GWL_STYLE);
4168 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4170 todo_wine ok(!(device_style & WS_VISIBLE), "Expected the device window to be hidden, i=%u.\n", i);
4171 ShowWindow(device_window, SW_MINIMIZE);
4172 ShowWindow(device_window, SW_RESTORE);
4174 else
4176 ok(device_style & WS_VISIBLE, "Expected the device window to be visible, i=%u.\n", i);
4179 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
4180 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
4181 (LONG_PTR)test_proc, i);
4183 filter_messages = focus_window;
4184 ref = IDirect3DDevice9_Release(device);
4185 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4187 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4188 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4189 (LONG_PTR)DefWindowProcA, proc, i);
4191 done:
4192 filter_messages = NULL;
4193 DestroyWindow(device_window);
4194 DestroyWindow(focus_window);
4195 SetEvent(thread_params.test_finished);
4196 WaitForSingleObject(thread, INFINITE);
4197 CloseHandle(thread);
4200 IDirect3D9_Release(d3d9);
4201 CloseHandle(thread_params.test_finished);
4202 CloseHandle(thread_params.window_created);
4203 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4206 static void test_wndproc_windowed(void)
4208 struct wndproc_thread_param thread_params;
4209 struct device_desc device_desc;
4210 IDirect3DDevice9 *device;
4211 WNDCLASSA wc = {0};
4212 IDirect3D9 *d3d9;
4213 HANDLE thread;
4214 LONG_PTR proc;
4215 HRESULT hr;
4216 ULONG ref;
4217 DWORD res, tid;
4218 HWND tmp;
4220 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4221 ok(!!d3d9, "Failed to create a D3D object.\n");
4223 wc.lpfnWndProc = test_proc;
4224 wc.lpszClassName = "d3d9_test_wndproc_wc";
4225 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4227 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4228 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4229 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4230 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4232 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4233 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4234 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4235 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4236 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4237 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4238 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4239 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4241 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4242 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4244 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4245 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4246 (LONG_PTR)test_proc, proc);
4247 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4248 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4249 (LONG_PTR)test_proc, proc);
4251 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4252 device_window, focus_window, thread_params.dummy_window);
4254 tmp = GetFocus();
4255 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4256 if (thread_params.running_in_foreground)
4258 tmp = GetForegroundWindow();
4259 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4260 thread_params.dummy_window, tmp);
4262 else
4263 skip("Not running in foreground, skip foreground window test\n");
4265 filter_messages = focus_window;
4267 device_desc.device_window = device_window;
4268 device_desc.width = 640;
4269 device_desc.height = 480;
4270 device_desc.flags = 0;
4271 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4273 skip("Failed to create a D3D device, skipping tests.\n");
4274 goto done;
4277 tmp = GetFocus();
4278 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4279 tmp = GetForegroundWindow();
4280 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4281 thread_params.dummy_window, tmp);
4283 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4284 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4285 (LONG_PTR)test_proc, proc);
4287 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4288 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4289 (LONG_PTR)test_proc, proc);
4291 filter_messages = NULL;
4293 device_desc.width = registry_mode.dmPelsWidth;
4294 device_desc.height = registry_mode.dmPelsHeight;
4295 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4296 hr = reset_device(device, &device_desc);
4297 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4299 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4300 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4301 (LONG_PTR)test_proc, proc);
4303 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4304 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4306 device_desc.flags = 0;
4307 hr = reset_device(device, &device_desc);
4308 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4310 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4311 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4312 (LONG_PTR)test_proc, proc);
4314 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4315 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4316 (LONG_PTR)test_proc, proc);
4318 filter_messages = focus_window;
4320 ref = IDirect3DDevice9_Release(device);
4321 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4323 filter_messages = device_window;
4325 device_desc.device_window = focus_window;
4326 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4328 skip("Failed to create a D3D device, skipping tests.\n");
4329 goto done;
4332 filter_messages = NULL;
4334 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4335 hr = reset_device(device, &device_desc);
4336 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4338 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4339 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4340 (LONG_PTR)test_proc, proc);
4342 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4343 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4345 device_desc.flags = 0;
4346 hr = reset_device(device, &device_desc);
4347 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4349 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4350 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4351 (LONG_PTR)test_proc, proc);
4353 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4354 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4355 (LONG_PTR)test_proc, proc);
4357 filter_messages = device_window;
4359 ref = IDirect3DDevice9_Release(device);
4360 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4362 device_desc.device_window = device_window;
4363 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4365 skip("Failed to create a D3D device, skipping tests.\n");
4366 goto done;
4369 filter_messages = NULL;
4371 device_desc.device_window = device_window;
4372 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4373 hr = reset_device(device, &device_desc);
4374 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4376 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4377 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4378 (LONG_PTR)test_proc, proc);
4380 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4381 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4383 device_desc.flags = 0;
4384 hr = reset_device(device, &device_desc);
4385 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4387 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4388 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4389 (LONG_PTR)test_proc, proc);
4391 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4392 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4393 (LONG_PTR)test_proc, proc);
4395 filter_messages = device_window;
4397 ref = IDirect3DDevice9_Release(device);
4398 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4400 done:
4401 filter_messages = NULL;
4402 IDirect3D9_Release(d3d9);
4404 SetEvent(thread_params.test_finished);
4405 WaitForSingleObject(thread, INFINITE);
4406 CloseHandle(thread_params.test_finished);
4407 CloseHandle(thread_params.window_created);
4408 CloseHandle(thread);
4410 DestroyWindow(device_window);
4411 DestroyWindow(focus_window);
4412 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4415 static void test_reset_fullscreen(void)
4417 struct device_desc device_desc;
4418 D3DDISPLAYMODE d3ddm, d3ddm2;
4419 unsigned int mode_count, i;
4420 IDirect3DDevice9 *device;
4421 WNDCLASSEXA wc = {0};
4422 IDirect3D9 *d3d;
4423 HRESULT hr;
4424 ATOM atom;
4425 static const struct message messages[] =
4427 /* Windows usually sends wparam = TRUE, except on the testbot,
4428 * where it randomly sends FALSE. Ignore it. */
4429 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4430 {0, 0, FALSE, 0},
4433 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4434 ok(!!d3d, "Failed to create a D3D object.\n");
4435 expect_messages = messages;
4437 wc.cbSize = sizeof(wc);
4438 wc.lpfnWndProc = test_proc;
4439 wc.lpszClassName = "test_reset_fullscreen";
4441 atom = RegisterClassExA(&wc);
4442 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4444 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4445 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4446 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4449 * Create a device in windowed mode.
4450 * Since the device is windowed and we haven't called any methods that
4451 * could show the window (such as ShowWindow or SetWindowPos) yet,
4452 * WM_ACTIVATEAPP will not have been sent.
4454 if (!(device = create_device(d3d, device_window, NULL)))
4456 skip("Unable to create device. Skipping test.\n");
4457 goto cleanup;
4461 * Switch to fullscreen mode.
4462 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4463 * message to be sent.
4465 device_desc.width = registry_mode.dmPelsWidth;
4466 device_desc.height = registry_mode.dmPelsHeight;
4467 device_desc.device_window = device_window;
4468 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4469 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4471 flush_events();
4472 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4473 expect_messages = NULL;
4475 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
4476 mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
4477 for (i = 0; i < mode_count; ++i)
4479 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
4480 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4482 if (d3ddm2.Width != d3ddm.Width || d3ddm2.Height != d3ddm.Height)
4483 break;
4485 if (i == mode_count)
4487 skip("Could not find a suitable display mode.\n");
4488 goto cleanup;
4491 wm_size_received = 0;
4493 /* Fullscreen mode change. */
4494 device_desc.width = d3ddm2.Width;
4495 device_desc.height = d3ddm2.Height;
4496 device_desc.device_window = device_window;
4497 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4498 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4500 flush_events();
4501 ok(!wm_size_received, "Received unexpected WM_SIZE message.\n");
4503 cleanup:
4504 if (device) IDirect3DDevice9_Release(device);
4505 IDirect3D9_Release(d3d);
4506 DestroyWindow(device_window);
4507 device_window = focus_window = NULL;
4508 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4512 static inline void set_fpu_cw(WORD cw)
4514 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4515 #define D3D9_TEST_SET_FPU_CW 1
4516 __asm__ volatile ("fnclex");
4517 __asm__ volatile ("fldcw %0" : : "m" (cw));
4518 #elif defined(__i386__) && defined(_MSC_VER)
4519 #define D3D9_TEST_SET_FPU_CW 1
4520 __asm fnclex;
4521 __asm fldcw cw;
4522 #endif
4525 static inline WORD get_fpu_cw(void)
4527 WORD cw = 0;
4528 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4529 #define D3D9_TEST_GET_FPU_CW 1
4530 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4531 #elif defined(__i386__) && defined(_MSC_VER)
4532 #define D3D9_TEST_GET_FPU_CW 1
4533 __asm fnstcw cw;
4534 #endif
4535 return cw;
4538 static WORD callback_cw, callback_set_cw;
4539 static DWORD callback_tid;
4541 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4543 *out = NULL;
4544 return E_NOINTERFACE;
4547 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4549 callback_cw = get_fpu_cw();
4550 set_fpu_cw(callback_set_cw);
4551 callback_tid = GetCurrentThreadId();
4552 return 2;
4555 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4557 callback_cw = get_fpu_cw();
4558 set_fpu_cw(callback_set_cw);
4559 callback_tid = GetCurrentThreadId();
4560 return 1;
4563 static const IUnknownVtbl dummy_object_vtbl =
4565 dummy_object_QueryInterface,
4566 dummy_object_AddRef,
4567 dummy_object_Release,
4570 static const GUID d3d9_private_data_test_guid =
4572 0xfdb37466,
4573 0x428f,
4574 0x4edf,
4575 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4578 static void test_fpu_setup(void)
4580 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4581 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
4582 IUnknown dummy_object = {&dummy_object_vtbl};
4583 struct device_desc device_desc;
4584 IDirect3DSurface9 *surface;
4585 IDirect3DDevice9 *device;
4586 WORD cw, expected_cw;
4587 HWND window = NULL;
4588 IDirect3D9 *d3d9;
4589 HRESULT hr;
4591 window = create_window();
4592 ok(!!window, "Failed to create a window.\n");
4593 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4594 ok(!!d3d9, "Failed to create a D3D object.\n");
4596 device_desc.device_window = window;
4597 device_desc.width = 640;
4598 device_desc.height = 480;
4599 device_desc.flags = 0;
4601 set_fpu_cw(0xf60);
4602 cw = get_fpu_cw();
4603 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4605 if (!(device = create_device(d3d9, window, &device_desc)))
4607 skip("Failed to create a 3D device, skipping test.\n");
4608 set_fpu_cw(0x37f);
4609 goto done;
4612 expected_cw = is_64bit ? 0xf60 : 0x7f;
4614 cw = get_fpu_cw();
4615 todo_wine_if(is_64bit)
4616 ok(cw == expected_cw, "cw is %#x, expected %#x.\n", cw, expected_cw);
4618 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4619 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4621 callback_set_cw = 0xf60;
4622 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4623 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4624 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4625 todo_wine_if(is_64bit)
4626 ok(callback_cw == expected_cw, "Callback cw is %#x, expected %#x.\n", callback_cw, expected_cw);
4627 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4628 cw = get_fpu_cw();
4629 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4631 callback_cw = 0;
4632 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4633 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4634 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4635 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4636 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4638 callback_set_cw = 0x7f;
4639 set_fpu_cw(0x7f);
4641 IDirect3DSurface9_Release(surface);
4643 callback_cw = 0;
4644 IDirect3DDevice9_Release(device);
4645 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4646 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4648 cw = get_fpu_cw();
4649 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4650 set_fpu_cw(0xf60);
4651 cw = get_fpu_cw();
4652 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4654 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4655 device = create_device(d3d9, window, &device_desc);
4656 ok(device != NULL, "CreateDevice failed.\n");
4658 cw = get_fpu_cw();
4659 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4661 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4662 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4664 callback_cw = 0;
4665 callback_set_cw = 0x37f;
4666 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4667 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4668 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4669 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4670 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4671 cw = get_fpu_cw();
4672 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4674 IDirect3DSurface9_Release(surface);
4676 callback_cw = 0;
4677 IDirect3DDevice9_Release(device);
4678 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4679 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4681 done:
4682 IDirect3D9_Release(d3d9);
4683 DestroyWindow(window);
4684 #endif
4687 static void test_window_style(void)
4689 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4690 LONG device_style, device_exstyle;
4691 LONG focus_style, focus_exstyle;
4692 struct device_desc device_desc;
4693 LONG style, expected_style;
4694 IDirect3DDevice9 *device;
4695 IDirect3D9 *d3d9;
4696 HRESULT hr;
4697 ULONG ref;
4698 BOOL ret;
4699 static const struct
4701 DWORD device_flags;
4702 LONG style, focus_loss_style, exstyle;
4704 tests[] =
4706 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4707 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4709 unsigned int i;
4711 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4712 ok(!!d3d9, "Failed to create a D3D object.\n");
4713 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4715 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4717 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4718 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4719 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4720 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4722 device_style = GetWindowLongA(device_window, GWL_STYLE);
4723 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4724 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4725 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4727 GetWindowRect(focus_window, &focus_rect);
4728 GetWindowRect(device_window, &device_rect);
4730 device_desc.device_window = device_window;
4731 device_desc.width = registry_mode.dmPelsWidth;
4732 device_desc.height = registry_mode.dmPelsHeight;
4733 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4734 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4736 skip("Failed to create a D3D device, skipping tests.\n");
4737 DestroyWindow(device_window);
4738 DestroyWindow(focus_window);
4739 break;
4742 style = GetWindowLongA(device_window, GWL_STYLE);
4743 expected_style = device_style | tests[i].style;
4744 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4745 expected_style, style, i);
4746 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4747 expected_style = device_exstyle | tests[i].exstyle;
4748 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4749 expected_style, style, i);
4751 style = GetWindowLongA(focus_window, GWL_STYLE);
4752 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4753 focus_style, style, i);
4754 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4755 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4756 focus_exstyle, style, i);
4758 GetWindowRect(device_window, &r);
4759 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4760 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4761 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4762 else
4763 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4764 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4765 GetClientRect(device_window, &r2);
4766 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4767 GetWindowRect(focus_window, &r);
4768 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4769 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4771 device_desc.flags = 0;
4772 hr = reset_device(device, &device_desc);
4773 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4775 style = GetWindowLongA(device_window, GWL_STYLE);
4776 expected_style = device_style | tests[i].style;
4777 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4778 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4779 expected_style, style, i);
4780 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4781 expected_style = device_exstyle | tests[i].exstyle;
4782 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4783 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4784 expected_style, style, i);
4786 style = GetWindowLongA(focus_window, GWL_STYLE);
4787 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4788 focus_style, style, i);
4789 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4790 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4791 focus_exstyle, style, i);
4793 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4794 hr = reset_device(device, &device_desc);
4795 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4796 ret = SetForegroundWindow(GetDesktopWindow());
4797 ok(ret, "Failed to set foreground window.\n");
4799 style = GetWindowLongA(device_window, GWL_STYLE);
4800 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4801 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4802 expected_style, style);
4803 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4804 expected_style = device_exstyle | tests[i].exstyle;
4805 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4806 expected_style, style);
4808 style = GetWindowLongA(focus_window, GWL_STYLE);
4809 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4810 focus_style, style);
4811 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4812 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4813 focus_exstyle, style);
4815 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4816 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4817 * like a good idea to reset it first. */
4818 ShowWindow(focus_window, SW_MINIMIZE);
4819 ShowWindow(focus_window, SW_RESTORE);
4820 ret = SetForegroundWindow(focus_window);
4821 ok(ret, "Failed to set foreground window.\n");
4822 flush_events();
4823 hr = reset_device(device, &device_desc);
4824 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4826 ref = IDirect3DDevice9_Release(device);
4827 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4829 DestroyWindow(device_window);
4830 DestroyWindow(focus_window);
4832 IDirect3D9_Release(d3d9);
4835 static const POINT *expect_pos;
4837 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4839 if (message == WM_MOUSEMOVE)
4841 if (expect_pos && expect_pos->x && expect_pos->y)
4843 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4845 ClientToScreen(window, &p);
4846 if (expect_pos->x == p.x && expect_pos->y == p.y)
4847 ++expect_pos;
4851 return DefWindowProcA(window, message, wparam, lparam);
4854 static void test_cursor_pos(void)
4856 IDirect3DSurface9 *cursor;
4857 IDirect3DDevice9 *device;
4858 WNDCLASSA wc = {0};
4859 IDirect3D9 *d3d9;
4860 UINT refcount;
4861 HWND window;
4862 HRESULT hr;
4863 BOOL ret;
4865 /* Note that we don't check for movement we're not supposed to receive.
4866 * That's because it's hard to distinguish from the user accidentally
4867 * moving the mouse. */
4868 static const POINT points[] =
4870 {50, 50},
4871 {75, 75},
4872 {100, 100},
4873 {125, 125},
4874 {150, 150},
4875 {125, 125},
4876 {150, 150},
4877 {150, 150},
4878 {0, 0},
4881 wc.lpfnWndProc = test_cursor_proc;
4882 wc.lpszClassName = "d3d9_test_cursor_wc";
4883 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4884 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_POPUP | WS_SYSMENU,
4885 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4886 ShowWindow(window, SW_SHOW);
4887 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4888 ok(!!d3d9, "Failed to create a D3D object.\n");
4890 device = create_device(d3d9, window, NULL);
4891 if (!device)
4893 skip("Failed to create a D3D device, skipping tests.\n");
4894 goto done;
4897 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4898 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4899 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4900 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4901 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4902 IDirect3DSurface9_Release(cursor);
4903 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4904 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4906 flush_events();
4907 expect_pos = points;
4909 ret = SetCursorPos(50, 50);
4910 ok(ret, "Failed to set cursor position.\n");
4911 flush_events();
4913 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4914 flush_events();
4915 /* SetCursorPosition() eats duplicates. */
4916 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4917 flush_events();
4919 ret = SetCursorPos(100, 100);
4920 ok(ret, "Failed to set cursor position.\n");
4921 flush_events();
4922 /* Even if the position was set with SetCursorPos(). */
4923 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4924 flush_events();
4926 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4927 flush_events();
4928 ret = SetCursorPos(150, 150);
4929 ok(ret, "Failed to set cursor position.\n");
4930 flush_events();
4931 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4932 flush_events();
4934 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4935 flush_events();
4936 /* SetCursorPos() doesn't. */
4937 ret = SetCursorPos(150, 150);
4938 ok(ret, "Failed to set cursor position.\n");
4939 flush_events();
4941 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4942 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4944 refcount = IDirect3DDevice9_Release(device);
4945 ok(!refcount, "Device has %u references left.\n", refcount);
4946 done:
4947 DestroyWindow(window);
4948 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4949 IDirect3D9_Release(d3d9);
4952 static void test_mode_change(void)
4954 RECT d3d_rect, focus_rect, r;
4955 struct device_desc device_desc;
4956 IDirect3DSurface9 *backbuffer;
4957 IDirect3DDevice9 *device;
4958 D3DSURFACE_DESC desc;
4959 IDirect3D9 *d3d9;
4960 DEVMODEW devmode;
4961 ULONG refcount;
4962 UINT adapter_mode_count, i;
4963 HRESULT hr;
4964 DWORD ret;
4965 LONG change_ret;
4966 D3DDISPLAYMODE d3ddm;
4967 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4969 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4970 ok(!!d3d9, "Failed to create a D3D object.\n");
4972 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4973 for (i = 0; i < adapter_mode_count; ++i)
4975 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4976 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4978 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4979 continue;
4980 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4981 * refuses to create a device at these sizes. */
4982 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4983 continue;
4985 if (!user32_width)
4987 user32_width = d3ddm.Width;
4988 user32_height = d3ddm.Height;
4989 continue;
4992 /* Make sure the d3d mode is smaller in width or height and at most
4993 * equal in the other dimension than the mode passed to
4994 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4995 * the ChangeDisplaySettings parameters + 12. */
4996 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4997 continue;
4998 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
5000 d3d_width = d3ddm.Width;
5001 d3d_height = d3ddm.Height;
5002 break;
5004 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
5006 d3d_width = user32_width;
5007 d3d_height = user32_height;
5008 user32_width = d3ddm.Width;
5009 user32_height = d3ddm.Height;
5010 break;
5014 if (!d3d_width)
5016 skip("Could not find adequate modes, skipping mode tests.\n");
5017 IDirect3D9_Release(d3d9);
5018 return;
5021 memset(&devmode, 0, sizeof(devmode));
5022 devmode.dmSize = sizeof(devmode);
5023 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
5024 devmode.dmPelsWidth = user32_width;
5025 devmode.dmPelsHeight = user32_height;
5026 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5027 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5029 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5030 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
5031 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5032 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
5034 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
5035 GetWindowRect(focus_window, &focus_rect);
5037 device_desc.device_window = device_window;
5038 device_desc.width = d3d_width;
5039 device_desc.height = d3d_height;
5040 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5041 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5043 skip("Failed to create a D3D device, skipping tests.\n");
5044 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5045 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5046 goto done;
5049 devmode.dmPelsWidth = user32_width;
5050 devmode.dmPelsHeight = user32_height;
5051 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5052 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5054 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5055 ok(ret, "Failed to get display mode.\n");
5056 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
5057 "Expected resolution %ux%u, got %ux%u.\n",
5058 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
5060 GetWindowRect(device_window, &r);
5061 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
5062 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
5063 GetWindowRect(focus_window, &r);
5064 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
5065 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
5067 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
5068 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
5069 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
5070 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
5071 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
5072 desc.Width, d3d_width);
5073 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
5074 desc.Height, d3d_height);
5075 IDirect3DSurface9_Release(backbuffer);
5077 refcount = IDirect3DDevice9_Release(device);
5078 ok(!refcount, "Device has %u references left.\n", refcount);
5080 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5081 ok(ret, "Failed to get display mode.\n");
5082 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5083 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5084 "Expected resolution %ux%u, got %ux%u.\n",
5085 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5087 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5088 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5090 /* The mode restore also happens when the device was created at the original screen size. */
5092 device_desc.device_window = device_window;
5093 device_desc.width = registry_mode.dmPelsWidth;
5094 device_desc.height = registry_mode.dmPelsHeight;
5095 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5096 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
5098 devmode.dmPelsWidth = user32_width;
5099 devmode.dmPelsHeight = user32_height;
5100 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5101 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5103 refcount = IDirect3DDevice9_Release(device);
5104 ok(!refcount, "Device has %u references left.\n", refcount);
5106 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5107 ok(ret, "Failed to get display mode.\n");
5108 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5109 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5110 "Expected resolution %ux%u, got %ux%u.\n",
5111 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5113 done:
5114 DestroyWindow(device_window);
5115 DestroyWindow(focus_window);
5116 IDirect3D9_Release(d3d9);
5119 static void test_device_window_reset(void)
5121 RECT fullscreen_rect, device_rect, r;
5122 struct device_desc device_desc;
5123 IDirect3DDevice9 *device;
5124 WNDCLASSA wc = {0};
5125 IDirect3D9 *d3d9;
5126 LONG_PTR proc;
5127 HRESULT hr;
5128 ULONG ref;
5130 wc.lpfnWndProc = test_proc;
5131 wc.lpszClassName = "d3d9_test_wndproc_wc";
5132 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5134 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5135 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
5136 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5137 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
5138 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5139 ok(!!d3d9, "Failed to create a D3D object.\n");
5141 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
5142 GetWindowRect(device_window, &device_rect);
5144 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5145 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5146 (LONG_PTR)test_proc, proc);
5147 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5148 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5149 (LONG_PTR)test_proc, proc);
5151 device_desc.device_window = NULL;
5152 device_desc.width = registry_mode.dmPelsWidth;
5153 device_desc.height = registry_mode.dmPelsHeight;
5154 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5155 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5157 skip("Failed to create a D3D device, skipping tests.\n");
5158 goto done;
5161 GetWindowRect(focus_window, &r);
5162 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5163 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5164 GetWindowRect(device_window, &r);
5165 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
5166 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
5168 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5169 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5170 (LONG_PTR)test_proc, proc);
5171 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5172 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5174 device_desc.device_window = device_window;
5175 hr = reset_device(device, &device_desc);
5176 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5178 GetWindowRect(focus_window, &r);
5179 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5180 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5181 GetWindowRect(device_window, &r);
5182 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5183 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5185 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5186 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5187 (LONG_PTR)test_proc, proc);
5188 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5189 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5191 ref = IDirect3DDevice9_Release(device);
5192 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5194 done:
5195 IDirect3D9_Release(d3d9);
5196 DestroyWindow(device_window);
5197 DestroyWindow(focus_window);
5198 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
5201 static void test_reset_resources(void)
5203 IDirect3DSurface9 *surface, *rt;
5204 IDirect3DTexture9 *texture;
5205 IDirect3DDevice9 *device;
5206 IDirect3D9 *d3d9;
5207 unsigned int i;
5208 D3DCAPS9 caps;
5209 HWND window;
5210 HRESULT hr;
5211 ULONG ref;
5213 window = create_window();
5214 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5215 ok(!!d3d9, "Failed to create a D3D object.\n");
5217 if (!(device = create_device(d3d9, window, NULL)))
5219 skip("Failed to create a D3D device, skipping tests.\n");
5220 goto done;
5223 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5224 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5226 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5227 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5228 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5229 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5230 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5231 IDirect3DSurface9_Release(surface);
5233 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5235 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5236 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5237 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5238 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5239 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5240 IDirect3DTexture9_Release(texture);
5241 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5242 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5243 IDirect3DSurface9_Release(surface);
5246 hr = reset_device(device, NULL);
5247 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5249 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5250 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5251 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5252 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5253 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5254 IDirect3DSurface9_Release(surface);
5255 IDirect3DSurface9_Release(rt);
5257 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5259 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5260 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5263 ref = IDirect3DDevice9_Release(device);
5264 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5266 done:
5267 IDirect3D9_Release(d3d9);
5268 DestroyWindow(window);
5271 static void test_set_rt_vp_scissor(void)
5273 IDirect3DStateBlock9 *stateblock;
5274 IDirect3DDevice9 *device;
5275 IDirect3DSurface9 *rt;
5276 IDirect3D9 *d3d9;
5277 D3DVIEWPORT9 vp;
5278 UINT refcount;
5279 HWND window;
5280 HRESULT hr;
5281 RECT rect;
5283 window = create_window();
5284 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5285 ok(!!d3d9, "Failed to create a D3D object.\n");
5286 if (!(device = create_device(d3d9, window, NULL)))
5288 skip("Failed to create a D3D device, skipping tests.\n");
5289 DestroyWindow(window);
5290 return;
5293 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5294 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5295 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5297 hr = IDirect3DDevice9_GetViewport(device, &vp);
5298 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5299 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5300 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5301 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5302 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5303 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5304 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5306 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5307 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5308 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5309 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5311 hr = IDirect3DDevice9_BeginStateBlock(device);
5312 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5314 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5315 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5317 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5318 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5319 IDirect3DStateBlock9_Release(stateblock);
5321 hr = IDirect3DDevice9_GetViewport(device, &vp);
5322 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5323 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5324 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5325 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5326 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5327 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5328 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5330 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5331 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5332 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5333 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5335 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5336 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5338 vp.X = 10;
5339 vp.Y = 20;
5340 vp.Width = 30;
5341 vp.Height = 40;
5342 vp.MinZ = 0.25f;
5343 vp.MaxZ = 0.75f;
5344 hr = IDirect3DDevice9_SetViewport(device, &vp);
5345 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5347 SetRect(&rect, 50, 60, 70, 80);
5348 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5349 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5351 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5352 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5354 hr = IDirect3DDevice9_GetViewport(device, &vp);
5355 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5356 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5357 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5358 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5359 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5360 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5361 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5363 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5364 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5365 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5366 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5368 IDirect3DSurface9_Release(rt);
5369 refcount = IDirect3DDevice9_Release(device);
5370 ok(!refcount, "Device has %u references left.\n", refcount);
5371 IDirect3D9_Release(d3d9);
5372 DestroyWindow(window);
5375 static void test_volume_get_container(void)
5377 IDirect3DVolumeTexture9 *texture = NULL;
5378 IDirect3DVolume9 *volume = NULL;
5379 IDirect3DDevice9 *device;
5380 IUnknown *container;
5381 IDirect3D9 *d3d9;
5382 ULONG refcount;
5383 D3DCAPS9 caps;
5384 HWND window;
5385 HRESULT hr;
5387 window = create_window();
5388 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5389 ok(!!d3d9, "Failed to create a D3D object.\n");
5390 if (!(device = create_device(d3d9, window, NULL)))
5392 skip("Failed to create a D3D device, skipping tests.\n");
5393 IDirect3D9_Release(d3d9);
5394 DestroyWindow(window);
5395 return;
5398 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5399 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5400 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5402 skip("No volume texture support, skipping tests.\n");
5403 IDirect3DDevice9_Release(device);
5404 IDirect3D9_Release(d3d9);
5405 DestroyWindow(window);
5406 return;
5409 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5410 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5411 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5412 ok(!!texture, "Got unexpected texture %p.\n", texture);
5414 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5415 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5416 ok(!!volume, "Got unexpected volume %p.\n", volume);
5418 /* These should work... */
5419 container = NULL;
5420 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5421 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5422 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5423 IUnknown_Release(container);
5425 container = NULL;
5426 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5427 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5428 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5429 IUnknown_Release(container);
5431 container = NULL;
5432 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5433 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5434 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5435 IUnknown_Release(container);
5437 container = NULL;
5438 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5439 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5440 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5441 IUnknown_Release(container);
5443 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5444 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5445 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5446 ok(!container, "Got unexpected container %p.\n", container);
5448 IDirect3DVolume9_Release(volume);
5449 IDirect3DVolumeTexture9_Release(texture);
5450 refcount = IDirect3DDevice9_Release(device);
5451 ok(!refcount, "Device has %u references left.\n", refcount);
5452 IDirect3D9_Release(d3d9);
5453 DestroyWindow(window);
5456 static void test_volume_resource(void)
5458 IDirect3DVolumeTexture9 *texture;
5459 IDirect3DResource9 *resource;
5460 IDirect3DVolume9 *volume;
5461 IDirect3DDevice9 *device;
5462 IDirect3D9 *d3d9;
5463 ULONG refcount;
5464 D3DCAPS9 caps;
5465 HWND window;
5466 HRESULT hr;
5468 window = create_window();
5469 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5470 ok(!!d3d9, "Failed to create a D3D object.\n");
5471 if (!(device = create_device(d3d9, window, NULL)))
5473 skip("Failed to create a D3D device, skipping tests.\n");
5474 IDirect3D9_Release(d3d9);
5475 DestroyWindow(window);
5476 return;
5479 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5480 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5481 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5483 skip("No volume texture support, skipping tests.\n");
5484 IDirect3DDevice9_Release(device);
5485 IDirect3D9_Release(d3d9);
5486 DestroyWindow(window);
5487 return;
5490 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5491 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5492 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5493 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5494 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5495 IDirect3DVolumeTexture9_Release(texture);
5497 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5498 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5500 IDirect3DVolume9_Release(volume);
5501 refcount = IDirect3DDevice9_Release(device);
5502 ok(!refcount, "Device has %u references left.\n", refcount);
5503 IDirect3D9_Release(d3d9);
5504 DestroyWindow(window);
5507 static void test_vb_lock_flags(void)
5509 static const struct
5511 DWORD flags;
5512 const char *debug_string;
5513 HRESULT win7_result;
5515 test_data[] =
5517 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5518 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5519 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5520 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5521 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5522 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5523 /* Completely bogus flags aren't an error. */
5524 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5526 IDirect3DVertexBuffer9 *buffer;
5527 IDirect3DDevice9 *device;
5528 IDirect3D9 *d3d9;
5529 unsigned int i;
5530 ULONG refcount;
5531 HWND window;
5532 HRESULT hr;
5533 void *data;
5535 window = create_window();
5536 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5537 ok(!!d3d9, "Failed to create a D3D object.\n");
5538 if (!(device = create_device(d3d9, window, NULL)))
5540 skip("Failed to create a D3D device, skipping tests.\n");
5541 IDirect3D9_Release(d3d9);
5542 DestroyWindow(window);
5543 return;
5546 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5547 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5549 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5551 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5552 /* Windows XP always returns D3D_OK even with flags that don't make
5553 * sense. Windows 7 returns an error. At least one game (Shaiya)
5554 * depends on the Windows XP result, so mark the Windows 7 behavior as
5555 * broken. */
5556 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5557 hr, test_data[i].debug_string);
5558 if (SUCCEEDED(hr))
5560 ok(!!data, "Got unexpected data %p.\n", data);
5561 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5562 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5566 IDirect3DVertexBuffer9_Release(buffer);
5567 refcount = IDirect3DDevice9_Release(device);
5568 ok(!refcount, "Device has %u references left.\n", refcount);
5569 IDirect3D9_Release(d3d9);
5570 DestroyWindow(window);
5573 static const char *debug_d3dpool(D3DPOOL pool)
5575 switch (pool)
5577 case D3DPOOL_DEFAULT:
5578 return "D3DPOOL_DEFAULT";
5579 case D3DPOOL_SYSTEMMEM:
5580 return "D3DPOOL_SYSTEMMEM";
5581 case D3DPOOL_SCRATCH:
5582 return "D3DPOOL_SCRATCH";
5583 case D3DPOOL_MANAGED:
5584 return "D3DPOOL_MANAGED";
5585 default:
5586 return "unknown pool";
5590 static void test_vertex_buffer_alignment(void)
5592 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5593 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5594 IDirect3DVertexBuffer9 *buffer = NULL;
5595 const unsigned int align = 16;
5596 IDirect3DDevice9 *device;
5597 unsigned int i, j;
5598 IDirect3D9 *d3d9;
5599 ULONG refcount;
5600 HWND window;
5601 HRESULT hr;
5602 void *data;
5604 window = create_window();
5605 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5606 ok(!!d3d9, "Failed to create a D3D object.\n");
5607 if (!(device = create_device(d3d9, window, NULL)))
5609 skip("Failed to create a D3D device, skipping tests.\n");
5610 IDirect3D9_Release(d3d9);
5611 DestroyWindow(window);
5612 return;
5615 for (i = 0; i < ARRAY_SIZE(sizes); ++i)
5617 for (j = 0; j < ARRAY_SIZE(pools); ++j)
5619 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5620 if (pools[j] == D3DPOOL_SCRATCH)
5621 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5622 else
5623 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5624 debug_d3dpool(pools[j]), sizes[i], hr);
5625 if (FAILED(hr))
5626 continue;
5628 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5629 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5630 ok(!((DWORD_PTR)data & (align - 1)),
5631 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5632 data, align, sizes[i], debug_d3dpool(pools[j]));
5633 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5634 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5635 IDirect3DVertexBuffer9_Release(buffer);
5639 refcount = IDirect3DDevice9_Release(device);
5640 ok(!refcount, "Device has %u references left.\n", refcount);
5641 IDirect3D9_Release(d3d9);
5642 DestroyWindow(window);
5645 static void test_query_support(void)
5647 static const D3DQUERYTYPE queries[] =
5649 D3DQUERYTYPE_VCACHE,
5650 D3DQUERYTYPE_RESOURCEMANAGER,
5651 D3DQUERYTYPE_VERTEXSTATS,
5652 D3DQUERYTYPE_EVENT,
5653 D3DQUERYTYPE_OCCLUSION,
5654 D3DQUERYTYPE_TIMESTAMP,
5655 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5656 D3DQUERYTYPE_TIMESTAMPFREQ,
5657 D3DQUERYTYPE_PIPELINETIMINGS,
5658 D3DQUERYTYPE_INTERFACETIMINGS,
5659 D3DQUERYTYPE_VERTEXTIMINGS,
5660 D3DQUERYTYPE_PIXELTIMINGS,
5661 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5662 D3DQUERYTYPE_CACHEUTILIZATION,
5664 IDirect3DQuery9 *query = NULL;
5665 IDirect3DDevice9 *device;
5666 IDirect3D9 *d3d9;
5667 unsigned int i;
5668 ULONG refcount;
5669 BOOL supported;
5670 HWND window;
5671 HRESULT hr;
5673 window = create_window();
5674 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5675 ok(!!d3d9, "Failed to create a D3D object.\n");
5676 if (!(device = create_device(d3d9, window, NULL)))
5678 skip("Failed to create a D3D device, skipping tests.\n");
5679 IDirect3D9_Release(d3d9);
5680 DestroyWindow(window);
5681 return;
5684 for (i = 0; i < ARRAY_SIZE(queries); ++i)
5686 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5687 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5689 supported = hr == D3D_OK;
5691 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5692 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5694 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5695 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5697 if (query)
5699 IDirect3DQuery9_Release(query);
5700 query = NULL;
5704 for (i = 0; i < 40; ++i)
5706 /* Windows 10 17.09 (build 16299.19) added an undocumented query with an enum value of 0x16 (=22).
5707 * It returns D3D_OK when asking for support and E_FAIL when trying to actually create it. */
5708 if ((D3DQUERYTYPE_VCACHE <= i && i <= D3DQUERYTYPE_MEMORYPRESSURE) || i == 0x16)
5709 continue;
5711 hr = IDirect3DDevice9_CreateQuery(device, i, NULL);
5712 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5714 query = (IDirect3DQuery9 *)0xdeadbeef;
5715 hr = IDirect3DDevice9_CreateQuery(device, i, &query);
5716 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5717 ok(query == (IDirect3DQuery9 *)0xdeadbeef, "Got unexpected query %p.\n", query);
5720 refcount = IDirect3DDevice9_Release(device);
5721 ok(!refcount, "Device has %u references left.\n", refcount);
5722 IDirect3D9_Release(d3d9);
5723 DestroyWindow(window);
5726 static void test_occlusion_query(void)
5728 static const float quad[] =
5730 -1.0f, -1.0f, 0.0f,
5731 -1.0f, 1.0f, 0.0f,
5732 1.0f, 1.0f, 0.0f,
5733 1.0f, -1.0f, 0.0f,
5735 unsigned int data_size, i, count;
5736 struct device_desc device_desc;
5737 IDirect3DQuery9 *query = NULL;
5738 IDirect3DDevice9 *device;
5739 IDirect3DSurface9 *rt;
5740 IDirect3D9 *d3d9;
5741 D3DVIEWPORT9 vp;
5742 ULONG refcount;
5743 D3DCAPS9 caps;
5744 HWND window;
5745 HRESULT hr;
5746 union
5748 WORD word[4];
5749 DWORD dword[2];
5750 UINT64 uint;
5751 } data, expected;
5752 BOOL broken_occlusion = FALSE;
5753 expected.uint = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5755 window = create_window();
5756 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5757 ok(!!d3d9, "Failed to create a D3D object.\n");
5758 device_desc.device_window = window;
5759 device_desc.width = registry_mode.dmPelsWidth;
5760 device_desc.height = registry_mode.dmPelsHeight;
5761 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5762 if (!(device = create_device(d3d9, window, &device_desc)))
5764 skip("Failed to create a D3D device, skipping tests.\n");
5765 IDirect3D9_Release(d3d9);
5766 DestroyWindow(window);
5767 return;
5770 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5771 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5772 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5773 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5774 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5775 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5777 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5778 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5779 if (!query)
5781 skip("Occlusion queries are not supported, skipping tests.\n");
5782 IDirect3DDevice9_Release(device);
5783 IDirect3D9_Release(d3d9);
5784 DestroyWindow(window);
5785 return;
5788 data_size = IDirect3DQuery9_GetDataSize(query);
5789 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5791 memset(&data, 0xff, sizeof(data));
5792 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5793 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5794 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5795 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5796 ok(data.dword[0] == 0xdddddddd && data.dword[1] == 0xffffffff,
5797 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5799 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5800 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5801 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5802 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5803 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5804 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5806 data.dword[0] = 0x12345678;
5807 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5808 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5809 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5810 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5811 if (hr == D3D_OK)
5812 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5814 hr = IDirect3DDevice9_BeginScene(device);
5815 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5816 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5817 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5818 hr = IDirect3DDevice9_EndScene(device);
5819 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5821 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5822 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5823 for (i = 0; i < 500; ++i)
5825 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5826 break;
5827 Sleep(10);
5829 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5831 memset(&data, 0xff, sizeof(data));
5832 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5833 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5834 ok(data.dword[0] == expected.dword[0] || broken(!data.dword[0]),
5835 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5836 if (!data.dword[0])
5838 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5839 broken_occlusion = TRUE;
5842 memset(&data, 0xff, sizeof(data));
5843 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5844 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5845 if (!broken_occlusion)
5846 ok(data.word[0] == expected.word[0],
5847 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5848 ok(data.word[1] == 0xffff,
5849 "Data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5851 memset(&data, 0xf0, sizeof(data));
5852 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5853 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5854 if (!broken_occlusion)
5855 ok(data.dword[0] == expected.dword[0],
5856 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5857 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5858 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5859 on AMD and Nvidia respectively). */
5860 if (0)
5862 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5863 data.dword[1]);
5866 memset(&data, 0xff, sizeof(data));
5867 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5868 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5869 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5871 /* This crashes on Windows. */
5872 if (0)
5874 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5875 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5878 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5879 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5880 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5881 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5882 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5883 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5885 if (broken_occlusion)
5886 goto done;
5888 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5889 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5891 vp.X = 0;
5892 vp.Y = 0;
5893 vp.Width = min(caps.MaxTextureWidth, 8192);
5894 vp.Height = min(caps.MaxTextureHeight, 8192);
5895 vp.MinZ = 0.0f;
5896 vp.MaxZ = 1.0f;
5897 hr = IDirect3DDevice9_SetViewport(device, &vp);
5898 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5900 hr = IDirect3DDevice9_CreateRenderTarget(device, vp.Width, vp.Height,
5901 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5902 if (FAILED(hr))
5904 skip("Failed to create render target (width %u, height %u), hr %#x.\n", vp.Width, vp.Height, hr);
5905 goto done;
5907 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5908 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5909 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5910 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
5911 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5913 expected.uint = vp.Width * vp.Height;
5914 count = ((((UINT64)~0u) + 1) / expected.uint) + 1;
5915 expected.uint *= count;
5917 trace("Expects 0x%08x%08x samples.\n", expected.dword[1], expected.dword[0]);
5919 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5920 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5921 hr = IDirect3DDevice9_BeginScene(device);
5922 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5923 for (i = 0; i < count; i++)
5925 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5926 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5928 hr = IDirect3DDevice9_EndScene(device);
5929 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5930 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5931 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5933 for (i = 0; i < 500; ++i)
5935 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5936 break;
5937 Sleep(10);
5939 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5941 memset(&data, 0xff, sizeof(data));
5942 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5943 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5944 ok((data.dword[0] == expected.dword[0] && data.dword[1] == expected.dword[1])
5945 || (data.dword[0] == 0xffffffff && !data.dword[1])
5946 || broken(data.dword[0] < 0xffffffff && !data.dword[1]),
5947 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5949 hr = IDirect3DDevice9_BeginScene(device);
5950 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5951 for (i = 0; i < 50000; ++i)
5953 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5954 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5955 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5956 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5958 hr = IDirect3DDevice9_EndScene(device);
5959 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5961 for (i = 0; i < 500; ++i)
5963 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) == S_OK)
5964 break;
5965 Sleep(10);
5967 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5969 memset(&data, 0xff, sizeof(data));
5970 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5971 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5972 ok(data.dword[0] == 0 && data.dword[1] == 0,
5973 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5975 IDirect3DSurface9_Release(rt);
5977 done:
5978 IDirect3DQuery9_Release(query);
5979 refcount = IDirect3DDevice9_Release(device);
5980 ok(!refcount, "Device has %u references left.\n", refcount);
5981 IDirect3D9_Release(d3d9);
5982 DestroyWindow(window);
5985 static void test_timestamp_query(void)
5987 static const float quad[] =
5989 -1.0f, -1.0f, 0.0f,
5990 -1.0f, 1.0f, 0.0f,
5991 1.0f, 1.0f, 0.0f,
5992 1.0f, -1.0f, 0.0f,
5994 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5995 unsigned int data_size, i;
5996 IDirect3DDevice9 *device;
5997 IDirect3D9 *d3d9;
5998 ULONG refcount;
5999 HWND window;
6000 HRESULT hr;
6001 DWORD timestamp[2], freq[2];
6002 WORD disjoint[2];
6004 window = create_window();
6005 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
6006 ok(!!d3d9, "Failed to create a D3D object.\n");
6007 if (!(device = create_device(d3d9, window, NULL)))
6009 skip("Failed to create a D3D device, skipping tests.\n");
6010 IDirect3D9_Release(d3d9);
6011 DestroyWindow(window);
6012 return;
6015 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
6016 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
6017 if (FAILED(hr))
6019 skip("Timestamp queries are not supported, skipping tests.\n");
6020 IDirect3DDevice9_Release(device);
6021 IDirect3D9_Release(d3d9);
6022 DestroyWindow(window);
6023 return;
6025 data_size = IDirect3DQuery9_GetDataSize(freq_query);
6026 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
6028 memset(freq, 0xff, sizeof(freq));
6029 hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH);
6030 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6031 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
6032 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6033 ok(freq[0] == 0xdddddddd && freq[1] == 0xffffffff,
6034 "Got unexpected query result 0x%08x%08x.\n", freq[1], freq[0]);
6036 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
6037 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6038 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
6039 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
6041 memset(disjoint, 0xff, sizeof(disjoint));
6042 hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH);
6043 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6044 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
6045 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6046 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xffff,
6047 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
6048 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(DWORD), D3DGETDATA_FLUSH);
6049 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6050 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xdddd,
6051 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
6053 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
6054 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6055 data_size = IDirect3DQuery9_GetDataSize(query);
6056 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
6058 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
6059 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6060 for (i = 0; i < 500; ++i)
6062 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6063 break;
6064 Sleep(10);
6066 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6068 memset(freq, 0xff, sizeof(freq));
6069 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
6070 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6071 ok(freq[1] == 0xffffffff,
6072 "Freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
6073 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
6074 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6075 ok(freq[1] != 0xffffffff, "High bytes of freq were not modified (0x%.8x).\n",
6076 freq[1]);
6078 memset(timestamp, 0xff, sizeof(timestamp));
6079 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
6080 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6081 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6082 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6083 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xffffffff,
6084 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6085 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6086 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6087 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xdddddddd,
6088 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6090 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
6091 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6092 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
6093 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6094 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
6095 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6097 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6098 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6100 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6101 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
6102 hr = IDirect3DDevice9_BeginScene(device);
6103 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6104 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6105 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6106 hr = IDirect3DDevice9_EndScene(device);
6107 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6109 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6110 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6111 for (i = 0; i < 500; ++i)
6113 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6114 break;
6115 Sleep(10);
6117 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6119 memset(timestamp, 0xff, sizeof(timestamp));
6120 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6121 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6122 ok(timestamp[1] == 0xffffffff,
6123 "Timestamp was modified outside of the expected size (0x%.8x).\n",
6124 timestamp[1]);
6126 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
6127 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6128 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6129 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6130 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6131 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6133 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
6134 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6135 for (i = 0; i < 500; ++i)
6137 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6138 break;
6139 Sleep(10);
6141 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6143 memset(disjoint, 0xff, sizeof(disjoint));
6144 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
6145 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6146 ok(disjoint[1] == 0xffff,
6147 "Disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
6148 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
6149 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6150 ok(disjoint[1] != 0xffff, "High bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
6152 /* It's not strictly necessary for the TIMESTAMP query to be inside
6153 * a TIMESTAMP_DISJOINT query. */
6154 hr = IDirect3DDevice9_BeginScene(device);
6155 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6156 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6157 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6158 hr = IDirect3DDevice9_EndScene(device);
6159 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6161 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6162 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6163 for (i = 0; i < 500; ++i)
6165 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6166 break;
6167 Sleep(10);
6169 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6170 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6171 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6173 IDirect3DQuery9_Release(query);
6174 IDirect3DQuery9_Release(disjoint_query);
6175 IDirect3DQuery9_Release(freq_query);
6176 refcount = IDirect3DDevice9_Release(device);
6177 ok(!refcount, "Device has %u references left.\n", refcount);
6178 IDirect3D9_Release(d3d9);
6179 DestroyWindow(window);
6182 static void test_get_set_vertex_shader(void)
6184 IDirect3DVertexShader9 *current_shader = NULL;
6185 IDirect3DVertexShader9 *shader = NULL;
6186 const IDirect3DVertexShader9Vtbl *shader_vtbl;
6187 IDirect3DDevice9 *device;
6188 ULONG refcount, i;
6189 IDirect3D9 *d3d;
6190 D3DCAPS9 caps;
6191 HWND window;
6192 HRESULT hr;
6194 window = create_window();
6195 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6196 ok(!!d3d, "Failed to create a D3D object.\n");
6197 if (!(device = create_device(d3d, window, NULL)))
6199 skip("Failed to create a D3D device, skipping tests.\n");
6200 IDirect3D9_Release(d3d);
6201 DestroyWindow(window);
6202 return;
6205 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6206 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6207 if (!(caps.VertexShaderVersion & 0xffff))
6209 skip("No vertex shader support, skipping tests.\n");
6210 IDirect3DDevice9_Release(device);
6211 IDirect3D9_Release(d3d);
6212 DestroyWindow(window);
6213 return;
6216 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
6217 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6218 ok(!!shader, "Got unexpected shader %p.\n", shader);
6220 /* SetVertexShader() should not touch the shader's refcount. */
6221 i = get_refcount((IUnknown *)shader);
6222 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6223 refcount = get_refcount((IUnknown *)shader);
6224 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6225 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6227 /* GetVertexShader() should increase the shader's refcount by one. */
6228 i = refcount + 1;
6229 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
6230 refcount = get_refcount((IUnknown *)shader);
6231 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
6232 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6233 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6234 IDirect3DVertexShader9_Release(current_shader);
6236 /* SetVertexShader() with a bogus shader vtbl */
6237 shader_vtbl = shader->lpVtbl;
6238 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
6239 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6240 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6241 shader->lpVtbl = NULL;
6242 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6243 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6244 shader->lpVtbl = shader_vtbl;
6246 IDirect3DVertexShader9_Release(shader);
6247 refcount = IDirect3DDevice9_Release(device);
6248 ok(!refcount, "Device has %u references left.\n", refcount);
6249 IDirect3D9_Release(d3d);
6250 DestroyWindow(window);
6253 static void test_vertex_shader_constant(void)
6255 static const float d[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6256 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6257 IDirect3DDevice9 *device;
6258 struct device_desc desc;
6259 DWORD consts_swvp;
6260 IDirect3D9 *d3d;
6261 ULONG refcount;
6262 D3DCAPS9 caps;
6263 DWORD consts;
6264 HWND window;
6265 HRESULT hr;
6267 window = create_window();
6268 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6269 ok(!!d3d, "Failed to create a D3D object.\n");
6270 if (!(device = create_device(d3d, window, NULL)))
6272 skip("Failed to create a D3D device, skipping tests.\n");
6273 IDirect3D9_Release(d3d);
6274 DestroyWindow(window);
6275 return;
6278 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6279 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6280 if (!(caps.VertexShaderVersion & 0xffff))
6282 skip("No vertex shader support, skipping tests.\n");
6283 IDirect3DDevice9_Release(device);
6284 IDirect3D9_Release(d3d);
6285 DestroyWindow(window);
6286 return;
6288 consts = caps.MaxVertexShaderConst;
6290 /* A simple check that the stuff works at all. */
6291 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
6292 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6294 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
6295 * consts from MAX - 1. */
6296 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
6297 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6298 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6299 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6300 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6301 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6302 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6303 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6305 /* Constant -1. */
6306 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
6307 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6309 refcount = IDirect3DDevice9_Release(device);
6310 ok(!refcount, "Device has %u references left.\n", refcount);
6312 desc.device_window = window;
6313 desc.width = 640;
6314 desc.height = 480;
6315 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6317 if (!(device = create_device(d3d, window, &desc)))
6319 skip("Failed to create a D3D device, skipping tests.\n");
6320 IDirect3D9_Release(d3d);
6321 DestroyWindow(window);
6322 return;
6324 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6325 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6326 consts_swvp = caps.MaxVertexShaderConst;
6327 todo_wine
6328 ok(consts_swvp == 8192, "Unexpected consts_swvp %u.\n", consts_swvp);
6330 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6331 todo_wine
6332 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6333 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6334 todo_wine
6335 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6336 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6337 todo_wine
6338 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6339 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6340 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6341 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp, c, 1);
6342 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6344 refcount = IDirect3DDevice9_Release(device);
6345 ok(!refcount, "Device has %u references left.\n", refcount);
6347 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6348 if (!(device = create_device(d3d, window, &desc)))
6350 skip("Failed to create a D3D device, skipping tests.\n");
6351 IDirect3D9_Release(d3d);
6352 DestroyWindow(window);
6353 return;
6355 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6356 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6357 ok(consts == caps.MaxVertexShaderConst, "Unexpected caps.MaxVertexShaderConst %u, consts %u.\n",
6358 caps.MaxVertexShaderConst, consts);
6360 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6361 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6362 todo_wine
6363 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6364 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6365 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6367 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 1);
6369 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6370 todo_wine
6371 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6372 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6373 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6375 refcount = IDirect3DDevice9_Release(device);
6376 ok(!refcount, "Device has %u references left.\n", refcount);
6378 IDirect3D9_Release(d3d);
6379 DestroyWindow(window);
6382 static void test_get_set_pixel_shader(void)
6384 IDirect3DPixelShader9 *current_shader = NULL;
6385 IDirect3DPixelShader9 *shader = NULL;
6386 const IDirect3DPixelShader9Vtbl *shader_vtbl;
6387 IDirect3DDevice9 *device;
6388 ULONG refcount, i;
6389 IDirect3D9 *d3d;
6390 D3DCAPS9 caps;
6391 HWND window;
6392 HRESULT hr;
6394 window = create_window();
6395 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6396 ok(!!d3d, "Failed to create a D3D object.\n");
6397 if (!(device = create_device(d3d, window, NULL)))
6399 skip("Failed to create a D3D device, skipping tests.\n");
6400 IDirect3D9_Release(d3d);
6401 DestroyWindow(window);
6402 return;
6405 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6406 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6407 if (!(caps.PixelShaderVersion & 0xffff))
6409 skip("No pixel shader support, skipping tests.\n");
6410 IDirect3DDevice9_Release(device);
6411 IDirect3D9_Release(d3d);
6412 DestroyWindow(window);
6413 return;
6416 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
6417 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6418 ok(!!shader, "Got unexpected shader %p.\n", shader);
6420 /* SetPixelShader() should not touch the shader's refcount. */
6421 i = get_refcount((IUnknown *)shader);
6422 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6423 refcount = get_refcount((IUnknown *)shader);
6424 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6425 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6427 /* GetPixelShader() should increase the shader's refcount by one. */
6428 i = refcount + 1;
6429 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6430 refcount = get_refcount((IUnknown *)shader);
6431 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6432 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6433 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6434 IDirect3DPixelShader9_Release(current_shader);
6436 /* SetPixelShader() with a bogus shader vtbl */
6437 shader_vtbl = shader->lpVtbl;
6438 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6439 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6440 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6441 shader->lpVtbl = NULL;
6442 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6443 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6444 shader->lpVtbl = shader_vtbl;
6446 IDirect3DPixelShader9_Release(shader);
6447 refcount = IDirect3DDevice9_Release(device);
6448 ok(!refcount, "Device has %u references left.\n", refcount);
6449 IDirect3D9_Release(d3d);
6450 DestroyWindow(window);
6453 static void test_pixel_shader_constant(void)
6455 static const float d[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6456 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6457 IDirect3DDevice9 *device;
6458 DWORD consts = 0;
6459 IDirect3D9 *d3d;
6460 ULONG refcount;
6461 D3DCAPS9 caps;
6462 HWND window;
6463 HRESULT hr;
6465 window = create_window();
6466 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6467 ok(!!d3d, "Failed to create a D3D object.\n");
6468 if (!(device = create_device(d3d, window, NULL)))
6470 skip("Failed to create a D3D device, skipping tests.\n");
6471 IDirect3D9_Release(d3d);
6472 DestroyWindow(window);
6473 return;
6476 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6477 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6478 if (!(caps.PixelShaderVersion & 0xffff))
6480 skip("No pixel shader support, skipping tests.\n");
6481 IDirect3DDevice9_Release(device);
6482 IDirect3D9_Release(d3d);
6483 DestroyWindow(window);
6484 return;
6487 /* A simple check that the stuff works at all. */
6488 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6489 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6491 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6492 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6493 consts = consts - 1;
6494 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6496 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6497 * pointless given the way the constant limit was determined. */
6498 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6499 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6501 /* Constant -1. */
6502 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6503 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6505 refcount = IDirect3DDevice9_Release(device);
6506 ok(!refcount, "Device has %u references left.\n", refcount);
6507 IDirect3D9_Release(d3d);
6508 DestroyWindow(window);
6511 static void test_unsupported_shaders(void)
6513 static const DWORD vs_3_0[] =
6515 0xfffe0300, /* vs_3_0 */
6516 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6517 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6518 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6519 0x0000ffff, /* end */
6522 #if 0
6523 float4 main(const float4 color : COLOR) : SV_TARGET
6525 float4 o;
6527 o = color;
6529 return o;
6531 #endif
6532 static const DWORD ps_4_0[] =
6534 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6535 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6536 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6537 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6538 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6539 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6540 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6541 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6542 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6543 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6544 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6545 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6546 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6547 0x00000000, 0x00000000, 0x00000000,
6549 #if 0
6550 vs_1_1
6551 dcl_position v0
6552 def c255, 1.0, 1.0, 1.0, 1.0
6553 add r0, v0, c255
6554 mov oPos, r0
6555 #endif
6556 static const DWORD vs_1_255[] =
6558 0xfffe0101,
6559 0x0000001f, 0x80000000, 0x900f0000,
6560 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6561 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6562 0x00000001, 0xc00f0000, 0x80e40000,
6563 0x0000ffff
6565 #if 0
6566 vs_1_1
6567 dcl_position v0
6568 def c256, 1.0, 1.0, 1.0, 1.0
6569 add r0, v0, c256
6570 mov oPos, r0
6571 #endif
6572 static const DWORD vs_1_256[] =
6574 0xfffe0101,
6575 0x0000001f, 0x80000000, 0x900f0000,
6576 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6577 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6578 0x00000001, 0xc00f0000, 0x80e40000,
6579 0x0000ffff
6581 #if 0
6582 vs_3_0
6583 dcl_position v0
6584 dcl_position o0
6585 def c256, 1.0, 1.0, 1.0, 1.0
6586 add r0, v0, c256
6587 mov o0, r0
6588 #endif
6589 static const DWORD vs_3_256[] =
6591 0xfffe0300,
6592 0x0200001f, 0x80000000, 0x900f0000,
6593 0x0200001f, 0x80000000, 0xe00f0000,
6594 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6595 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6596 0x02000001, 0xe00f0000, 0x80e40000,
6597 0x0000ffff
6599 #if 0
6600 /* This shader source generates syntax errors with the native shader assembler
6601 * due to the constant register index values.
6602 * The bytecode was modified by hand to use the intended values. */
6603 vs_3_0
6604 dcl_position v0
6605 dcl_position o0
6606 defi i16, 1, 1, 1, 1
6607 rep i16
6608 add r0, r0, v0
6609 endrep
6610 mov o0, r0
6611 #endif
6612 static const DWORD vs_3_i16[] =
6614 0xfffe0300,
6615 0x0200001f, 0x80000000, 0x900f0000,
6616 0x0200001f, 0x80000000, 0xe00f0000,
6617 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6618 0x01000026, 0xf0e40010,
6619 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6620 0x00000027,
6621 0x02000001, 0xe00f0000, 0x80e40000,
6622 0x0000ffff
6624 #if 0
6625 /* This shader source generates syntax errors with the native shader assembler
6626 * due to the constant register index values.
6627 * The bytecode was modified by hand to use the intended values. */
6628 vs_3_0
6629 dcl_position v0
6630 dcl_position o0
6631 defb b16, true
6632 mov r0, v0
6633 if b16
6634 add r0, r0, v0
6635 endif
6636 mov o0, r0
6637 #endif
6638 static const DWORD vs_3_b16[] =
6640 0xfffe0300,
6641 0x0200001f, 0x80000000, 0x900f0000,
6642 0x0200001f, 0x80000000, 0xe00f0000,
6643 0x0200002f, 0xe00f0810, 0x00000001,
6644 0x02000001, 0x800f0000, 0x90e40000,
6645 0x01000028, 0xe0e40810,
6646 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6647 0x0000002b,
6648 0x02000001, 0xe00f0000, 0x80e40000,
6649 0x0000ffff
6651 #if 0
6652 /* This shader source generates syntax errors with the native shader assembler
6653 * due to the constant register index values.
6654 * The bytecode was modified by hand to use the intended values. */
6655 ps_1_1
6656 def c8, 1.0, 1.0, 1.0, 1.0
6657 add r0, v0, c8
6658 #endif
6659 static const DWORD ps_1_8[] =
6661 0xffff0101,
6662 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6663 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6664 0x0000ffff
6666 #if 0
6667 /* This shader source generates syntax errors with the native shader assembler
6668 * due to the constant register index values.
6669 * The bytecode was modified by hand to use the intended values. */
6670 ps_2_0
6671 def c32, 1.0, 1.0, 1.0, 1.0
6672 add oC0, v0, c32
6673 #endif
6674 static const DWORD ps_2_32[] =
6676 0xffff0200,
6677 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6678 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6679 0x0000ffff
6681 #if 0
6682 /* This shader source generates syntax errors with the native shader assembler
6683 * due to the constant register index values.
6684 * The bytecode was modified by hand to use the intended values. */
6685 ps_3_0
6686 dcl_color0 v0
6687 def c224, 1.0, 1.0, 1.0, 1.0
6688 add oC0, v0, c224
6689 #endif
6690 static const DWORD ps_3_224[] =
6692 0xffff0300,
6693 0x0200001f, 0x8000000a, 0x900f0000,
6694 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6695 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6696 0x0000ffff
6698 #if 0
6699 /* This shader source generates syntax errors with the native shader assembler
6700 * due to the constant register index values.
6701 * The bytecode was modified by hand to use the intended values. */
6702 ps_2_0
6703 defb b0, true
6704 defi i0, 1, 1, 1, 1
6705 rep i0
6706 if b0
6707 add r0, r0, v0
6708 endif
6709 endrep
6710 mov oC0, r0
6711 #endif
6712 static const DWORD ps_2_0_boolint[] =
6714 0xffff0200,
6715 0x0200002f, 0xe00f0800, 0x00000001,
6716 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6717 0x01000026, 0xf0e40000,
6718 0x01000028, 0xe0e40800,
6719 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6720 0x0000002b,
6721 0x00000027,
6722 0x02000001, 0x800f0800, 0x80e40000,
6723 0x0000ffff
6726 IDirect3DVertexShader9 *vs = NULL;
6727 IDirect3DPixelShader9 *ps = NULL;
6728 IDirect3DDevice9 *device;
6729 struct device_desc desc;
6730 IDirect3D9 * d3d;
6731 ULONG refcount;
6732 D3DCAPS9 caps;
6733 HWND window;
6734 HRESULT hr;
6736 window = create_window();
6737 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6738 ok(!!d3d, "Failed to create a D3D object.\n");
6739 if (!(device = create_device(d3d, window, NULL)))
6741 skip("Failed to create a D3D device, skipping tests.\n");
6742 IDirect3D9_Release(d3d);
6743 DestroyWindow(window);
6744 return;
6747 /* These should always fail, regardless of supported shader version. */
6748 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6749 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6750 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6751 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6752 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6753 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6755 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6756 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6757 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6759 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6760 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6761 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6763 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6764 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6766 else
6768 skip("GPU supports SM2+, skipping SM1 test.\n");
6771 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6773 else
6775 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6777 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6778 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6779 IDirect3DVertexShader9_Release(vs);
6780 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6781 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6782 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6783 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6784 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6785 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6786 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6787 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6790 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6792 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6793 goto cleanup;
6795 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6796 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6797 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6798 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6799 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6800 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6801 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6802 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6803 if (ps)
6804 IDirect3DPixelShader9_Release(ps);
6806 refcount = IDirect3DDevice9_Release(device);
6807 ok(!refcount, "Device has %u references left.\n", refcount);
6809 desc.device_window = window;
6810 desc.width = 640;
6811 desc.height = 480;
6812 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6814 if (!(device = create_device(d3d, window, &desc)))
6816 skip("Failed to create a D3D device, skipping tests.\n");
6817 IDirect3D9_Release(d3d);
6818 DestroyWindow(window);
6819 return;
6822 vs = NULL;
6823 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6824 todo_wine
6825 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6826 if (vs)
6827 IDirect3DVertexShader9_Release(vs);
6828 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6829 todo_wine
6830 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6831 if (vs)
6832 IDirect3DVertexShader9_Release(vs);
6834 refcount = IDirect3DDevice9_Release(device);
6835 ok(!refcount, "Device has %u references left.\n", refcount);
6837 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6838 if (!(device = create_device(d3d, window, &desc)))
6840 skip("Failed to create a D3D device, skipping tests.\n");
6841 IDirect3D9_Release(d3d);
6842 DestroyWindow(window);
6843 return;
6845 hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6846 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6848 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6849 todo_wine
6850 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6851 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6852 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6853 if (vs)
6854 IDirect3DVertexShader9_Release(vs);
6856 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6857 todo_wine
6858 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6859 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6860 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6861 if (vs)
6862 IDirect3DVertexShader9_Release(vs);
6864 cleanup:
6865 refcount = IDirect3DDevice9_Release(device);
6866 ok(!refcount, "Device has %u references left.\n", refcount);
6867 IDirect3D9_Release(d3d);
6868 DestroyWindow(window);
6871 /* Test the default texture stage state values */
6872 static void test_texture_stage_states(void)
6874 IDirect3DDevice9 *device;
6875 IDirect3D9 *d3d;
6876 unsigned int i;
6877 ULONG refcount;
6878 D3DCAPS9 caps;
6879 DWORD value;
6880 HWND window;
6881 HRESULT hr;
6883 window = create_window();
6884 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6885 ok(!!d3d, "Failed to create a D3D object.\n");
6886 if (!(device = create_device(d3d, window, NULL)))
6888 skip("Failed to create a D3D device, skipping tests.\n");
6889 IDirect3D9_Release(d3d);
6890 DestroyWindow(window);
6891 return;
6894 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6895 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6897 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6899 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6900 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6901 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6902 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6903 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6904 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6905 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6906 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6907 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6908 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6909 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6910 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6911 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6912 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6913 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6914 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6915 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6916 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6917 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6918 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6919 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6920 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6921 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6922 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6923 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6924 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6925 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6926 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6927 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6928 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6929 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6930 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6931 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6932 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6933 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6934 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6935 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6936 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6937 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6938 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6939 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6940 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6941 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6942 ok(value == D3DTTFF_DISABLE,
6943 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6944 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6945 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6946 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6947 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6948 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6949 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6950 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6951 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6952 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6953 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6954 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6955 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6958 refcount = IDirect3DDevice9_Release(device);
6959 ok(!refcount, "Device has %u references left.\n", refcount);
6960 IDirect3D9_Release(d3d);
6961 DestroyWindow(window);
6964 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6966 IDirect3DCubeTexture9 *texture;
6967 IDirect3D9 *d3d;
6968 HRESULT hr;
6970 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6971 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6972 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6973 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6974 IDirect3D9_Release(d3d);
6975 if (hr != D3D_OK)
6977 skip("No cube mipmap generation support, skipping tests.\n");
6978 return;
6981 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6982 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6983 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6984 IDirect3DCubeTexture9_Release(texture);
6986 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6987 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6988 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6989 IDirect3DCubeTexture9_Release(texture);
6992 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6994 IDirect3DCubeTexture9 *texture;
6995 IDirect3DSurface9 *surface;
6996 D3DSURFACE_DESC desc;
6997 DWORD levels;
6998 HRESULT hr;
6999 D3DCAPS9 caps;
7001 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7002 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7003 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
7004 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
7006 skip("Failed to create cube texture, skipping tests.\n");
7007 return;
7010 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
7011 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
7012 ok(levels == 7, "Got unexpected levels %u.\n", levels);
7013 else
7014 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7016 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
7017 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7018 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
7019 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7020 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
7021 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7023 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
7024 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7025 IDirect3DSurface9_Release(surface);
7026 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
7027 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7028 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
7029 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7031 IDirect3DCubeTexture9_Release(texture);
7034 static void test_cube_textures(void)
7036 IDirect3DCubeTexture9 *texture;
7037 IDirect3DDevice9 *device;
7038 IDirect3D9 *d3d;
7039 ULONG refcount;
7040 D3DCAPS9 caps;
7041 HWND window;
7042 HRESULT hr;
7044 window = create_window();
7045 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7046 ok(!!d3d, "Failed to create a D3D object.\n");
7047 if (!(device = create_device(d3d, window, NULL)))
7049 skip("Failed to create a D3D device, skipping tests.\n");
7050 IDirect3D9_Release(d3d);
7051 DestroyWindow(window);
7052 return;
7055 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7056 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7058 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7060 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7061 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
7062 IDirect3DCubeTexture9_Release(texture);
7063 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7064 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
7065 IDirect3DCubeTexture9_Release(texture);
7066 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7067 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
7068 IDirect3DCubeTexture9_Release(texture);
7070 else
7072 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7073 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
7074 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7075 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
7076 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7077 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
7079 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
7080 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
7081 IDirect3DCubeTexture9_Release(texture);
7083 test_cube_texture_mipmap_gen(device);
7084 test_cube_texture_levels(device);
7086 refcount = IDirect3DDevice9_Release(device);
7087 ok(!refcount, "Device has %u references left.\n", refcount);
7088 IDirect3D9_Release(d3d);
7089 DestroyWindow(window);
7092 static void test_mipmap_gen(void)
7094 static const D3DFORMAT formats[] =
7096 D3DFMT_A8R8G8B8,
7097 D3DFMT_X8R8G8B8,
7098 D3DFMT_A1R5G5B5,
7099 D3DFMT_A4R4G4B4,
7100 D3DFMT_A8,
7101 D3DFMT_L8,
7102 D3DFMT_A8L8,
7103 D3DFMT_V8U8,
7104 D3DFMT_DXT5,
7106 D3DTEXTUREFILTERTYPE filter_type;
7107 IDirect3DTexture9 *texture;
7108 IDirect3DSurface9 *surface;
7109 IDirect3DDevice9 *device;
7110 unsigned int i, count;
7111 D3DSURFACE_DESC desc;
7112 D3DLOCKED_RECT lr;
7113 IDirect3D9 *d3d;
7114 BOOL renderable;
7115 ULONG refcount;
7116 DWORD levels;
7117 HWND window;
7118 HRESULT hr;
7120 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7121 ok(!!d3d, "Failed to create a D3D object.\n");
7123 for (i = 0; i < ARRAY_SIZE(formats); ++i)
7125 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7126 0, D3DRTYPE_TEXTURE, formats[i]);
7127 if (FAILED(hr))
7129 skip("Skipping unsupported format %#x.\n", formats[i]);
7130 continue;
7132 renderable = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7133 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, formats[i]));
7134 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7135 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, formats[i]);
7136 ok((hr == D3D_OK && renderable) || hr == D3DOK_NOAUTOGEN,
7137 "Got unexpected hr %#x for %srenderable format %#x.\n",
7138 hr, renderable ? "" : "non", formats[i]);
7141 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7142 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK)
7144 skip("No mipmap generation support, skipping tests.\n");
7145 IDirect3D9_Release(d3d);
7146 return;
7149 window = create_window();
7150 if (!(device = create_device(d3d, window, NULL)))
7152 skip("Failed to create a D3D device, skipping tests.\n");
7153 IDirect3D9_Release(d3d);
7154 DestroyWindow(window);
7155 return;
7158 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
7159 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7160 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7161 IDirect3DTexture9_Release(texture);
7163 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7164 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7165 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7167 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7168 ok(filter_type == D3DTEXF_LINEAR, "Got unexpected filter_type %#x.\n", filter_type);
7169 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
7170 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7171 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
7172 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7173 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7174 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
7175 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
7176 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7178 levels = IDirect3DTexture9_GetLevelCount(texture);
7179 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7181 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
7183 surface = NULL;
7184 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
7185 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7186 if (surface)
7187 IDirect3DSurface9_Release(surface);
7189 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
7190 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7192 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
7193 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7194 if (SUCCEEDED(hr))
7196 hr = IDirect3DTexture9_UnlockRect(texture, i);
7197 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7200 IDirect3DTexture9_Release(texture);
7202 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
7203 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7204 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7205 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
7206 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7207 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7209 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
7210 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7211 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7212 levels = IDirect3DTexture9_GetLevelCount(texture);
7213 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7214 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7215 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7216 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7217 IDirect3DTexture9_Release(texture);
7219 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7220 D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, 0);
7221 ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr);
7223 for (i = 0; i < ARRAY_SIZE(formats); ++i)
7225 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7226 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, formats[i]);
7227 if (SUCCEEDED(hr))
7229 /* i.e. there is no difference between the D3D_OK and the
7230 * D3DOK_NOAUTOGEN cases. */
7231 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7232 formats[i], D3DPOOL_DEFAULT, &texture, 0);
7233 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7234 count = IDirect3DTexture9_GetLevelCount(texture);
7235 ok(count == 1, "Unexpected level count %u.\n", count);
7236 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7237 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7238 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7239 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7240 ok(filter_type == D3DTEXF_LINEAR, "Got unexpected filter_type %#x.\n", filter_type);
7241 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
7242 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7243 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7244 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
7245 IDirect3DTexture9_Release(texture);
7249 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
7250 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_WRAPANDMIP, D3DRTYPE_TEXTURE, D3DFMT_D16);
7251 if (hr == D3D_OK)
7253 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7254 D3DFMT_D16, D3DPOOL_DEFAULT, &texture, 0);
7255 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7256 count = IDirect3DTexture9_GetLevelCount(texture);
7257 ok(count == 7, "Unexpected level count %u.\n", count);
7258 IDirect3DTexture9_Release(texture);
7260 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
7261 D3DFMT_X8R8G8B8, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_D16);
7262 ok(hr == D3DOK_NOAUTOGEN, "Unexpected hr %#x.\n", hr);
7263 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7264 D3DFMT_D16, D3DPOOL_DEFAULT, &texture, 0);
7265 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7266 count = IDirect3DTexture9_GetLevelCount(texture);
7267 ok(count == 1, "Unexpected level count %u.\n", count);
7268 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7269 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7270 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7271 IDirect3DTexture9_Release(texture);
7273 else
7275 skip("Mipmapping not supported for D3DFMT_D16, skipping test.\n");
7278 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7279 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&texture, 0);
7280 ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr);
7282 refcount = IDirect3DDevice9_Release(device);
7283 ok(!refcount, "Device has %u references left.\n", refcount);
7284 IDirect3D9_Release(d3d);
7285 DestroyWindow(window);
7288 static void test_filter(void)
7290 static const struct
7292 DWORD magfilter, minfilter, mipfilter;
7293 BOOL has_texture;
7294 HRESULT result;
7296 tests[] =
7298 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7299 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7300 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7301 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
7302 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
7304 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7305 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7306 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
7307 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
7309 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7310 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7311 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
7312 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
7313 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
7315 IDirect3DTexture9 *texture;
7316 IDirect3DDevice9 *device;
7317 IDirect3D9 *d3d;
7318 unsigned int i;
7319 ULONG refcount;
7320 DWORD passes;
7321 HWND window;
7322 HRESULT hr;
7324 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7325 ok(!!d3d, "Failed to create a D3D object.\n");
7327 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7328 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7330 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
7331 IDirect3D9_Release(d3d);
7332 return;
7335 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7336 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7338 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
7339 IDirect3D9_Release(d3d);
7340 return;
7343 window = create_window();
7344 if (!(device = create_device(d3d, window, NULL)))
7346 skip("Failed to create a D3D device, skipping tests.\n");
7347 IDirect3D9_Release(d3d);
7348 DestroyWindow(window);
7349 return;
7352 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
7353 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
7354 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7356 /* Needed for ValidateDevice(). */
7357 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7358 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
7360 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7362 if (tests[i].has_texture)
7364 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
7365 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7367 else
7369 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7370 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7373 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
7374 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7375 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
7376 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7377 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
7378 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7380 passes = 0xdeadbeef;
7381 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
7382 ok(hr == tests[i].result,
7383 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
7384 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
7385 tests[i].mipfilter, tests[i].has_texture);
7386 if (SUCCEEDED(hr))
7387 ok(!!passes, "Got unexpected passes %#x.\n", passes);
7388 else
7389 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
7392 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7393 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7394 IDirect3DTexture9_Release(texture);
7396 refcount = IDirect3DDevice9_Release(device);
7397 ok(!refcount, "Device has %u references left.\n", refcount);
7398 IDirect3D9_Release(d3d);
7399 DestroyWindow(window);
7402 static void test_get_set_texture(void)
7404 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
7405 IDirect3DBaseTexture9 *texture;
7406 IDirect3DDevice9 *device;
7407 IDirect3D9 *d3d;
7408 ULONG refcount;
7409 HWND window;
7410 HRESULT hr;
7412 window = create_window();
7413 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7414 ok(!!d3d, "Failed to create a D3D object.\n");
7415 if (!(device = create_device(d3d, window, NULL)))
7417 skip("Failed to create a D3D device, skipping tests.\n");
7418 IDirect3D9_Release(d3d);
7419 DestroyWindow(window);
7420 return;
7423 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
7424 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7425 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7426 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
7427 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7428 ok(!texture, "Got unexpected texture %p.\n", texture);
7430 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
7431 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
7432 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7433 texture_vtbl = texture->lpVtbl;
7434 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
7435 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7436 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7437 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7438 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7439 texture->lpVtbl = NULL;
7440 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7441 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7442 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7443 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7444 texture->lpVtbl = texture_vtbl;
7445 IDirect3DBaseTexture9_Release(texture);
7447 refcount = IDirect3DDevice9_Release(device);
7448 ok(!refcount, "Device has %u references left.\n", refcount);
7449 IDirect3D9_Release(d3d);
7450 DestroyWindow(window);
7453 static void test_lod(void)
7455 IDirect3DTexture9 *texture;
7456 IDirect3DDevice9 *device;
7457 IDirect3D9 *d3d;
7458 ULONG refcount;
7459 HWND window;
7460 HRESULT hr;
7461 DWORD ret;
7463 window = create_window();
7464 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7465 ok(!!d3d, "Failed to create a D3D object.\n");
7466 if (!(device = create_device(d3d, window, NULL)))
7468 skip("Failed to create a D3D device, skipping tests.\n");
7469 IDirect3D9_Release(d3d);
7470 DestroyWindow(window);
7471 return;
7474 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
7475 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7476 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7478 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
7479 * return a HRESULT, so it can't return a normal error. Instead, the call
7480 * is simply ignored. */
7481 ret = IDirect3DTexture9_SetLOD(texture, 0);
7482 ok(!ret, "Got unexpected ret %u.\n", ret);
7483 ret = IDirect3DTexture9_SetLOD(texture, 1);
7484 ok(!ret, "Got unexpected ret %u.\n", ret);
7485 ret = IDirect3DTexture9_SetLOD(texture, 2);
7486 ok(!ret, "Got unexpected ret %u.\n", ret);
7487 ret = IDirect3DTexture9_GetLOD(texture);
7488 ok(!ret, "Got unexpected ret %u.\n", ret);
7490 IDirect3DTexture9_Release(texture);
7491 refcount = IDirect3DDevice9_Release(device);
7492 ok(!refcount, "Device has %u references left.\n", refcount);
7493 IDirect3D9_Release(d3d);
7494 DestroyWindow(window);
7497 static void test_surface_get_container(void)
7499 IDirect3DTexture9 *texture = NULL;
7500 IDirect3DSurface9 *surface = NULL;
7501 IDirect3DDevice9 *device;
7502 IUnknown *container;
7503 IDirect3D9 *d3d;
7504 ULONG refcount;
7505 HWND window;
7506 HRESULT hr;
7508 window = create_window();
7509 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7510 ok(!!d3d, "Failed to create a D3D object.\n");
7511 if (!(device = create_device(d3d, window, NULL)))
7513 skip("Failed to create a D3D device, skipping tests.\n");
7514 IDirect3D9_Release(d3d);
7515 DestroyWindow(window);
7516 return;
7519 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
7520 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7521 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7522 ok(!!texture, "Got unexpected texture %p.\n", texture);
7524 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7525 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7526 ok(!!surface, "Got unexpected surface %p.\n", surface);
7528 /* These should work... */
7529 container = NULL;
7530 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
7531 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7532 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7533 IUnknown_Release(container);
7535 container = NULL;
7536 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
7537 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7538 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7539 IUnknown_Release(container);
7541 container = NULL;
7542 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
7543 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7544 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7545 IUnknown_Release(container);
7547 container = NULL;
7548 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
7549 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7550 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7551 IUnknown_Release(container);
7553 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
7554 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
7555 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7556 ok(!container, "Got unexpected container %p.\n", container);
7558 IDirect3DSurface9_Release(surface);
7559 IDirect3DTexture9_Release(texture);
7560 refcount = IDirect3DDevice9_Release(device);
7561 ok(!refcount, "Device has %u references left.\n", refcount);
7562 IDirect3D9_Release(d3d);
7563 DestroyWindow(window);
7566 static void test_surface_alignment(void)
7568 IDirect3DSurface9 *surface;
7569 IDirect3DDevice9 *device;
7570 D3DLOCKED_RECT lr;
7571 unsigned int i, j;
7572 IDirect3D9 *d3d;
7573 ULONG refcount;
7574 HWND window;
7575 HRESULT hr;
7577 window = create_window();
7578 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7579 ok(!!d3d, "Failed to create a D3D object.\n");
7580 if (!(device = create_device(d3d, window, NULL)))
7582 skip("Failed to create a D3D device, skipping tests.\n");
7583 IDirect3D9_Release(d3d);
7584 DestroyWindow(window);
7585 return;
7588 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7589 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7590 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7591 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7593 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7594 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7595 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7596 /* Some applications also depend on the exact pitch, rather than just the
7597 * alignment. */
7598 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7599 hr = IDirect3DSurface9_UnlockRect(surface);
7600 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7601 IDirect3DSurface9_Release(surface);
7603 for (i = 0; i < 5; ++i)
7605 IDirect3DTexture9 *texture;
7606 unsigned int level_count;
7607 D3DSURFACE_DESC desc;
7608 int expected_pitch;
7610 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7611 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7612 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7613 if (FAILED(hr))
7615 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7616 continue;
7619 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7620 for (j = 0; j < level_count; ++j)
7622 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7623 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7624 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7625 hr = IDirect3DTexture9_UnlockRect(texture, j);
7626 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7628 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7629 if (i > 0)
7630 expected_pitch <<= 1;
7631 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7632 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7634 IDirect3DTexture9_Release(texture);
7637 refcount = IDirect3DDevice9_Release(device);
7638 ok(!refcount, "Device has %u references left.\n", refcount);
7639 IDirect3D9_Release(d3d);
7640 DestroyWindow(window);
7643 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7644 * different from regular formats. This test verifies we return the correct
7645 * memory offsets. */
7646 static void test_lockrect_offset(void)
7648 static const struct
7650 D3DFORMAT format;
7651 const char *name;
7652 unsigned int block_width;
7653 unsigned int block_height;
7654 unsigned int block_size;
7656 dxt_formats[] =
7658 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7659 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7660 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7661 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7662 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7663 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7664 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7666 unsigned int expected_offset, offset, i;
7667 const RECT rect = {60, 60, 68, 68};
7668 IDirect3DSurface9 *surface;
7669 D3DLOCKED_RECT locked_rect;
7670 IDirect3DDevice9 *device;
7671 int expected_pitch;
7672 IDirect3D9 *d3d;
7673 ULONG refcount;
7674 HWND window;
7675 BYTE *base;
7676 HRESULT hr;
7678 window = create_window();
7679 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7680 ok(!!d3d, "Failed to create a D3D object.\n");
7681 if (!(device = create_device(d3d, window, NULL)))
7683 skip("Failed to create a D3D device, skipping tests.\n");
7684 IDirect3D9_Release(d3d);
7685 DestroyWindow(window);
7686 return;
7689 for (i = 0; i < ARRAY_SIZE(dxt_formats); ++i)
7691 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7692 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7694 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7695 continue;
7698 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7699 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7700 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7702 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7703 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7705 base = locked_rect.pBits;
7706 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7707 * dxt_formats[i].block_size;
7708 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7709 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7711 hr = IDirect3DSurface9_UnlockRect(surface);
7712 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7714 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7715 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7717 offset = (BYTE *)locked_rect.pBits - base;
7718 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7719 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7720 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7721 offset, dxt_formats[i].name, expected_offset);
7723 hr = IDirect3DSurface9_UnlockRect(surface);
7724 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7726 IDirect3DSurface9_Release(surface);
7729 refcount = IDirect3DDevice9_Release(device);
7730 ok(!refcount, "Device has %u references left.\n", refcount);
7731 IDirect3D9_Release(d3d);
7732 DestroyWindow(window);
7735 static void test_lockrect_invalid(void)
7737 static const struct
7739 RECT rect;
7740 HRESULT win7_result;
7742 test_data[] =
7744 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7745 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7746 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7747 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7748 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7749 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7750 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7751 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7752 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7753 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7754 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7755 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7756 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7758 static const RECT test_rect_2 = {0, 0, 8, 8};
7759 IDirect3DSurface9 *surface = NULL;
7760 D3DLOCKED_RECT locked_rect;
7761 IDirect3DDevice9 *device;
7762 IDirect3DTexture9 *texture;
7763 IDirect3DCubeTexture9 *cube_texture;
7764 HRESULT hr, expected_hr;
7765 unsigned int i, r;
7766 IDirect3D9 *d3d;
7767 ULONG refcount;
7768 HWND window;
7769 BYTE *base;
7770 static const struct
7772 D3DRESOURCETYPE type;
7773 D3DPOOL pool;
7774 const char *name;
7776 resources[] =
7778 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7779 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7780 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7781 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7782 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7783 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7784 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7787 window = create_window();
7788 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7789 ok(!!d3d, "Failed to create a D3D object.\n");
7790 if (!(device = create_device(d3d, window, NULL)))
7792 skip("Failed to create a D3D device, skipping tests.\n");
7793 IDirect3D9_Release(d3d);
7794 DestroyWindow(window);
7795 return;
7798 for (r = 0; r < ARRAY_SIZE(resources); ++r)
7800 texture = NULL;
7801 cube_texture = NULL;
7802 switch (resources[r].type)
7804 case D3DRTYPE_SURFACE:
7805 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7806 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7807 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7808 hr, resources[r].name);
7809 break;
7811 case D3DRTYPE_TEXTURE:
7812 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7813 resources[r].pool, &texture, NULL);
7814 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7815 hr, resources[r].name);
7816 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7817 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7818 hr, resources[r].name);
7819 break;
7821 case D3DRTYPE_CUBETEXTURE:
7822 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7823 resources[r].pool, &cube_texture, NULL);
7824 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7825 hr, resources[r].name);
7826 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7827 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7828 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7829 hr, resources[r].name);
7830 break;
7832 default:
7833 break;
7836 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7837 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7838 base = locked_rect.pBits;
7839 hr = IDirect3DSurface9_UnlockRect(surface);
7840 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7841 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
7842 hr = IDirect3DSurface9_UnlockRect(surface);
7843 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
7845 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7847 unsigned int offset, expected_offset;
7848 const RECT *rect = &test_data[i].rect;
7850 locked_rect.pBits = (BYTE *)0xdeadbeef;
7851 locked_rect.Pitch = 0xdeadbeef;
7853 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7854 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7855 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7856 * one broken. */
7857 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7858 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7859 wine_dbgstr_rect(rect), hr, resources[r].name);
7860 if (FAILED(hr))
7861 continue;
7863 offset = (BYTE *)locked_rect.pBits - base;
7864 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7865 ok(offset == expected_offset,
7866 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7867 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7869 hr = IDirect3DSurface9_UnlockRect(surface);
7870 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7872 if (texture)
7874 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7875 ok(SUCCEEDED(hr),
7876 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7877 wine_dbgstr_rect(rect), hr, resources[r].name);
7878 if (FAILED(hr))
7879 continue;
7881 offset = (BYTE *)locked_rect.pBits - base;
7882 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7883 ok(offset == expected_offset,
7884 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7885 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7887 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7888 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7890 if (cube_texture)
7892 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7893 &locked_rect, rect, 0);
7894 ok(SUCCEEDED(hr),
7895 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7896 wine_dbgstr_rect(rect), hr, resources[r].name);
7897 if (FAILED(hr))
7898 continue;
7900 offset = (BYTE *)locked_rect.pBits - base;
7901 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7902 ok(offset == expected_offset,
7903 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7904 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7906 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7907 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7911 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7912 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7913 locked_rect.pBits = (BYTE *)0xdeadbeef;
7914 locked_rect.Pitch = 1;
7915 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7916 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7917 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7918 locked_rect.pBits, resources[r].name);
7919 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7920 locked_rect.Pitch, resources[r].name);
7921 hr = IDirect3DSurface9_UnlockRect(surface);
7922 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7924 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7925 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7926 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7927 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7928 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7929 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7930 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7931 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7932 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7933 hr = IDirect3DSurface9_UnlockRect(surface);
7934 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7936 IDirect3DSurface9_Release(surface);
7938 if (texture)
7940 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7941 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7942 hr, resources[r].name);
7943 locked_rect.pBits = (BYTE *)0xdeadbeef;
7944 locked_rect.Pitch = 1;
7945 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7946 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7947 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7948 locked_rect.pBits, resources[r].name);
7949 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7950 locked_rect.Pitch, resources[r].name);
7951 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7952 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7953 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7954 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7955 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7956 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7958 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7959 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7960 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7961 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7962 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7963 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7964 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7965 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7966 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7967 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7968 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7970 IDirect3DTexture9_Release(texture);
7972 if (cube_texture)
7974 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7975 &locked_rect, NULL, 0);
7976 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7977 hr, resources[r].name);
7978 locked_rect.pBits = (BYTE *)0xdeadbeef;
7979 locked_rect.Pitch = 1;
7980 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7981 &locked_rect, NULL, 0);
7982 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7983 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7984 locked_rect.pBits, resources[r].name);
7985 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7986 locked_rect.Pitch, resources[r].name);
7987 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7988 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7989 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7990 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7991 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7992 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7994 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7995 &locked_rect, &test_data[0].rect, 0);
7996 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7997 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7998 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7999 &locked_rect, &test_data[0].rect, 0);
8000 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
8001 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
8002 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
8003 &locked_rect, &test_rect_2, 0);
8004 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
8005 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
8006 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
8007 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
8009 IDirect3DCubeTexture9_Release(cube_texture);
8013 refcount = IDirect3DDevice9_Release(device);
8014 ok(!refcount, "Device has %u references left.\n", refcount);
8015 IDirect3D9_Release(d3d);
8016 DestroyWindow(window);
8019 static void test_private_data(void)
8021 ULONG refcount, expected_refcount;
8022 IDirect3DTexture9 *texture;
8023 IDirect3DSurface9 *surface, *surface2;
8024 IDirect3DDevice9 *device;
8025 IDirect3D9 *d3d;
8026 IUnknown *ptr;
8027 HWND window;
8028 HRESULT hr;
8029 DWORD size;
8030 DWORD data[4] = {1, 2, 3, 4};
8031 static const GUID d3d9_private_data_test_guid2 =
8033 0x2e5afac2,
8034 0x87b5,
8035 0x4c10,
8036 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
8039 window = create_window();
8040 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8041 ok(!!d3d, "Failed to create a D3D object.\n");
8042 if (!(device = create_device(d3d, window, NULL)))
8044 skip("Failed to create a D3D device, skipping tests.\n");
8045 IDirect3D9_Release(d3d);
8046 DestroyWindow(window);
8047 return;
8050 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
8051 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8052 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8054 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8055 device, 0, D3DSPD_IUNKNOWN);
8056 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8057 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8058 device, 5, D3DSPD_IUNKNOWN);
8059 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8060 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8061 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
8062 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8064 /* A failing SetPrivateData call does not clear the old data with the same tag. */
8065 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
8066 sizeof(device), D3DSPD_IUNKNOWN);
8067 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8068 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
8069 sizeof(device) * 2, D3DSPD_IUNKNOWN);
8070 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8071 size = sizeof(ptr);
8072 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8073 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8074 IUnknown_Release(ptr);
8075 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8076 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8078 refcount = get_refcount((IUnknown *)device);
8079 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8080 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8081 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8082 expected_refcount = refcount + 1;
8083 refcount = get_refcount((IUnknown *)device);
8084 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8085 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8086 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8087 expected_refcount = refcount - 1;
8088 refcount = get_refcount((IUnknown *)device);
8089 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8091 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8092 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8093 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8094 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8095 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8096 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8097 refcount = get_refcount((IUnknown *)device);
8098 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8100 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8101 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8102 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8103 size = 2 * sizeof(ptr);
8104 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8105 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8106 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8107 expected_refcount = refcount + 2;
8108 refcount = get_refcount((IUnknown *)device);
8109 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8110 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
8111 IUnknown_Release(ptr);
8112 expected_refcount--;
8114 ptr = (IUnknown *)0xdeadbeef;
8115 size = 1;
8116 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8117 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8118 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8119 size = 2 * sizeof(ptr);
8120 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8121 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8122 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8123 refcount = get_refcount((IUnknown *)device);
8124 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8125 size = 1;
8126 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8127 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8128 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8129 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8130 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
8131 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8132 size = 0xdeadbabe;
8133 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
8134 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8135 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8136 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
8137 /* GetPrivateData with size = NULL causes an access violation on Windows if the
8138 * requested data exists. */
8140 /* Destroying the surface frees the held reference. */
8141 IDirect3DSurface9_Release(surface);
8142 expected_refcount = refcount - 2;
8143 refcount = get_refcount((IUnknown *)device);
8144 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8146 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
8147 &texture, NULL);
8148 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8149 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8150 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
8151 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
8152 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
8154 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8155 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8157 memset(data, 0, sizeof(data));
8158 size = sizeof(data);
8159 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
8160 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8161 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
8162 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8163 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
8164 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
8166 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
8167 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8169 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8170 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8171 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
8172 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8174 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8175 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8177 IDirect3DSurface9_Release(surface2);
8178 IDirect3DSurface9_Release(surface);
8179 IDirect3DTexture9_Release(texture);
8181 refcount = IDirect3DDevice9_Release(device);
8182 ok(!refcount, "Device has %u references left.\n", refcount);
8183 IDirect3D9_Release(d3d);
8184 DestroyWindow(window);
8187 static void test_getdc(void)
8189 static const struct
8191 const char *name;
8192 D3DFORMAT format;
8193 unsigned int bit_count;
8194 DWORD mask_r, mask_g, mask_b;
8195 BOOL getdc_supported;
8197 testdata[] =
8199 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8200 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8201 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
8202 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8203 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8204 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
8205 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8206 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8207 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8208 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8209 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8210 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8211 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8212 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8213 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8214 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
8215 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8216 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8217 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8218 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8220 IDirect3DSurface9 *surface, *surface2;
8221 IDirect3DCubeTexture9 *cube_texture;
8222 struct device_desc device_desc;
8223 IDirect3DTexture9 *texture;
8224 IDirect3DDevice9 *device;
8225 D3DLOCKED_RECT map_desc;
8226 IDirect3D9 *d3d;
8227 unsigned int i;
8228 ULONG refcount;
8229 HWND window;
8230 HDC dc, dc2;
8231 HRESULT hr;
8233 window = create_window();
8234 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8235 ok(!!d3d, "Failed to create a D3D object.\n");
8236 if (!(device = create_device(d3d, window, NULL)))
8238 skip("Failed to create a D3D device, skipping tests.\n");
8239 IDirect3D9_Release(d3d);
8240 DestroyWindow(window);
8241 return;
8244 for (i = 0; i < ARRAY_SIZE(testdata); ++i)
8246 texture = NULL;
8247 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8248 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
8249 if (FAILED(hr))
8251 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
8252 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
8253 if (FAILED(hr))
8255 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8256 continue;
8258 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8259 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8262 dc = (void *)0x1234;
8263 hr = IDirect3DSurface9_GetDC(surface, &dc);
8264 if (testdata[i].getdc_supported)
8265 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8266 else
8267 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8269 if (SUCCEEDED(hr))
8271 unsigned int width_bytes;
8272 DIBSECTION dib;
8273 HBITMAP bitmap;
8274 DWORD type;
8275 int size;
8277 type = GetObjectType(dc);
8278 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8279 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8280 type = GetObjectType(bitmap);
8281 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8283 size = GetObjectA(bitmap, sizeof(dib), &dib);
8284 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
8285 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
8286 dib.dsBm.bmType, testdata[i].name);
8287 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
8288 dib.dsBm.bmWidth, testdata[i].name);
8289 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
8290 dib.dsBm.bmHeight, testdata[i].name);
8291 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
8292 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
8293 dib.dsBm.bmWidthBytes, testdata[i].name);
8294 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
8295 dib.dsBm.bmPlanes, testdata[i].name);
8296 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
8297 "Got unexpected bit count %d for format %s.\n",
8298 dib.dsBm.bmBitsPixel, testdata[i].name);
8299 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
8300 dib.dsBm.bmBits, testdata[i].name);
8302 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
8303 dib.dsBmih.biSize, testdata[i].name);
8304 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
8305 dib.dsBmih.biHeight, testdata[i].name);
8306 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
8307 dib.dsBmih.biHeight, testdata[i].name);
8308 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
8309 dib.dsBmih.biPlanes, testdata[i].name);
8310 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
8311 dib.dsBmih.biBitCount, testdata[i].name);
8312 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
8313 "Got unexpected compression %#x for format %s.\n",
8314 dib.dsBmih.biCompression, testdata[i].name);
8315 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
8316 dib.dsBmih.biSizeImage, testdata[i].name);
8317 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
8318 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
8319 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
8320 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
8321 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
8322 dib.dsBmih.biClrUsed, testdata[i].name);
8323 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
8324 dib.dsBmih.biClrImportant, testdata[i].name);
8326 if (dib.dsBmih.biCompression == BI_BITFIELDS)
8328 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
8329 && dib.dsBitfields[2] == testdata[i].mask_b,
8330 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8331 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8333 else
8335 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
8336 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8337 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8339 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
8340 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
8342 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8343 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
8345 else
8347 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
8350 IDirect3DSurface9_Release(surface);
8351 if (texture)
8352 IDirect3DTexture9_Release(texture);
8354 if (!testdata[i].getdc_supported)
8355 continue;
8357 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
8358 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
8360 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8361 continue;
8364 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
8365 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8366 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
8367 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8369 hr = IDirect3DSurface9_GetDC(surface, &dc);
8370 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8371 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8372 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8373 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8374 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8375 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8376 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8378 hr = IDirect3DSurface9_GetDC(surface, &dc);
8379 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8380 dc2 = (void *)0x1234;
8381 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8382 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8383 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
8384 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8385 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8386 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8387 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8389 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8390 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8391 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8392 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8393 hr = IDirect3DSurface9_UnlockRect(surface);
8394 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8395 hr = IDirect3DSurface9_UnlockRect(surface);
8396 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8398 hr = IDirect3DSurface9_GetDC(surface, &dc);
8399 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8400 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8401 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8402 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8403 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8405 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8406 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8407 hr = IDirect3DSurface9_GetDC(surface, &dc);
8408 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8409 hr = IDirect3DSurface9_UnlockRect(surface);
8410 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8412 hr = IDirect3DSurface9_GetDC(surface, &dc);
8413 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8414 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
8415 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8416 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
8417 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8418 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8419 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8421 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8422 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8423 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8424 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8425 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
8426 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8427 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8428 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8430 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8431 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8432 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8433 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8434 hr = IDirect3DSurface9_UnlockRect(surface2);
8435 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8436 hr = IDirect3DSurface9_UnlockRect(surface);
8437 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8439 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8440 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8441 hr = IDirect3DSurface9_GetDC(surface, &dc);
8442 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8443 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8444 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8445 hr = IDirect3DSurface9_UnlockRect(surface);
8446 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8448 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8449 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8450 hr = IDirect3DSurface9_GetDC(surface, &dc);
8451 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8452 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8453 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8454 hr = IDirect3DSurface9_UnlockRect(surface2);
8455 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8457 hr = IDirect3DSurface9_GetDC(surface, &dc);
8458 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8459 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8460 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8461 hr = IDirect3DSurface9_UnlockRect(surface2);
8462 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8463 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8464 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8466 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8467 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8468 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8469 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8470 hr = IDirect3DSurface9_UnlockRect(surface);
8471 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8472 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8473 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8475 hr = IDirect3DSurface9_UnlockRect(surface);
8476 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8477 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8478 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8479 hr = IDirect3DSurface9_UnlockRect(surface);
8480 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8481 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8482 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8483 hr = IDirect3DSurface9_UnlockRect(surface);
8484 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8486 hr = IDirect3DSurface9_UnlockRect(surface2);
8487 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8488 hr = IDirect3DSurface9_GetDC(surface, &dc);
8489 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8490 hr = IDirect3DSurface9_UnlockRect(surface2);
8491 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8492 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8493 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8494 hr = IDirect3DSurface9_UnlockRect(surface2);
8495 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8497 IDirect3DSurface9_Release(surface2);
8498 IDirect3DSurface9_Release(surface);
8499 IDirect3DCubeTexture9_Release(cube_texture);
8502 refcount = IDirect3DDevice9_Release(device);
8503 ok(!refcount, "Device has %u references left.\n", refcount);
8505 /* Backbuffer created with D3DFMT_UNKNOWN format. */
8506 device_desc.width = 640;
8507 device_desc.height = 480;
8508 device_desc.device_window = window;
8509 device_desc.flags = CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT | CREATE_DEVICE_LOCKABLE_BACKBUFFER;
8511 device = create_device(d3d, window, &device_desc);
8512 ok(!!device, "Failed to create device.\n");
8514 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8515 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
8517 dc = NULL;
8518 hr = IDirect3DSurface9_GetDC(surface, &dc);
8519 ok(!!dc, "Unexpected DC returned.\n");
8520 ok(SUCCEEDED(hr), "Failed to get backbuffer DC, hr %#x.\n", hr);
8521 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8522 ok(SUCCEEDED(hr), "Failed to release backbuffer DC, hr %#x.\n", hr);
8524 IDirect3DSurface9_Release(surface);
8526 refcount = IDirect3DDevice9_Release(device);
8527 ok(!refcount, "Device has %u references left.\n", refcount);
8529 IDirect3D9_Release(d3d);
8530 DestroyWindow(window);
8533 static void test_surface_dimensions(void)
8535 IDirect3DSurface9 *surface;
8536 IDirect3DDevice9 *device;
8537 IDirect3D9 *d3d;
8538 ULONG refcount;
8539 HWND window;
8540 HRESULT hr;
8542 window = create_window();
8543 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8544 ok(!!d3d, "Failed to create a D3D object.\n");
8545 if (!(device = create_device(d3d, window, NULL)))
8547 skip("Failed to create a D3D device, skipping tests.\n");
8548 IDirect3D9_Release(d3d);
8549 DestroyWindow(window);
8550 return;
8553 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8554 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8555 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8556 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8557 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8558 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8560 refcount = IDirect3DDevice9_Release(device);
8561 ok(!refcount, "Device has %u references left.\n", refcount);
8562 IDirect3D9_Release(d3d);
8563 DestroyWindow(window);
8566 static void test_surface_format_null(void)
8568 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8569 IDirect3DTexture9 *texture;
8570 IDirect3DSurface9 *surface;
8571 IDirect3DSurface9 *rt, *ds;
8572 D3DLOCKED_RECT locked_rect;
8573 IDirect3DDevice9 *device;
8574 D3DSURFACE_DESC desc;
8575 IDirect3D9 *d3d;
8576 ULONG refcount;
8577 HWND window;
8578 HRESULT hr;
8580 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8581 ok(!!d3d, "Failed to create a D3D object.\n");
8583 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8584 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8585 if (hr != D3D_OK)
8587 skip("No D3DFMT_NULL support, skipping test.\n");
8588 IDirect3D9_Release(d3d);
8589 return;
8592 window = create_window();
8593 if (!(device = create_device(d3d, window, NULL)))
8595 skip("Failed to create a D3D device, skipping tests.\n");
8596 IDirect3D9_Release(d3d);
8597 DestroyWindow(window);
8598 return;
8601 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8602 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8603 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8605 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8606 D3DFMT_NULL, D3DFMT_D24S8);
8607 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8609 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8610 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8611 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8613 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8614 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8616 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8617 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8619 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8620 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8622 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8623 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8625 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8626 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8628 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8629 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8631 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8632 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8634 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8635 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8637 IDirect3DSurface9_Release(rt);
8638 IDirect3DSurface9_Release(ds);
8640 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8641 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8642 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8643 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8645 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8646 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8647 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8648 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8650 hr = IDirect3DSurface9_UnlockRect(surface);
8651 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8653 IDirect3DSurface9_Release(surface);
8655 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8656 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8657 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8658 IDirect3DTexture9_Release(texture);
8660 refcount = IDirect3DDevice9_Release(device);
8661 ok(!refcount, "Device has %u references left.\n", refcount);
8662 IDirect3D9_Release(d3d);
8663 DestroyWindow(window);
8666 static void test_surface_double_unlock(void)
8668 static const D3DPOOL pools[] =
8670 D3DPOOL_DEFAULT,
8671 D3DPOOL_SCRATCH,
8672 D3DPOOL_SYSTEMMEM,
8674 IDirect3DSurface9 *surface;
8675 IDirect3DDevice9 *device;
8676 D3DSURFACE_DESC desc;
8677 D3DLOCKED_RECT lr;
8678 IDirect3D9 *d3d;
8679 unsigned int i;
8680 ULONG refcount;
8681 HWND window;
8682 HRESULT hr;
8684 window = create_window();
8685 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8686 ok(!!d3d, "Failed to create a D3D object.\n");
8687 if (!(device = create_device(d3d, window, NULL)))
8689 skip("Failed to create a D3D device, skipping tests.\n");
8690 IDirect3D9_Release(d3d);
8691 DestroyWindow(window);
8692 return;
8695 for (i = 0; i < ARRAY_SIZE(pools); ++i)
8697 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8698 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8699 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8701 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8702 ok(hr == D3D_OK, "Pool %#x: Got unexpected hr %#x.\n", pools[i], hr);
8703 ok(!desc.Usage, "Pool %#x: Got unexpected usage %#x.\n", pools[i], desc.Usage);
8704 ok(desc.Pool == pools[i], "Pool %#x: Got unexpected pool %#x.\n", pools[i], desc.Pool);
8706 hr = IDirect3DSurface9_UnlockRect(surface);
8707 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8708 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8709 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8710 hr = IDirect3DSurface9_UnlockRect(surface);
8711 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8712 hr = IDirect3DSurface9_UnlockRect(surface);
8713 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8715 IDirect3DSurface9_Release(surface);
8718 refcount = IDirect3DDevice9_Release(device);
8719 ok(!refcount, "Device has %u references left.\n", refcount);
8720 IDirect3D9_Release(d3d);
8721 DestroyWindow(window);
8724 static void test_surface_blocks(void)
8726 static const struct
8728 D3DFORMAT fmt;
8729 const char *name;
8730 unsigned int block_width;
8731 unsigned int block_height;
8732 BOOL broken;
8733 BOOL create_size_checked, core_fmt;
8735 formats[] =
8737 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8738 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8739 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8740 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8741 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8742 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8743 * which doesn't match the format spec. On newer Nvidia cards
8744 * they have the correct 4x4 block size */
8745 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8746 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8747 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8748 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8750 static const struct
8752 D3DPOOL pool;
8753 const char *name;
8754 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8755 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8756 BOOL success;
8758 pools[] =
8760 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8761 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8762 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8763 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8765 static struct
8767 D3DRESOURCETYPE rtype;
8768 const char *type_name;
8769 D3DPOOL pool;
8770 const char *pool_name;
8771 BOOL need_driver_support, need_runtime_support;
8773 create_tests[] =
8775 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8776 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8777 /* Managed offscreen plain surfaces are not supported */
8778 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8780 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8781 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8782 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8783 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8785 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8786 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8787 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8788 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8790 IDirect3DTexture9 *texture;
8791 IDirect3DCubeTexture9 *cube_texture;
8792 IDirect3DSurface9 *surface;
8793 D3DLOCKED_RECT locked_rect;
8794 IDirect3DDevice9 *device;
8795 unsigned int i, j, k, w, h;
8796 BOOL surface_only;
8797 IDirect3D9 *d3d;
8798 ULONG refcount;
8799 HWND window;
8800 HRESULT hr;
8801 RECT rect;
8802 BOOL tex_pow2, cube_pow2;
8803 D3DCAPS9 caps;
8804 static const RECT invalid[] =
8806 {60, 60, 60, 68}, /* 0 height */
8807 {60, 60, 68, 60}, /* 0 width */
8808 {68, 60, 60, 68}, /* left > right */
8809 {60, 68, 68, 60}, /* top > bottom */
8810 {-8, 60, 0, 68}, /* left < surface */
8811 {60, -8, 68, 0}, /* top < surface */
8812 {-16, 60, -8, 68}, /* right < surface */
8813 {60, -16, 68, -8}, /* bottom < surface */
8814 {60, 60, 136, 68}, /* right > surface */
8815 {60, 60, 68, 136}, /* bottom > surface */
8816 {136, 60, 144, 68}, /* left > surface */
8817 {60, 136, 68, 144}, /* top > surface */
8820 window = create_window();
8821 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8822 ok(!!d3d, "Failed to create a D3D object.\n");
8823 if (!(device = create_device(d3d, window, NULL)))
8825 skip("Failed to create a D3D device, skipping tests.\n");
8826 IDirect3D9_Release(d3d);
8827 DestroyWindow(window);
8828 return;
8831 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8832 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8833 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8834 if (tex_pow2)
8835 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8836 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8838 for (i = 0; i < ARRAY_SIZE(formats); ++i)
8840 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8842 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8843 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8844 tex_support = SUCCEEDED(hr);
8845 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8846 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8847 cube_support = SUCCEEDED(hr);
8848 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8849 0, D3DRTYPE_SURFACE, formats[i].fmt);
8850 surface_support = SUCCEEDED(hr);
8852 /* Scratch pool in general allows texture creation even if the driver does
8853 * not support the format. If the format is an extension format that is not
8854 * known to the runtime, like ATI2N, some driver support is required for
8855 * this to work.
8857 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8858 * about ATI2N. I cannot check this because all my Vista+ machines support
8859 * ATI2N in hardware, but none of my WinXP machines do. */
8860 format_known = tex_support || cube_support || surface_support;
8862 for (w = 1; w <= 8; w++)
8864 for (h = 1; h <= 8; h++)
8866 BOOL block_aligned = TRUE;
8867 BOOL size_is_pow2;
8869 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8870 block_aligned = FALSE;
8872 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8874 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
8876 BOOL support, pow2;
8877 HRESULT expect_hr;
8878 BOOL may_succeed = FALSE;
8879 IUnknown **check_null;
8881 if (!formats[i].core_fmt)
8883 /* AMD warns against creating ATI2N textures smaller than
8884 * the block size because the runtime cannot calculate the
8885 * correct texture size. Generalize this for all extension
8886 * formats. */
8887 if (w < formats[i].block_width || h < formats[i].block_height)
8888 continue;
8891 texture = (IDirect3DTexture9 *)0xdeadbeef;
8892 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8893 surface = (IDirect3DSurface9 *)0xdeadbeef;
8895 switch (create_tests[j].rtype)
8897 case D3DRTYPE_TEXTURE:
8898 check_null = (IUnknown **)&texture;
8899 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8900 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8901 support = tex_support;
8902 pow2 = tex_pow2;
8903 break;
8905 case D3DRTYPE_CUBETEXTURE:
8906 if (w != h)
8907 continue;
8908 check_null = (IUnknown **)&cube_texture;
8909 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8910 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8911 support = cube_support;
8912 pow2 = cube_pow2;
8913 break;
8915 case D3DRTYPE_SURFACE:
8916 check_null = (IUnknown **)&surface;
8917 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8918 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8919 support = surface_support;
8920 pow2 = FALSE;
8921 break;
8923 default:
8924 check_null = NULL;
8925 pow2 = FALSE;
8926 support = FALSE;
8927 break;
8930 if (create_tests[j].need_driver_support && !support)
8931 expect_hr = D3DERR_INVALIDCALL;
8932 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8933 expect_hr = D3DERR_INVALIDCALL;
8934 else if (formats[i].create_size_checked && !block_aligned)
8935 expect_hr = D3DERR_INVALIDCALL;
8936 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8937 expect_hr = D3DERR_INVALIDCALL;
8938 else
8939 expect_hr = D3D_OK;
8941 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8942 * does not support it. Accept scratch creation of extension formats on
8943 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8944 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8945 * support it. */
8946 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8947 may_succeed = TRUE;
8949 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8950 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8951 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8952 if (FAILED(hr))
8953 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8954 else
8955 IUnknown_Release(*check_null);
8960 surface_only = FALSE;
8961 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8962 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8963 dynamic_tex_support = SUCCEEDED(hr);
8964 if (!dynamic_tex_support)
8966 if (!surface_support)
8968 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8969 continue;
8971 surface_only = TRUE;
8974 for (j = 0; j < ARRAY_SIZE(pools); ++j)
8976 switch (pools[j].pool)
8978 case D3DPOOL_SYSTEMMEM:
8979 case D3DPOOL_MANAGED:
8980 if (surface_only)
8981 continue;
8982 /* Fall through */
8983 case D3DPOOL_DEFAULT:
8984 if (surface_only)
8986 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8987 formats[i].fmt, pools[j].pool, &surface, NULL);
8988 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8990 else
8992 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8993 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8994 formats[i].fmt, pools[j].pool, &texture, NULL);
8995 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8996 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8997 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8998 IDirect3DTexture9_Release(texture);
9000 break;
9002 case D3DPOOL_SCRATCH:
9003 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9004 formats[i].fmt, pools[j].pool, &surface, NULL);
9005 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9006 break;
9008 default:
9009 break;
9012 if (formats[i].block_width > 1)
9014 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
9015 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9016 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9017 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9018 SUCCEEDED(hr) ? "succeeded" : "failed",
9019 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9020 if (SUCCEEDED(hr))
9022 hr = IDirect3DSurface9_UnlockRect(surface);
9023 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9026 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
9027 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9028 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9029 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9030 SUCCEEDED(hr) ? "succeeded" : "failed",
9031 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9032 if (SUCCEEDED(hr))
9034 hr = IDirect3DSurface9_UnlockRect(surface);
9035 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9039 if (formats[i].block_height > 1)
9041 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
9042 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9043 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9044 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9045 SUCCEEDED(hr) ? "succeeded" : "failed",
9046 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9047 if (SUCCEEDED(hr))
9049 hr = IDirect3DSurface9_UnlockRect(surface);
9050 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9053 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
9054 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9055 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9056 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9057 SUCCEEDED(hr) ? "succeeded" : "failed",
9058 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9059 if (SUCCEEDED(hr))
9061 hr = IDirect3DSurface9_UnlockRect(surface);
9062 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9066 for (k = 0; k < ARRAY_SIZE(invalid); ++k)
9068 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
9069 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
9070 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
9071 formats[i].name, pools[j].name, k);
9072 if (SUCCEEDED(hr))
9074 hr = IDirect3DSurface9_UnlockRect(surface);
9075 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9079 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
9080 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9081 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
9082 hr = IDirect3DSurface9_UnlockRect(surface);
9083 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9085 IDirect3DSurface9_Release(surface);
9088 if (!dynamic_tex_support)
9090 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
9091 continue;
9094 if (formats[i].block_width == 1 && formats[i].block_height == 1)
9095 continue;
9096 if (!formats[i].core_fmt)
9097 continue;
9099 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
9100 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
9101 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
9103 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
9104 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9105 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9106 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9108 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
9109 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
9110 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9111 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9112 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9113 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9115 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
9116 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9117 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9118 if (SUCCEEDED(hr))
9119 IDirect3DTexture9_UnlockRect(texture, 1);
9121 IDirect3DTexture9_Release(texture);
9124 refcount = IDirect3DDevice9_Release(device);
9125 ok(!refcount, "Device has %u references left.\n", refcount);
9126 IDirect3D9_Release(d3d);
9127 DestroyWindow(window);
9130 static void test_set_palette(void)
9132 IDirect3DDevice9 *device;
9133 IDirect3D9 *d3d9;
9134 UINT refcount;
9135 HWND window;
9136 HRESULT hr;
9137 PALETTEENTRY pal[256];
9138 unsigned int i;
9139 D3DCAPS9 caps;
9141 window = create_window();
9142 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9143 ok(!!d3d9, "Failed to create a D3D object.\n");
9144 if (!(device = create_device(d3d9, window, NULL)))
9146 skip("Failed to create a D3D device, skipping tests.\n");
9147 DestroyWindow(window);
9148 return;
9151 for (i = 0; i < ARRAY_SIZE(pal); i++)
9153 pal[i].peRed = i;
9154 pal[i].peGreen = i;
9155 pal[i].peBlue = i;
9156 pal[i].peFlags = 0xff;
9158 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9159 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9161 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9162 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9163 for (i = 0; i < ARRAY_SIZE(pal); i++)
9165 pal[i].peRed = i;
9166 pal[i].peGreen = i;
9167 pal[i].peBlue = i;
9168 pal[i].peFlags = i;
9170 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
9172 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9173 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9175 else
9177 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9178 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
9181 refcount = IDirect3DDevice9_Release(device);
9182 ok(!refcount, "Device has %u references left.\n", refcount);
9183 IDirect3D9_Release(d3d9);
9184 DestroyWindow(window);
9187 static void test_swvp_buffer(void)
9189 IDirect3DDevice9 *device;
9190 IDirect3D9 *d3d9;
9191 UINT refcount;
9192 HWND window;
9193 HRESULT hr;
9194 unsigned int i;
9195 IDirect3DVertexBuffer9 *buffer;
9196 static const unsigned int bufsize = 1024;
9197 D3DVERTEXBUFFER_DESC desc;
9198 struct device_desc device_desc;
9199 struct
9201 float x, y, z;
9202 } *ptr, *ptr2;
9204 window = create_window();
9205 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9206 ok(!!d3d9, "Failed to create a D3D object.\n");
9208 device_desc.device_window = window;
9209 device_desc.width = 640;
9210 device_desc.height = 480;
9211 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
9212 if (!(device = create_device(d3d9, window, &device_desc)))
9214 skip("Failed to create a D3D device, skipping tests.\n");
9215 DestroyWindow(window);
9216 IDirect3D9_Release(d3d9);
9217 return;
9220 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
9221 D3DPOOL_DEFAULT, &buffer, NULL);
9222 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9223 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9224 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9225 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
9226 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
9227 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
9229 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9230 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9231 for (i = 0; i < bufsize; i++)
9233 ptr[i].x = i * 1.0f;
9234 ptr[i].y = i * 2.0f;
9235 ptr[i].z = i * 3.0f;
9237 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9238 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9240 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9241 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9242 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9243 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9244 hr = IDirect3DDevice9_BeginScene(device);
9245 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9246 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9247 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9248 hr = IDirect3DDevice9_EndScene(device);
9249 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9251 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9252 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9253 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
9254 for (i = 0; i < bufsize; i++)
9256 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9258 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
9259 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9260 break;
9263 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9264 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9266 IDirect3DVertexBuffer9_Release(buffer);
9267 refcount = IDirect3DDevice9_Release(device);
9268 ok(!refcount, "Device has %u references left.\n", refcount);
9269 IDirect3D9_Release(d3d9);
9270 DestroyWindow(window);
9273 static void test_managed_buffer(void)
9275 static const unsigned int vertex_count = 1024;
9276 IDirect3DVertexBuffer9 *buffer;
9277 D3DVERTEXBUFFER_DESC desc;
9278 IDirect3DDevice9 *device;
9279 struct vec3 *ptr, *ptr2;
9280 IDirect3D9 *d3d9;
9281 unsigned int i;
9282 UINT refcount;
9283 HWND window;
9284 HRESULT hr;
9286 window = create_window();
9287 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9288 ok(!!d3d9, "Failed to create a D3D object.\n");
9289 if (!(device = create_device(d3d9, window, NULL)))
9291 skip("Failed to create a D3D device, skipping tests.\n");
9292 IDirect3D9_Release(d3d9);
9293 DestroyWindow(window);
9294 return;
9297 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
9298 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
9299 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9300 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9301 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9302 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
9303 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
9305 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9306 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9307 for (i = 0; i < vertex_count; ++i)
9309 ptr[i].x = i * 1.0f;
9310 ptr[i].y = i * 2.0f;
9311 ptr[i].z = i * 3.0f;
9313 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9314 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9316 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9317 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9318 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9319 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9320 hr = IDirect3DDevice9_BeginScene(device);
9321 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9322 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9323 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9324 hr = IDirect3DDevice9_EndScene(device);
9325 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9327 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9328 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9329 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
9330 for (i = 0; i < vertex_count; ++i)
9332 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9334 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
9335 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9336 break;
9339 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9340 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9342 IDirect3DVertexBuffer9_Release(buffer);
9343 refcount = IDirect3DDevice9_Release(device);
9344 ok(!refcount, "Device has %u references left.\n", refcount);
9345 IDirect3D9_Release(d3d9);
9346 DestroyWindow(window);
9349 static void test_npot_textures(void)
9351 IDirect3DDevice9 *device = NULL;
9352 IDirect3D9 *d3d9;
9353 ULONG refcount;
9354 HWND window = NULL;
9355 HRESULT hr;
9356 D3DCAPS9 caps;
9357 IDirect3DTexture9 *texture;
9358 IDirect3DCubeTexture9 *cube_texture;
9359 IDirect3DVolumeTexture9 *volume_texture;
9360 struct
9362 D3DPOOL pool;
9363 const char *pool_name;
9364 HRESULT hr;
9366 pools[] =
9368 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
9369 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
9370 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
9371 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
9373 unsigned int i, levels;
9374 BOOL tex_pow2, cube_pow2, vol_pow2;
9376 window = create_window();
9377 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9378 ok(!!d3d9, "Failed to create a D3D object.\n");
9379 if (!(device = create_device(d3d9, window, NULL)))
9381 skip("Failed to create a D3D device, skipping tests.\n");
9382 goto done;
9385 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9386 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9387 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
9388 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
9389 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9390 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
9391 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
9393 for (i = 0; i < ARRAY_SIZE(pools); i++)
9395 for (levels = 0; levels <= 2; levels++)
9397 HRESULT expected;
9399 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
9400 pools[i].pool, &texture, NULL);
9401 if (!tex_pow2)
9403 expected = D3D_OK;
9405 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
9407 if (levels == 1)
9408 expected = D3D_OK;
9409 else
9410 expected = pools[i].hr;
9412 else
9414 expected = pools[i].hr;
9416 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
9417 pools[i].pool_name, levels, hr, expected);
9419 if (SUCCEEDED(hr))
9420 IDirect3DTexture9_Release(texture);
9423 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9424 &cube_texture, NULL);
9425 if (tex_pow2)
9427 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9428 pools[i].pool_name, hr, pools[i].hr);
9430 else
9432 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9433 pools[i].pool_name, hr, D3D_OK);
9436 if (SUCCEEDED(hr))
9437 IDirect3DCubeTexture9_Release(cube_texture);
9439 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9440 &volume_texture, NULL);
9441 if (tex_pow2)
9443 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9444 pools[i].pool_name, hr, pools[i].hr);
9446 else
9448 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9449 pools[i].pool_name, hr, D3D_OK);
9452 if (SUCCEEDED(hr))
9453 IDirect3DVolumeTexture9_Release(volume_texture);
9456 done:
9457 if (device)
9459 refcount = IDirect3DDevice9_Release(device);
9460 ok(!refcount, "Device has %u references left.\n", refcount);
9462 IDirect3D9_Release(d3d9);
9463 DestroyWindow(window);
9467 static void test_vidmem_accounting(void)
9469 IDirect3DDevice9 *device;
9470 IDirect3D9 *d3d9;
9471 ULONG refcount;
9472 HWND window;
9473 HRESULT hr = D3D_OK;
9474 IDirect3DTexture9 *textures[20];
9475 unsigned int i;
9476 UINT vidmem_start, vidmem_end, diff;
9478 window = create_window();
9479 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9480 ok(!!d3d9, "Failed to create a D3D object.\n");
9481 if (!(device = create_device(d3d9, window, NULL)))
9483 skip("Failed to create a D3D device, skipping tests.\n");
9484 IDirect3D9_Release(d3d9);
9485 DestroyWindow(window);
9486 return;
9489 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
9490 memset(textures, 0, sizeof(textures));
9491 for (i = 0; i < ARRAY_SIZE(textures); i++)
9493 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9494 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9495 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9496 * E_FAIL is returned on address space or system memory exhaustion */
9497 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9498 "Failed to create texture, hr %#x.\n", hr);
9500 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9502 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9503 diff = vidmem_start - vidmem_end;
9504 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9505 2 * i, diff / 1024 / 1024);
9507 for (i = 0; i < ARRAY_SIZE(textures); i++)
9509 if (textures[i])
9510 IDirect3DTexture9_Release(textures[i]);
9513 refcount = IDirect3DDevice9_Release(device);
9514 ok(!refcount, "Device has %u references left.\n", refcount);
9515 IDirect3D9_Release(d3d9);
9516 DestroyWindow(window);
9519 static void test_volume_locking(void)
9521 IDirect3DDevice9 *device;
9522 IDirect3D9 *d3d9;
9523 HWND window;
9524 HRESULT hr;
9525 IDirect3DVolumeTexture9 *texture;
9526 unsigned int i;
9527 D3DLOCKED_BOX locked_box;
9528 ULONG refcount;
9529 D3DCAPS9 caps;
9530 static const struct
9532 D3DPOOL pool;
9533 DWORD usage;
9534 HRESULT create_hr, lock_hr;
9536 tests[] =
9538 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9539 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9540 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9541 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9542 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9543 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9544 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9545 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9548 window = create_window();
9549 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9550 ok(!!d3d9, "Failed to create a D3D object.\n");
9551 if (!(device = create_device(d3d9, window, NULL)))
9553 skip("Failed to create a D3D device, skipping tests.\n");
9554 IDirect3D9_Release(d3d9);
9555 DestroyWindow(window);
9556 return;
9559 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9560 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9561 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9563 skip("Volume textures not supported, skipping test.\n");
9564 goto out;
9567 for (i = 0; i < ARRAY_SIZE(tests); i++)
9569 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9570 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9571 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9572 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9573 if (FAILED(hr))
9574 continue;
9576 locked_box.pBits = (void *)0xdeadbeef;
9577 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9578 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9579 if (SUCCEEDED(hr))
9581 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9582 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9584 else
9586 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9588 IDirect3DVolumeTexture9_Release(texture);
9591 out:
9592 refcount = IDirect3DDevice9_Release(device);
9593 ok(!refcount, "Device has %u references left.\n", refcount);
9594 IDirect3D9_Release(d3d9);
9595 DestroyWindow(window);
9598 static void test_update_volumetexture(void)
9600 IDirect3DDevice9 *device;
9601 IDirect3D9 *d3d9;
9602 HWND window;
9603 HRESULT hr;
9604 IDirect3DVolumeTexture9 *src, *dst;
9605 unsigned int i;
9606 D3DLOCKED_BOX locked_box;
9607 ULONG refcount;
9608 D3DCAPS9 caps;
9609 static const struct
9611 D3DPOOL src_pool, dst_pool;
9612 HRESULT hr;
9614 tests[] =
9616 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9617 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9618 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9619 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9621 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9622 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9623 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9624 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9626 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9627 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9628 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9629 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9631 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9632 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9633 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9634 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9636 static const struct
9638 UINT src_size, dst_size;
9639 UINT src_lvl, dst_lvl;
9640 D3DFORMAT src_fmt, dst_fmt;
9642 tests2[] =
9644 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9645 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9646 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9647 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9648 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9649 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9650 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9651 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9654 window = create_window();
9655 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9656 ok(!!d3d9, "Failed to create a D3D object.\n");
9657 if (!(device = create_device(d3d9, window, NULL)))
9659 skip("Failed to create a D3D device, skipping tests.\n");
9660 IDirect3D9_Release(d3d9);
9661 DestroyWindow(window);
9662 return;
9665 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9666 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9667 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9669 skip("Volume textures not supported, skipping test.\n");
9670 goto out;
9673 for (i = 0; i < ARRAY_SIZE(tests); i++)
9675 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9676 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9678 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9679 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9680 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9681 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9682 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9683 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9685 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9686 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9687 *((DWORD *)locked_box.pBits) = 0x11223344;
9688 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9689 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9691 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9692 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9693 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9695 if (SUCCEEDED(hr))
9697 DWORD content = *((DWORD *)locked_box.pBits);
9698 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9699 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9700 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9701 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9702 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9704 IDirect3DVolumeTexture9_Release(src);
9705 IDirect3DVolumeTexture9_Release(dst);
9708 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9710 skip("Mipmapped volume maps not supported.\n");
9711 goto out;
9714 for (i = 0; i < ARRAY_SIZE(tests2); i++)
9716 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9717 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9718 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9719 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9720 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9721 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9722 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9723 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9725 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9726 todo_wine_if (FAILED(hr))
9727 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9729 IDirect3DVolumeTexture9_Release(src);
9730 IDirect3DVolumeTexture9_Release(dst);
9733 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9734 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9735 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9736 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9737 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9739 * I'm not adding tests for this behavior until an application needs it. */
9741 out:
9742 refcount = IDirect3DDevice9_Release(device);
9743 ok(!refcount, "Device has %u references left.\n", refcount);
9744 IDirect3D9_Release(d3d9);
9745 DestroyWindow(window);
9748 static void test_create_rt_ds_fail(void)
9750 IDirect3DDevice9 *device;
9751 HWND window;
9752 HRESULT hr;
9753 ULONG refcount;
9754 IDirect3D9 *d3d9;
9755 IDirect3DSurface9 *surface;
9757 window = create_window();
9758 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9759 ok(!!d3d9, "Failed to create a D3D object.\n");
9760 if (!(device = create_device(d3d9, window, NULL)))
9762 skip("Failed to create a D3D device, skipping tests.\n");
9763 IDirect3D9_Release(d3d9);
9764 DestroyWindow(window);
9765 return;
9768 /* Output pointer == NULL segfaults on Windows. */
9770 surface = (IDirect3DSurface9 *)0xdeadbeef;
9771 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9772 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9773 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9774 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9775 if (SUCCEEDED(hr))
9776 IDirect3DSurface9_Release(surface);
9778 surface = (IDirect3DSurface9 *)0xdeadbeef;
9779 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9780 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9781 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9782 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9783 if (SUCCEEDED(hr))
9784 IDirect3DSurface9_Release(surface);
9786 refcount = IDirect3DDevice9_Release(device);
9787 ok(!refcount, "Device has %u references left.\n", refcount);
9788 IDirect3D9_Release(d3d9);
9789 DestroyWindow(window);
9792 static void test_volume_blocks(void)
9794 IDirect3DDevice9 *device;
9795 IDirect3D9 *d3d9;
9796 UINT refcount;
9797 HWND window;
9798 HRESULT hr;
9799 D3DCAPS9 caps;
9800 IDirect3DVolumeTexture9 *texture;
9801 unsigned int w, h, d, i, j;
9802 static const struct
9804 D3DFORMAT fmt;
9805 const char *name;
9806 unsigned int block_width;
9807 unsigned int block_height;
9808 unsigned int block_depth;
9809 unsigned int block_size;
9810 unsigned int broken;
9811 BOOL create_size_checked, core_fmt;
9813 formats[] =
9815 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9816 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9817 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9818 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9819 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9820 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9821 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9822 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9823 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9824 * which doesn't match the format spec. On newer Nvidia cards
9825 * it has the correct 4x4 block size.
9826 * ATI1N volume textures are only supported by AMD GPUs right
9827 * now and locking offsets seem just wrong. */
9828 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9829 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9830 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9831 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9833 static const struct
9835 D3DPOOL pool;
9836 const char *name;
9837 BOOL need_driver_support, need_runtime_support;
9839 create_tests[] =
9841 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9842 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9843 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9844 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9846 static const struct
9848 unsigned int x, y, z, x2, y2, z2;
9850 offset_tests[] =
9852 {0, 0, 0, 8, 8, 8},
9853 {0, 0, 3, 8, 8, 8},
9854 {0, 4, 0, 8, 8, 8},
9855 {0, 4, 3, 8, 8, 8},
9856 {4, 0, 0, 8, 8, 8},
9857 {4, 0, 3, 8, 8, 8},
9858 {4, 4, 0, 8, 8, 8},
9859 {4, 4, 3, 8, 8, 8},
9861 D3DBOX box;
9862 D3DLOCKED_BOX locked_box;
9863 BYTE *base;
9864 INT expected_row_pitch, expected_slice_pitch;
9865 BOOL support;
9866 BOOL pow2;
9867 unsigned int offset, expected_offset;
9869 window = create_window();
9870 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9871 ok(!!d3d9, "Failed to create a D3D object.\n");
9872 if (!(device = create_device(d3d9, window, NULL)))
9874 skip("Failed to create a D3D device, skipping tests.\n");
9875 IDirect3D9_Release(d3d9);
9876 DestroyWindow(window);
9877 return;
9879 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9880 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9881 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9883 for (i = 0; i < ARRAY_SIZE(formats); i++)
9885 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9886 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9887 support = SUCCEEDED(hr);
9889 /* Test creation restrictions */
9890 for (w = 1; w <= 8; w++)
9892 for (h = 1; h <= 8; h++)
9894 for (d = 1; d <= 8; d++)
9896 HRESULT expect_hr;
9897 BOOL size_is_pow2;
9898 BOOL block_aligned = TRUE;
9900 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9901 block_aligned = FALSE;
9903 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9905 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
9907 BOOL may_succeed = FALSE;
9909 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9910 expect_hr = D3DERR_INVALIDCALL;
9911 else if (formats[i].create_size_checked && !block_aligned)
9912 expect_hr = D3DERR_INVALIDCALL;
9913 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9914 expect_hr = D3DERR_INVALIDCALL;
9915 else if (create_tests[j].need_driver_support && !support)
9916 expect_hr = D3DERR_INVALIDCALL;
9917 else
9918 expect_hr = D3D_OK;
9920 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9921 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9922 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9924 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9925 * does not support it. Accept scratch creation of extension formats on
9926 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9927 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9928 * support it. */
9929 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9930 may_succeed = TRUE;
9932 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9933 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9934 hr, formats[i].name, create_tests[j].name, w, h, d);
9936 if (FAILED(hr))
9937 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9938 else
9939 IDirect3DVolumeTexture9_Release(texture);
9945 if (!support && !formats[i].core_fmt)
9946 continue;
9948 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9949 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9950 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9952 /* Test lockrect offset */
9953 for (j = 0; j < ARRAY_SIZE(offset_tests); j++)
9955 unsigned int bytes_per_pixel;
9956 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9958 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9959 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9961 base = locked_box.pBits;
9962 if (formats[i].broken == 1)
9964 expected_row_pitch = bytes_per_pixel * 24;
9966 else if (formats[i].broken == 2)
9968 expected_row_pitch = 24;
9970 else
9972 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9973 * formats[i].block_size;
9975 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9976 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9978 if (formats[i].broken)
9980 expected_slice_pitch = expected_row_pitch * 8;
9982 else
9984 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9985 * expected_row_pitch;
9987 ok(locked_box.SlicePitch == expected_slice_pitch,
9988 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9989 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9991 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9992 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9994 box.Left = offset_tests[j].x;
9995 box.Top = offset_tests[j].y;
9996 box.Front = offset_tests[j].z;
9997 box.Right = offset_tests[j].x2;
9998 box.Bottom = offset_tests[j].y2;
9999 box.Back = offset_tests[j].z2;
10000 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10001 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
10003 offset = (BYTE *)locked_box.pBits - base;
10004 if (formats[i].broken == 1)
10006 expected_offset = box.Front * expected_slice_pitch
10007 + box.Top * expected_row_pitch
10008 + box.Left * bytes_per_pixel;
10010 else if (formats[i].broken == 2)
10012 expected_offset = box.Front * expected_slice_pitch
10013 + box.Top * expected_row_pitch
10014 + box.Left;
10016 else
10018 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
10019 + (box.Top / formats[i].block_height) * expected_row_pitch
10020 + (box.Left / formats[i].block_width) * formats[i].block_size;
10022 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
10023 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
10025 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10026 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10029 /* Test partial block locks */
10030 box.Front = 0;
10031 box.Back = 1;
10032 if (formats[i].block_width > 1)
10034 box.Left = formats[i].block_width >> 1;
10035 box.Top = 0;
10036 box.Right = formats[i].block_width;
10037 box.Bottom = formats[i].block_height;
10038 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10039 ok(FAILED(hr) || broken(formats[i].broken),
10040 "Partial block lock succeeded, expected failure, format %s.\n",
10041 formats[i].name);
10042 if (SUCCEEDED(hr))
10044 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10045 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10048 box.Left = 0;
10049 box.Top = 0;
10050 box.Right = formats[i].block_width >> 1;
10051 box.Bottom = formats[i].block_height;
10052 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10053 ok(FAILED(hr) || broken(formats[i].broken),
10054 "Partial block lock succeeded, expected failure, format %s.\n",
10055 formats[i].name);
10056 if (SUCCEEDED(hr))
10058 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10059 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10063 if (formats[i].block_height > 1)
10065 box.Left = 0;
10066 box.Top = formats[i].block_height >> 1;
10067 box.Right = formats[i].block_width;
10068 box.Bottom = formats[i].block_height;
10069 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10070 ok(FAILED(hr) || broken(formats[i].broken),
10071 "Partial block lock succeeded, expected failure, format %s.\n",
10072 formats[i].name);
10073 if (SUCCEEDED(hr))
10075 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10076 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10079 box.Left = 0;
10080 box.Top = 0;
10081 box.Right = formats[i].block_width;
10082 box.Bottom = formats[i].block_height >> 1;
10083 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10084 ok(FAILED(hr) || broken(formats[i].broken),
10085 "Partial block lock succeeded, expected failure, format %s.\n",
10086 formats[i].name);
10087 if (SUCCEEDED(hr))
10089 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10090 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10094 /* Test full block lock */
10095 box.Left = 0;
10096 box.Top = 0;
10097 box.Right = formats[i].block_width;
10098 box.Bottom = formats[i].block_height;
10099 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10100 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10101 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10102 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10104 IDirect3DVolumeTexture9_Release(texture);
10106 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
10107 * does not allocate surfaces smaller than the blocksize properly. */
10108 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
10110 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
10111 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
10112 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10114 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
10115 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10116 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10117 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10119 box.Left = box.Top = box.Front = 0;
10120 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
10121 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
10122 box.Back = 1;
10123 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10124 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10125 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10126 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10128 box.Right = formats[i].block_width;
10129 box.Bottom = formats[i].block_height;
10130 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10131 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10132 if (SUCCEEDED(hr))
10133 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10135 IDirect3DVolumeTexture9_Release(texture);
10139 refcount = IDirect3DDevice9_Release(device);
10140 ok(!refcount, "Device has %u references left.\n", refcount);
10141 IDirect3D9_Release(d3d9);
10142 DestroyWindow(window);
10145 static void test_lockbox_invalid(void)
10147 static const struct
10149 D3DBOX box;
10150 HRESULT result;
10152 test_data[] =
10154 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
10155 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
10156 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
10157 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
10158 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
10159 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
10160 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
10161 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
10162 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
10163 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
10164 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
10165 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
10166 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
10167 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
10169 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
10170 IDirect3DVolumeTexture9 *texture = NULL;
10171 D3DLOCKED_BOX locked_box;
10172 IDirect3DDevice9 *device;
10173 IDirect3D9 *d3d;
10174 unsigned int i;
10175 ULONG refcount;
10176 HWND window;
10177 BYTE *base;
10178 HRESULT hr;
10180 window = create_window();
10181 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10182 ok(!!d3d, "Failed to create a D3D object.\n");
10183 if (!(device = create_device(d3d, window, NULL)))
10185 skip("Failed to create a D3D device, skipping tests.\n");
10186 IDirect3D9_Release(d3d);
10187 DestroyWindow(window);
10188 return;
10191 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
10192 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
10193 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10194 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10195 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10196 base = locked_box.pBits;
10197 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10198 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10200 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10202 unsigned int offset, expected_offset;
10203 const D3DBOX *box = &test_data[i].box;
10205 locked_box.pBits = (BYTE *)0xdeadbeef;
10206 locked_box.RowPitch = 0xdeadbeef;
10207 locked_box.SlicePitch = 0xdeadbeef;
10209 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
10210 /* Unlike surfaces, volumes properly check the box even in Windows XP */
10211 ok(hr == test_data[i].result,
10212 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
10213 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
10214 test_data[i].result);
10215 if (FAILED(hr))
10216 continue;
10218 offset = (BYTE *)locked_box.pBits - base;
10219 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
10220 ok(offset == expected_offset,
10221 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
10222 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
10224 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10225 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10228 /* locked_box = NULL throws an exception on Windows */
10229 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10230 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10231 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10232 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10233 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10234 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10235 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10236 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10238 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10239 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10240 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10241 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10242 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10243 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10244 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10245 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10246 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
10247 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10248 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
10249 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
10250 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10251 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10253 IDirect3DVolumeTexture9_Release(texture);
10254 refcount = IDirect3DDevice9_Release(device);
10255 ok(!refcount, "Device has %u references left.\n", refcount);
10256 IDirect3D9_Release(d3d);
10257 DestroyWindow(window);
10260 static void test_shared_handle(void)
10262 IDirect3DDevice9 *device;
10263 IDirect3D9 *d3d;
10264 ULONG refcount;
10265 HWND window;
10266 HRESULT hr;
10267 /* Native d3d9ex refuses to create a shared texture if the texture pointer
10268 * is not initialized to NULL. Make sure this doesn't cause issues here. */
10269 IDirect3DTexture9 *texture = NULL;
10270 IDirect3DSurface9 *surface = NULL;
10271 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
10272 IDirect3DIndexBuffer9 *index_buffer = NULL;
10273 HANDLE handle = NULL;
10274 void *mem;
10275 D3DCAPS9 caps;
10277 window = create_window();
10278 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10279 ok(!!d3d, "Failed to create a D3D object.\n");
10280 if (!(device = create_device(d3d, window, NULL)))
10282 skip("Failed to create a D3D device, skipping tests.\n");
10283 IDirect3D9_Release(d3d);
10284 DestroyWindow(window);
10285 return;
10288 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10289 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10290 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
10292 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
10293 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
10294 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10295 D3DPOOL_DEFAULT, &texture, &handle);
10296 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10297 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10298 D3DPOOL_SYSTEMMEM, &texture, &mem);
10299 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10301 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10302 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
10303 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10304 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10305 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
10306 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10308 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10309 &vertex_buffer, &handle);
10310 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10311 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10312 &vertex_buffer, &mem);
10313 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
10315 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10316 &index_buffer, &handle);
10317 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10318 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10319 &index_buffer, &mem);
10320 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10322 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10324 IDirect3DCubeTexture9 *cube_texture = NULL;
10325 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10326 D3DPOOL_DEFAULT, &cube_texture, &handle);
10327 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10328 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10329 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
10330 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10333 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
10335 IDirect3DVolumeTexture9 *volume_texture = NULL;
10336 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10337 D3DPOOL_DEFAULT, &volume_texture, &handle);
10338 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10339 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10340 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
10341 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10344 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
10345 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10346 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10348 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
10349 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10350 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10352 HeapFree(GetProcessHeap(), 0, mem);
10353 refcount = IDirect3DDevice9_Release(device);
10354 ok(!refcount, "Device has %u references left.\n", refcount);
10355 IDirect3D9_Release(d3d);
10356 DestroyWindow(window);
10359 static void test_pixel_format(void)
10361 int format, test_format;
10362 PIXELFORMATDESCRIPTOR pfd;
10363 IDirect3D9 *d3d9 = NULL;
10364 IDirect3DDevice9 *device = NULL;
10365 HWND hwnd, hwnd2;
10366 HDC hdc, hdc2;
10367 HMODULE gl;
10368 HRESULT hr;
10370 static const float point[] = {0.0f, 0.0f, 0.0f};
10372 hwnd = create_window();
10373 ok(!!hwnd, "Failed to create window.\n");
10374 hwnd2 = create_window();
10375 ok(!!hwnd2, "Failed to create window.\n");
10377 hdc = GetDC(hwnd);
10378 ok(!!hdc, "Failed to get DC.\n");
10379 hdc2 = GetDC(hwnd2);
10380 ok(!!hdc2, "Failed to get DC.\n");
10382 gl = LoadLibraryA("opengl32.dll");
10383 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
10385 format = GetPixelFormat(hdc);
10386 ok(format == 0, "new window has pixel format %d\n", format);
10388 ZeroMemory(&pfd, sizeof(pfd));
10389 pfd.nSize = sizeof(pfd);
10390 pfd.nVersion = 1;
10391 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
10392 pfd.iPixelType = PFD_TYPE_RGBA;
10393 pfd.iLayerType = PFD_MAIN_PLANE;
10394 format = ChoosePixelFormat(hdc, &pfd);
10395 if (format <= 0)
10397 skip("no pixel format available\n");
10398 goto cleanup;
10401 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
10403 skip("failed to set pixel format\n");
10404 goto cleanup;
10407 if (!SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
10409 skip("failed to set pixel format on second window\n");
10410 goto cleanup;
10413 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
10414 ok(!!d3d9, "Failed to create a D3D object.\n");
10416 test_format = GetPixelFormat(hdc);
10417 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10419 if (!(device = create_device(d3d9, hwnd, NULL)))
10421 skip("Failed to create device\n");
10422 goto cleanup;
10425 test_format = GetPixelFormat(hdc);
10426 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10428 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10429 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10431 test_format = GetPixelFormat(hdc);
10432 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10434 hr = IDirect3DDevice9_BeginScene(device);
10435 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
10437 test_format = GetPixelFormat(hdc);
10438 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10440 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
10441 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10443 test_format = GetPixelFormat(hdc);
10444 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10446 hr = IDirect3DDevice9_EndScene(device);
10447 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
10449 test_format = GetPixelFormat(hdc);
10450 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10452 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10453 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10455 test_format = GetPixelFormat(hdc);
10456 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10458 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
10459 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10461 test_format = GetPixelFormat(hdc);
10462 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10464 test_format = GetPixelFormat(hdc2);
10465 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
10467 cleanup:
10468 if (device)
10470 UINT refcount = IDirect3DDevice9_Release(device);
10471 ok(!refcount, "Device has %u references left.\n", refcount);
10473 if (d3d9)
10474 IDirect3D9_Release(d3d9);
10475 FreeLibrary(gl);
10476 ReleaseDC(hwnd2, hdc2);
10477 ReleaseDC(hwnd, hdc);
10478 DestroyWindow(hwnd2);
10479 DestroyWindow(hwnd);
10482 static void test_begin_end_state_block(void)
10484 IDirect3DStateBlock9 *stateblock;
10485 IDirect3DDevice9 *device;
10486 IDirect3D9 *d3d;
10487 ULONG refcount;
10488 HWND window;
10489 HRESULT hr;
10491 window = create_window();
10492 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10493 ok(!!d3d, "Failed to create a D3D object.\n");
10494 if (!(device = create_device(d3d, window, NULL)))
10496 skip("Failed to create a D3D device, skipping tests.\n");
10497 IDirect3D9_Release(d3d);
10498 DestroyWindow(window);
10499 return;
10502 /* Should succeed. */
10503 hr = IDirect3DDevice9_BeginStateBlock(device);
10504 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10506 /* Calling BeginStateBlock() while recording should return
10507 * D3DERR_INVALIDCALL. */
10508 hr = IDirect3DDevice9_BeginStateBlock(device);
10509 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10511 /* Should succeed. */
10512 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10513 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10514 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10515 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10516 "Got unexpected stateblock %p.\n", stateblock);
10517 IDirect3DStateBlock9_Release(stateblock);
10519 /* Calling EndStateBlock() while not recording should return
10520 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10521 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10522 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10523 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10524 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10525 "Got unexpected stateblock %p.\n", stateblock);
10527 refcount = IDirect3DDevice9_Release(device);
10528 ok(!refcount, "Device has %u references left.\n", refcount);
10529 IDirect3D9_Release(d3d);
10530 DestroyWindow(window);
10533 static void test_shader_constant_apply(void)
10535 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10536 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10537 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10538 IDirect3DStateBlock9 *stateblock;
10539 DWORD vs_version, ps_version;
10540 IDirect3DDevice9 *device;
10541 IDirect3D9 *d3d;
10542 ULONG refcount;
10543 D3DCAPS9 caps;
10544 float ret[4];
10545 HWND window;
10546 HRESULT hr;
10548 window = create_window();
10549 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10550 ok(!!d3d, "Failed to create a D3D object.\n");
10551 if (!(device = create_device(d3d, window, NULL)))
10553 skip("Failed to create a D3D device, skipping tests.\n");
10554 IDirect3D9_Release(d3d);
10555 DestroyWindow(window);
10556 return;
10559 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10560 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10561 vs_version = caps.VertexShaderVersion & 0xffff;
10562 ps_version = caps.PixelShaderVersion & 0xffff;
10564 if (vs_version)
10566 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10567 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10568 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10569 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10571 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10572 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10573 ok(!memcmp(ret, initial, sizeof(initial)),
10574 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10575 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10576 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10577 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10578 ok(!memcmp(ret, initial, sizeof(initial)),
10579 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10580 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10582 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10583 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10585 if (ps_version)
10587 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10588 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10589 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10590 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10592 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10593 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10594 ok(!memcmp(ret, initial, sizeof(initial)),
10595 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10596 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10597 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10598 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10599 ok(!memcmp(ret, initial, sizeof(initial)),
10600 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10601 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10603 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10604 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10607 hr = IDirect3DDevice9_BeginStateBlock(device);
10608 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10610 if (vs_version)
10612 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10613 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10615 if (ps_version)
10617 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10618 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10621 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10622 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10624 if (vs_version)
10626 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10627 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10628 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10629 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10630 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10631 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10632 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10633 ok(!memcmp(ret, initial, sizeof(initial)),
10634 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10635 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10637 if (ps_version)
10639 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10640 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10641 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10642 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10643 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10644 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10645 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10646 ok(!memcmp(ret, initial, sizeof(initial)),
10647 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10648 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10651 /* Apply doesn't overwrite constants that aren't explicitly set on the
10652 * source stateblock. */
10653 hr = IDirect3DStateBlock9_Apply(stateblock);
10654 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10656 if (vs_version)
10658 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10659 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10660 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10661 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10662 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10663 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10664 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10665 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10666 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10667 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10669 if (ps_version)
10671 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10672 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10673 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10674 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10675 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10676 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10677 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10678 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10679 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10680 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10683 IDirect3DStateBlock9_Release(stateblock);
10684 refcount = IDirect3DDevice9_Release(device);
10685 ok(!refcount, "Device has %u references left.\n", refcount);
10686 IDirect3D9_Release(d3d);
10687 DestroyWindow(window);
10690 static void test_vdecl_apply(void)
10692 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10693 IDirect3DStateBlock9 *stateblock;
10694 IDirect3DDevice9 *device;
10695 IDirect3D9 *d3d;
10696 ULONG refcount;
10697 HWND window;
10698 HRESULT hr;
10700 static const D3DVERTEXELEMENT9 decl1[] =
10702 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10703 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10704 D3DDECL_END(),
10707 static const D3DVERTEXELEMENT9 decl2[] =
10709 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10710 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10711 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10712 D3DDECL_END(),
10715 window = create_window();
10716 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10717 ok(!!d3d, "Failed to create a D3D object.\n");
10718 if (!(device = create_device(d3d, window, NULL)))
10720 skip("Failed to create a D3D device, skipping tests.\n");
10721 IDirect3D9_Release(d3d);
10722 DestroyWindow(window);
10723 return;
10726 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10727 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10729 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10730 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10732 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10733 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10734 hr = IDirect3DDevice9_BeginStateBlock(device);
10735 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10736 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10737 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10738 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10739 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10740 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10741 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10742 hr = IDirect3DStateBlock9_Apply(stateblock);
10743 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10744 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10745 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10746 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10747 declaration, declaration1);
10748 IDirect3DVertexDeclaration9_Release(declaration);
10750 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10751 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10752 hr = IDirect3DStateBlock9_Capture(stateblock);
10753 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10754 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10755 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10756 hr = IDirect3DStateBlock9_Apply(stateblock);
10757 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10758 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10759 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10760 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10761 declaration, declaration2);
10762 IDirect3DVertexDeclaration9_Release(declaration);
10764 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10765 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10766 hr = IDirect3DStateBlock9_Capture(stateblock);
10767 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10768 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10769 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10770 hr = IDirect3DStateBlock9_Apply(stateblock);
10771 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10772 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10773 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10774 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10775 declaration, declaration2);
10776 IDirect3DVertexDeclaration9_Release(declaration);
10778 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10779 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10780 hr = IDirect3DStateBlock9_Capture(stateblock);
10781 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10782 hr = IDirect3DStateBlock9_Apply(stateblock);
10783 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10784 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10785 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10786 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10788 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10789 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10790 hr = IDirect3DStateBlock9_Capture(stateblock);
10791 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10792 hr = IDirect3DStateBlock9_Apply(stateblock);
10793 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10794 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10795 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10796 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10797 declaration, declaration2);
10798 IDirect3DVertexDeclaration9_Release(declaration);
10800 IDirect3DStateBlock9_Release(stateblock);
10801 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10802 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10803 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10804 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10805 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10806 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10807 hr = IDirect3DStateBlock9_Apply(stateblock);
10808 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10809 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10810 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10811 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10812 declaration, declaration1);
10813 IDirect3DVertexDeclaration9_Release(declaration);
10815 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10816 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10817 hr = IDirect3DStateBlock9_Capture(stateblock);
10818 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10819 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10820 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10821 hr = IDirect3DStateBlock9_Apply(stateblock);
10822 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10823 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10824 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10825 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10826 declaration, declaration2);
10827 IDirect3DVertexDeclaration9_Release(declaration);
10829 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10830 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10831 hr = IDirect3DStateBlock9_Capture(stateblock);
10832 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10833 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10834 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10835 hr = IDirect3DStateBlock9_Apply(stateblock);
10836 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10837 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10838 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10839 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10840 declaration, declaration2);
10841 IDirect3DVertexDeclaration9_Release(declaration);
10843 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10844 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10845 hr = IDirect3DStateBlock9_Capture(stateblock);
10846 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10847 hr = IDirect3DStateBlock9_Apply(stateblock);
10848 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10849 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10850 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10851 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10853 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10854 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10855 hr = IDirect3DStateBlock9_Capture(stateblock);
10856 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10857 hr = IDirect3DStateBlock9_Apply(stateblock);
10858 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10859 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10860 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10861 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10862 declaration, declaration2);
10863 IDirect3DVertexDeclaration9_Release(declaration);
10865 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10866 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10867 IDirect3DVertexDeclaration9_Release(declaration1);
10868 IDirect3DVertexDeclaration9_Release(declaration2);
10869 IDirect3DStateBlock9_Release(stateblock);
10870 refcount = IDirect3DDevice9_Release(device);
10871 ok(!refcount, "Device has %u references left.\n", refcount);
10872 IDirect3D9_Release(d3d);
10873 DestroyWindow(window);
10876 static void test_resource_type(void)
10878 IDirect3DDevice9 *device;
10879 IDirect3DSurface9 *surface;
10880 IDirect3DTexture9 *texture;
10881 IDirect3DCubeTexture9 *cube_texture;
10882 IDirect3DVolume9 *volume;
10883 IDirect3DVolumeTexture9 *volume_texture;
10884 D3DSURFACE_DESC surface_desc;
10885 D3DVOLUME_DESC volume_desc;
10886 D3DRESOURCETYPE type;
10887 IDirect3D9 *d3d;
10888 ULONG refcount;
10889 HWND window;
10890 HRESULT hr;
10891 D3DCAPS9 caps;
10893 window = create_window();
10894 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10895 ok(!!d3d, "Failed to create a D3D object.\n");
10896 if (!(device = create_device(d3d, window, NULL)))
10898 skip("Failed to create a D3D device, skipping tests.\n");
10899 IDirect3D9_Release(d3d);
10900 DestroyWindow(window);
10901 return;
10904 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10905 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10907 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10908 D3DPOOL_SYSTEMMEM, &surface, NULL);
10909 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10910 type = IDirect3DSurface9_GetType(surface);
10911 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10912 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10913 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10914 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10915 surface_desc.Type);
10916 IDirect3DSurface9_Release(surface);
10918 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10919 D3DPOOL_SYSTEMMEM, &texture, NULL);
10920 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10921 type = IDirect3DTexture9_GetType(texture);
10922 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10924 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10925 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10926 /* The following code crashes, for the sake of completeness:
10927 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10928 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10930 * So applications will not depend on getting the "right" resource type - whatever it
10931 * may be - from the "wrong" vtable. */
10932 type = IDirect3DSurface9_GetType(surface);
10933 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10934 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10935 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10936 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10937 surface_desc.Type);
10938 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10939 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10940 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10941 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10942 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10943 surface_desc.Type);
10944 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10945 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10946 IDirect3DSurface9_Release(surface);
10948 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10949 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10950 type = IDirect3DSurface9_GetType(surface);
10951 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10952 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10953 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10954 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10955 surface_desc.Type);
10956 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10957 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10958 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10959 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10960 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10961 surface_desc.Type);
10962 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10963 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10964 IDirect3DSurface9_Release(surface);
10965 IDirect3DTexture9_Release(texture);
10967 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10969 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10970 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10971 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10972 type = IDirect3DCubeTexture9_GetType(cube_texture);
10973 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10975 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10976 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10977 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10978 type = IDirect3DSurface9_GetType(surface);
10979 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10980 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10981 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10982 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10983 surface_desc.Type);
10984 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10985 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10986 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10987 surface_desc.Type);
10988 IDirect3DSurface9_Release(surface);
10989 IDirect3DCubeTexture9_Release(cube_texture);
10991 else
10992 skip("Cube maps not supported.\n");
10994 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10996 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10997 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10998 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10999 type = IDirect3DVolumeTexture9_GetType(volume_texture);
11000 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
11002 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
11003 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
11004 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
11005 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
11006 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
11007 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11008 volume_desc.Type);
11009 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
11010 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
11011 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
11012 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
11013 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
11014 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11015 volume_desc.Type);
11016 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
11017 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
11018 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
11019 IDirect3DVolume9_Release(volume);
11021 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
11022 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
11023 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
11024 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
11025 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
11026 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11027 volume_desc.Type);
11028 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
11029 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
11030 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
11031 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
11032 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
11033 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11034 volume_desc.Type);
11035 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
11036 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
11037 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
11038 IDirect3DVolume9_Release(volume);
11039 IDirect3DVolumeTexture9_Release(volume_texture);
11041 else
11042 skip("Mipmapped volume maps not supported.\n");
11044 refcount = IDirect3DDevice9_Release(device);
11045 ok(!refcount, "Device has %u references left.\n", refcount);
11046 IDirect3D9_Release(d3d);
11047 DestroyWindow(window);
11050 static void test_mipmap_lock(void)
11052 IDirect3DDevice9 *device;
11053 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
11054 IDirect3DTexture9 *texture, *texture_dst;
11055 IDirect3D9 *d3d;
11056 ULONG refcount;
11057 HWND window;
11058 HRESULT hr;
11059 D3DLOCKED_RECT locked_rect;
11061 window = create_window();
11062 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11063 ok(!!d3d, "Failed to create a D3D object.\n");
11064 if (!(device = create_device(d3d, window, NULL)))
11066 skip("Failed to create a D3D device, skipping tests.\n");
11067 IDirect3D9_Release(d3d);
11068 DestroyWindow(window);
11069 return;
11072 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11073 D3DPOOL_DEFAULT, &texture_dst, NULL);
11074 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11075 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
11076 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11077 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
11078 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11080 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11081 D3DPOOL_SYSTEMMEM, &texture, NULL);
11082 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11083 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11084 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11085 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
11086 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11088 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
11089 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11090 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
11091 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11092 hr = IDirect3DSurface9_UnlockRect(surface);
11093 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11095 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
11096 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
11097 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
11098 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11100 /* Apparently there's no validation on the container. */
11101 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
11102 (IDirect3DBaseTexture9 *)texture_dst);
11103 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
11105 hr = IDirect3DSurface9_UnlockRect(surface2);
11106 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11108 IDirect3DSurface9_Release(surface_dst2);
11109 IDirect3DSurface9_Release(surface_dst);
11110 IDirect3DSurface9_Release(surface2);
11111 IDirect3DSurface9_Release(surface);
11112 IDirect3DTexture9_Release(texture_dst);
11113 IDirect3DTexture9_Release(texture);
11115 refcount = IDirect3DDevice9_Release(device);
11116 ok(!refcount, "Device has %u references left.\n", refcount);
11117 IDirect3D9_Release(d3d);
11118 DestroyWindow(window);
11121 static void test_writeonly_resource(void)
11123 IDirect3D9 *d3d;
11124 IDirect3DDevice9 *device;
11125 IDirect3DVertexBuffer9 *buffer;
11126 ULONG refcount;
11127 HWND window;
11128 HRESULT hr;
11129 void *ptr;
11130 static const struct
11132 struct vec3 pos;
11134 quad[] =
11136 {{-1.0f, -1.0f, 0.0f}},
11137 {{-1.0f, 1.0f, 0.0f}},
11138 {{ 1.0f, -1.0f, 0.0f}},
11139 {{ 1.0f, 1.0f, 0.0f}}
11142 window = create_window();
11143 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11144 ok(!!d3d, "Failed to create a D3D object.\n");
11145 if (!(device = create_device(d3d, window, NULL)))
11147 skip("Failed to create a D3D device, skipping tests.\n");
11148 IDirect3D9_Release(d3d);
11149 DestroyWindow(window);
11150 return;
11153 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
11154 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
11155 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
11157 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
11158 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11159 memcpy(ptr, quad, sizeof(quad));
11160 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11161 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11162 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
11163 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
11164 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
11165 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
11167 hr = IDirect3DDevice9_BeginScene(device);
11168 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
11169 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
11170 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11171 hr = IDirect3DDevice9_EndScene(device);
11172 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
11174 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
11175 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11176 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11177 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11178 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11180 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
11181 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11182 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11183 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11184 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11186 refcount = IDirect3DVertexBuffer9_Release(buffer);
11187 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
11188 refcount = IDirect3DDevice9_Release(device);
11189 ok(!refcount, "Device has %u references left.\n", refcount);
11190 IDirect3D9_Release(d3d);
11191 DestroyWindow(window);
11194 static void test_lost_device(void)
11196 struct device_desc device_desc;
11197 IDirect3DDevice9 *device;
11198 IDirect3D9 *d3d;
11199 ULONG refcount;
11200 HWND window;
11201 HRESULT hr;
11202 BOOL ret;
11204 window = create_window();
11205 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11206 ok(!!d3d, "Failed to create a D3D object.\n");
11207 device_desc.device_window = window;
11208 device_desc.width = registry_mode.dmPelsWidth;
11209 device_desc.height = registry_mode.dmPelsHeight;
11210 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11211 if (!(device = create_device(d3d, window, &device_desc)))
11213 skip("Failed to create a D3D device, skipping tests.\n");
11214 goto done;
11217 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11218 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11219 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11220 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11222 ret = SetForegroundWindow(GetDesktopWindow());
11223 ok(ret, "Failed to set foreground window.\n");
11224 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11225 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11226 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11227 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11229 ret = ShowWindow(window, SW_RESTORE);
11230 ok(ret, "Failed to restore window.\n");
11231 ret = SetForegroundWindow(window);
11232 ok(ret, "Failed to set foreground window.\n");
11233 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11234 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
11235 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11236 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11238 hr = reset_device(device, &device_desc);
11239 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11240 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11241 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11242 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11243 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11245 device_desc.flags = 0;
11246 hr = reset_device(device, &device_desc);
11247 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11248 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11249 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11250 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11251 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11253 ret = SetForegroundWindow(GetDesktopWindow());
11254 ok(ret, "Failed to set foreground window.\n");
11255 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11256 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11257 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11258 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11260 ret = ShowWindow(window, SW_RESTORE);
11261 ok(ret, "Failed to restore window.\n");
11262 ret = SetForegroundWindow(window);
11263 ok(ret, "Failed to set foreground window.\n");
11264 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11265 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11266 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11267 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11269 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11270 hr = reset_device(device, &device_desc);
11271 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11272 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11273 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11274 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11275 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11277 ret = SetForegroundWindow(GetDesktopWindow());
11278 ok(ret, "Failed to set foreground window.\n");
11279 hr = reset_device(device, &device_desc);
11280 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11281 ret = ShowWindow(window, SW_RESTORE);
11282 ok(ret, "Failed to restore window.\n");
11283 ret = SetForegroundWindow(window);
11284 ok(ret, "Failed to set foreground window.\n");
11285 hr = reset_device(device, &device_desc);
11286 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11288 refcount = IDirect3DDevice9_Release(device);
11289 ok(!refcount, "Device has %u references left.\n", refcount);
11290 done:
11291 IDirect3D9_Release(d3d);
11292 DestroyWindow(window);
11295 static void test_resource_priority(void)
11297 IDirect3DDevice9 *device;
11298 IDirect3DSurface9 *surface;
11299 IDirect3DTexture9 *texture;
11300 IDirect3DVertexBuffer9 *buffer;
11301 IDirect3D9 *d3d;
11302 ULONG refcount;
11303 HWND window;
11304 HRESULT hr;
11305 static const struct
11307 D3DPOOL pool;
11308 const char *name;
11309 BOOL can_set_priority;
11311 test_data[] =
11313 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
11314 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
11315 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
11316 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
11318 unsigned int i;
11319 DWORD priority;
11321 window = create_window();
11322 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11323 ok(!!d3d, "Failed to create a D3D object.\n");
11324 if (!(device = create_device(d3d, window, NULL)))
11326 skip("Failed to create a D3D device, skipping tests.\n");
11327 IDirect3D9_Release(d3d);
11328 DestroyWindow(window);
11329 return;
11332 for (i = 0; i < ARRAY_SIZE(test_data); i++)
11334 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
11335 test_data[i].pool, &texture, NULL);
11336 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
11337 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11338 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11340 priority = IDirect3DTexture9_GetPriority(texture);
11341 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11342 priority = IDirect3DTexture9_SetPriority(texture, 1);
11343 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11344 priority = IDirect3DTexture9_GetPriority(texture);
11345 if (test_data[i].can_set_priority)
11347 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11348 priority = IDirect3DTexture9_SetPriority(texture, 2);
11349 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11351 else
11352 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11354 priority = IDirect3DSurface9_GetPriority(surface);
11355 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11356 priority = IDirect3DSurface9_SetPriority(surface, 1);
11357 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11358 priority = IDirect3DSurface9_GetPriority(surface);
11359 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11361 IDirect3DSurface9_Release(surface);
11362 IDirect3DTexture9_Release(texture);
11364 if (test_data[i].pool != D3DPOOL_MANAGED)
11366 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
11367 test_data[i].pool, &surface, NULL);
11368 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
11370 priority = IDirect3DSurface9_GetPriority(surface);
11371 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11372 priority = IDirect3DSurface9_SetPriority(surface, 1);
11373 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11374 priority = IDirect3DSurface9_GetPriority(surface);
11375 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11377 IDirect3DSurface9_Release(surface);
11380 if (test_data[i].pool != D3DPOOL_SCRATCH)
11382 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
11383 test_data[i].pool, &buffer, NULL);
11384 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
11386 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11387 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11388 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
11389 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11390 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11391 if (test_data[i].can_set_priority)
11393 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11394 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
11395 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11397 else
11398 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11400 IDirect3DVertexBuffer9_Release(buffer);
11404 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
11405 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11407 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11408 priority = IDirect3DSurface9_GetPriority(surface);
11409 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11410 priority = IDirect3DSurface9_SetPriority(surface, 1);
11411 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11412 priority = IDirect3DSurface9_GetPriority(surface);
11413 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11415 IDirect3DSurface9_Release(surface);
11417 refcount = IDirect3DDevice9_Release(device);
11418 ok(!refcount, "Device has %u references left.\n", refcount);
11419 IDirect3D9_Release(d3d);
11420 DestroyWindow(window);
11423 static void test_swapchain_parameters(void)
11425 IDirect3DDevice9 *device;
11426 HRESULT hr, expected_hr;
11427 IDirect3D9 *d3d;
11428 D3DCAPS9 caps;
11429 HWND window;
11430 unsigned int i;
11431 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
11432 IDirect3DSwapChain9 *swapchain;
11433 static const struct
11435 BOOL windowed;
11436 UINT backbuffer_count;
11437 D3DSWAPEFFECT swap_effect;
11438 HRESULT hr;
11440 tests[] =
11442 /* Swap effect 0 is not allowed. */
11443 {TRUE, 1, 0, D3DERR_INVALIDCALL},
11444 {FALSE, 1, 0, D3DERR_INVALIDCALL},
11446 /* All (non-ex) swap effects are allowed in
11447 * windowed and fullscreen mode. */
11448 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11449 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11450 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11451 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11452 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11454 /* Only one backbuffer in copy mode. */
11455 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
11456 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11457 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11458 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11460 /* Ok with the others, in fullscreen and windowed mode. */
11461 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11462 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11463 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11464 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11466 /* D3D9Ex swap effects. */
11467 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11468 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11469 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11470 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11471 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11472 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11474 /* 3 is the highest allowed backbuffer count. */
11475 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11476 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11477 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11478 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11479 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11482 window = create_window();
11483 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11484 ok(!!d3d, "Failed to create a D3D object.\n");
11485 if (!(device = create_device(d3d, window, NULL)))
11487 skip("Failed to create a D3D device, skipping tests.\n");
11488 IDirect3D9_Release(d3d);
11489 DestroyWindow(window);
11490 return;
11492 memset(&caps, 0, sizeof(caps));
11493 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11494 ok(hr == D3D_OK, "Failed to get device caps, hr %#x.\n", hr);
11495 IDirect3DDevice9_Release(device);
11497 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11498 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11499 present_parameters_windowed.hDeviceWindow = window;
11500 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11501 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11502 present_parameters_windowed.Windowed = TRUE;
11503 present_parameters_windowed.BackBufferCount = 1;
11505 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11507 memset(&present_parameters, 0, sizeof(present_parameters));
11508 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11509 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11510 present_parameters.hDeviceWindow = window;
11511 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11513 present_parameters.SwapEffect = tests[i].swap_effect;
11514 present_parameters.Windowed = tests[i].windowed;
11515 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11517 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11518 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11519 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11520 if (SUCCEEDED(hr))
11522 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11524 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11525 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11527 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11528 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11529 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11530 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11531 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11532 bb_count, present_parameters2.BackBufferCount, i);
11533 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11534 tests[i].windowed, present_parameters2.Windowed, i);
11536 IDirect3DSwapChain9_Release(swapchain);
11537 IDirect3DDevice9_Release(device);
11540 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11541 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11542 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11544 memset(&present_parameters, 0, sizeof(present_parameters));
11545 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11546 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11547 present_parameters.hDeviceWindow = window;
11548 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11550 present_parameters.SwapEffect = tests[i].swap_effect;
11551 present_parameters.Windowed = tests[i].windowed;
11552 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11554 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11555 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11557 if (FAILED(hr))
11559 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11560 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11562 IDirect3DDevice9_Release(device);
11565 for (i = 0; i < 10; ++i)
11567 memset(&present_parameters, 0, sizeof(present_parameters));
11568 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11569 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11570 present_parameters.hDeviceWindow = window;
11571 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11572 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
11573 present_parameters.Windowed = FALSE;
11574 present_parameters.BackBufferCount = 2;
11576 present_parameters.PresentationInterval = i;
11577 switch (present_parameters.PresentationInterval)
11579 case D3DPRESENT_INTERVAL_ONE:
11580 case D3DPRESENT_INTERVAL_TWO:
11581 case D3DPRESENT_INTERVAL_THREE:
11582 case D3DPRESENT_INTERVAL_FOUR:
11583 if (!(caps.PresentationIntervals & present_parameters.PresentationInterval))
11584 continue;
11585 /* Fall through */
11586 case D3DPRESENT_INTERVAL_DEFAULT:
11587 expected_hr = D3D_OK;
11588 break;
11589 default:
11590 expected_hr = D3DERR_INVALIDCALL;
11591 break;
11594 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11595 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11596 ok(hr == expected_hr, "Got unexpected hr %#x, test %u.\n", hr, i);
11597 if (FAILED(hr))
11598 continue;
11600 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11601 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11603 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11604 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11605 ok(present_parameters2.PresentationInterval == i,
11606 "Got presentation interval %#x, expected %#x.\n",
11607 present_parameters2.PresentationInterval, i);
11609 IDirect3DSwapChain9_Release(swapchain);
11610 IDirect3DDevice9_Release(device);
11613 IDirect3D9_Release(d3d);
11614 DestroyWindow(window);
11617 static void test_check_device_format(void)
11619 static const D3DFORMAT adapter_formats[] =
11621 D3DFMT_A8R8G8B8,
11622 D3DFMT_X8R8G8B8,
11624 static const D3DFORMAT mipmap_autogen_formats[] =
11626 D3DFMT_R8G8B8,
11627 D3DFMT_A8R8G8B8,
11628 D3DFMT_X8R8G8B8,
11629 D3DFMT_R5G6B5,
11630 D3DFMT_X1R5G5B5,
11631 D3DFMT_A8P8,
11632 D3DFMT_P8,
11633 D3DFMT_A1R5G5B5,
11634 D3DFMT_A4R4G4B4,
11637 D3DFORMAT adapter_format, format;
11638 BOOL render_target_supported;
11639 D3DDEVTYPE device_type;
11640 unsigned int i, j;
11641 IDirect3D9 *d3d;
11642 HRESULT hr;
11644 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11645 ok(!!d3d, "Failed to create a D3D object.\n");
11647 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11648 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11650 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11652 else
11654 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11655 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11656 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11657 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11658 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11659 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11662 for (device_type = D3DDEVTYPE_HAL; device_type < D3DDEVTYPE_NULLREF; ++device_type)
11664 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11665 0, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11666 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11667 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11668 0, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8);
11669 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11670 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11671 0, D3DRTYPE_SURFACE, D3DFMT_X8R8G8B8);
11672 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11673 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, device_type, D3DFMT_UNKNOWN,
11674 0, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8);
11675 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, device type %#x.\n", hr, device_type);
11678 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11679 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11680 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11681 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11682 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11683 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11684 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11685 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11686 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11688 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11689 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11690 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11691 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11692 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11693 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11694 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11695 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11696 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11698 for (i = 0; i < ARRAY_SIZE(adapter_formats); ++i)
11700 adapter_format = adapter_formats[i];
11702 for (j = 0; j < ARRAY_SIZE(mipmap_autogen_formats); ++j)
11704 format = mipmap_autogen_formats[j];
11706 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, adapter_format,
11707 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, format);
11708 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
11709 render_target_supported = hr == D3D_OK;
11711 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, adapter_format,
11712 D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, format);
11713 if (render_target_supported)
11715 ok(hr == D3D_OK || hr == D3DOK_NOAUTOGEN, "Got unexpected hr %#x.\n", hr);
11717 else
11719 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
11724 IDirect3D9_Release(d3d);
11727 static void test_miptree_layout(void)
11729 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11730 IDirect3DCubeTexture9 *texture_cube;
11731 IDirect3DTexture9 *texture_2d;
11732 IDirect3DDevice9 *device;
11733 D3DLOCKED_RECT map_desc;
11734 BYTE *base = NULL;
11735 IDirect3D9 *d3d;
11736 D3DCAPS9 caps;
11737 UINT refcount;
11738 HWND window;
11739 HRESULT hr;
11741 static const struct
11743 D3DFORMAT format;
11744 const char *name;
11746 formats[] =
11748 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11749 {D3DFMT_A8, "D3DFMT_A8"},
11750 {D3DFMT_L8, "D3DFMT_L8"},
11751 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11752 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11754 static const struct
11756 D3DPOOL pool;
11757 const char *name;
11759 pools[] =
11761 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11762 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11763 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11766 window = create_window();
11767 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11768 ok(!!d3d, "Failed to create a D3D object.\n");
11769 if (!(device = create_device(d3d, window, NULL)))
11771 skip("Failed to create a D3D device, skipping tests.\n");
11772 goto done;
11775 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11776 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11778 base_dimension = 257;
11779 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11781 skip("Using power of two base dimension.\n");
11782 base_dimension = 256;
11785 for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx)
11787 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11788 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11790 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11791 continue;
11794 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11796 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11797 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11798 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11799 pools[pool_idx].name, formats[format_idx].name, hr);
11801 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11802 for (i = 0, offset = 0; i < level_count; ++i)
11804 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11805 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11806 pools[pool_idx].name, formats[format_idx].name, i, hr);
11808 if (!i)
11809 base = map_desc.pBits;
11810 else
11811 ok(map_desc.pBits == base + offset,
11812 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11813 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11814 offset += (base_dimension >> i) * map_desc.Pitch;
11816 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11817 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11818 pools[pool_idx].name, formats[format_idx].name, i, hr);
11821 IDirect3DTexture9_Release(texture_2d);
11824 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11825 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11827 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11828 continue;
11831 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11833 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11834 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11835 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11836 pools[pool_idx].name, formats[format_idx].name, hr);
11838 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11839 for (i = 0, offset = 0; i < 6; ++i)
11841 for (j = 0; j < level_count; ++j)
11843 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11844 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11845 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11847 if (!i && !j)
11848 base = map_desc.pBits;
11849 else
11850 ok(map_desc.pBits == base + offset,
11851 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11852 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11853 offset += (base_dimension >> j) * map_desc.Pitch;
11855 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11856 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11857 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11859 offset = (offset + 15) & ~15;
11862 IDirect3DCubeTexture9_Release(texture_cube);
11866 refcount = IDirect3DDevice9_Release(device);
11867 ok(!refcount, "Device has %u references left.\n", refcount);
11868 done:
11869 IDirect3D9_Release(d3d);
11870 DestroyWindow(window);
11873 static void test_get_render_target_data(void)
11875 IDirect3DSurface9 *offscreen_surface, *render_target;
11876 IDirect3DDevice9 *device;
11877 IDirect3D9 *d3d;
11878 UINT refcount;
11879 HWND window;
11880 HRESULT hr;
11882 window = create_window();
11883 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11884 ok(!!d3d, "Failed to create a D3D object.\n");
11885 if (!(device = create_device(d3d, window, NULL)))
11887 skip("Failed to create a D3D device.\n");
11888 IDirect3D9_Release(d3d);
11889 DestroyWindow(window);
11890 return;
11893 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11894 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11895 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11897 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11898 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11899 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11901 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11902 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11904 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11905 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11907 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11908 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11910 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11911 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11913 IDirect3DSurface9_Release(render_target);
11914 IDirect3DSurface9_Release(offscreen_surface);
11915 refcount = IDirect3DDevice9_Release(device);
11916 ok(!refcount, "Device has %u references left.\n", refcount);
11917 IDirect3D9_Release(d3d);
11918 DestroyWindow(window);
11921 static void test_render_target_device_mismatch(void)
11923 IDirect3DDevice9 *device, *device2;
11924 IDirect3DSurface9 *surface, *rt;
11925 IDirect3D9 *d3d;
11926 UINT refcount;
11927 HWND window;
11928 HRESULT hr;
11930 window = create_window();
11931 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11932 ok(!!d3d, "Failed to create a D3D object.\n");
11933 if (!(device = create_device(d3d, window, NULL)))
11935 skip("Failed to create a D3D device.\n");
11936 IDirect3D9_Release(d3d);
11937 DestroyWindow(window);
11938 return;
11941 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
11942 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11944 device2 = create_device(d3d, window, NULL);
11945 ok(!!device2, "Failed to create a D3D device.\n");
11947 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11948 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11949 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11951 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11952 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11954 IDirect3DSurface9_Release(surface);
11956 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11957 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11959 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11960 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11962 IDirect3DSurface9_Release(surface);
11964 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11965 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11966 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11967 IDirect3DSurface9_Release(surface);
11968 IDirect3DSurface9_Release(rt);
11970 refcount = IDirect3DDevice9_Release(device);
11971 ok(!refcount, "Device has %u references left.\n", refcount);
11972 refcount = IDirect3DDevice9_Release(device2);
11973 ok(!refcount, "Device has %u references left.\n", refcount);
11974 IDirect3D9_Release(d3d);
11975 DestroyWindow(window);
11978 static void test_format_unknown(void)
11980 IDirect3DDevice9 *device;
11981 IDirect3D9 *d3d;
11982 UINT refcount;
11983 HWND window;
11984 void *iface;
11985 HRESULT hr;
11987 window = create_window();
11988 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11989 ok(!!d3d, "Failed to create a D3D object.\n");
11990 if (!(device = create_device(d3d, window, NULL)))
11992 skip("Failed to create a D3D device.\n");
11993 IDirect3D9_Release(d3d);
11994 DestroyWindow(window);
11995 return;
11998 iface = (void *)0xdeadbeef;
11999 hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64,
12000 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
12001 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12002 ok(!iface, "Got unexpected iface %p.\n", iface);
12004 iface = (void *)0xdeadbeef;
12005 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 64, 64,
12006 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
12007 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12008 ok(!iface, "Got unexpected iface %p.\n", iface);
12010 iface = (void *)0xdeadbeef;
12011 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
12012 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
12013 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12014 ok(!iface, "Got unexpected iface %p.\n", iface);
12016 iface = (void *)0xdeadbeef;
12017 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
12018 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
12019 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12020 ok(!iface, "Got unexpected iface %p.\n", iface);
12022 iface = (void *)0xdeadbeef;
12023 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 1, 0,
12024 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
12025 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12026 ok(!iface, "Got unexpected iface %p.\n", iface);
12028 iface = (void *)0xdeadbeef;
12029 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
12030 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
12031 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12032 ok(!iface, "Got unexpected iface %p.\n", iface);
12034 refcount = IDirect3DDevice9_Release(device);
12035 ok(!refcount, "Device has %u references left.\n", refcount);
12036 IDirect3D9_Release(d3d);
12037 DestroyWindow(window);
12040 static void test_destroyed_window(void)
12042 IDirect3DDevice9 *device;
12043 IDirect3D9 *d3d9;
12044 ULONG refcount;
12045 HWND window;
12046 HRESULT hr;
12048 /* No WS_VISIBLE. */
12049 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
12050 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12051 ok(!!window, "Failed to create a window.\n");
12053 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
12054 ok(!!d3d9, "Failed to create a D3D object.\n");
12055 device = create_device(d3d9, window, NULL);
12056 IDirect3D9_Release(d3d9);
12057 DestroyWindow(window);
12058 if (!device)
12060 skip("Failed to create a 3D device, skipping test.\n");
12061 return;
12064 hr = IDirect3DDevice9_BeginScene(device);
12065 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12066 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
12067 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12068 hr = IDirect3DDevice9_EndScene(device);
12069 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12070 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12071 ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
12073 refcount = IDirect3DDevice9_Release(device);
12074 ok(!refcount, "Device has %u references left.\n", refcount);
12077 static void test_lockable_backbuffer(void)
12079 D3DPRESENT_PARAMETERS present_parameters = {0};
12080 struct device_desc device_desc;
12081 IDirect3DSurface9 *surface;
12082 IDirect3DDevice9 *device;
12083 D3DLOCKED_RECT lockrect;
12084 IDirect3D9 *d3d;
12085 ULONG refcount;
12086 HWND window;
12087 HRESULT hr;
12088 HDC dc;
12090 window = create_window();
12091 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12092 ok(!!d3d, "Failed to create a D3D object.\n");
12094 if (!(device = create_device(d3d, window, NULL)))
12096 skip("Failed to create a D3D device, skipping tests.\n");
12097 IDirect3D9_Release(d3d);
12098 DestroyWindow(window);
12099 return;
12102 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12103 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12105 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12106 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12108 dc = (void *)0xdeadbeef;
12109 hr = IDirect3DSurface9_GetDC(surface, &dc);
12110 ok(dc == (void *)0xdeadbeef, "Unexpected DC returned.\n");
12111 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12113 IDirect3DSurface9_Release(surface);
12115 /* Reset with D3DPRESENTFLAG_LOCKABLE_BACKBUFFER. */
12116 present_parameters.BackBufferWidth = 640;
12117 present_parameters.BackBufferHeight = 480;
12118 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
12119 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
12120 present_parameters.hDeviceWindow = window;
12121 present_parameters.Windowed = TRUE;
12122 present_parameters.EnableAutoDepthStencil = TRUE;
12123 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
12124 present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
12126 hr = IDirect3DDevice9_Reset(device, &present_parameters);
12127 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
12129 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12130 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12132 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12133 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
12134 hr = IDirect3DSurface9_UnlockRect(surface);
12135 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
12137 IDirect3DSurface9_Release(surface);
12138 refcount = IDirect3DDevice9_Release(device);
12139 ok(!refcount, "Device has %u references left.\n", refcount);
12141 device_desc.width = 640;
12142 device_desc.height = 480;
12143 device_desc.device_window = window;
12144 device_desc.flags = CREATE_DEVICE_LOCKABLE_BACKBUFFER;
12146 device = create_device(d3d, window, &device_desc);
12147 ok(!!device, "Failed to create device.\n");
12149 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12150 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12152 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12153 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
12154 hr = IDirect3DSurface9_UnlockRect(surface);
12155 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
12157 IDirect3DSurface9_Release(surface);
12158 refcount = IDirect3DDevice9_Release(device);
12159 ok(!refcount, "Device has %u references left.\n", refcount);
12160 IDirect3D9_Release(d3d);
12161 DestroyWindow(window);
12164 static void test_clip_planes_limits(void)
12166 static const DWORD device_flags[] = {0, CREATE_DEVICE_SWVP_ONLY};
12167 IDirect3DDevice9 *device;
12168 struct device_desc desc;
12169 unsigned int i, j;
12170 IDirect3D9 *d3d;
12171 ULONG refcount;
12172 float plane[4];
12173 D3DCAPS9 caps;
12174 DWORD state;
12175 HWND window;
12176 HRESULT hr;
12178 window = create_window();
12179 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12180 ok(!!d3d, "Failed to create a D3D object.\n");
12182 for (i = 0; i < ARRAY_SIZE(device_flags); ++i)
12184 desc.device_window = window;
12185 desc.width = 640;
12186 desc.height = 480;
12187 desc.flags = device_flags[i];
12188 if (!(device = create_device(d3d, window, &desc)))
12190 skip("Failed to create D3D device, flags %#x.\n", desc.flags);
12191 continue;
12194 memset(&caps, 0, sizeof(caps));
12195 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12196 ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr);
12198 trace("Max user clip planes: %u.\n", caps.MaxUserClipPlanes);
12200 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12202 memset(plane, 0xff, sizeof(plane));
12203 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12204 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12205 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
12206 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12207 j, plane[0], plane[1], plane[2], plane[3]);
12210 plane[0] = 2.0f;
12211 plane[1] = 8.0f;
12212 plane[2] = 5.0f;
12213 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12215 plane[3] = j;
12216 hr = IDirect3DDevice9_SetClipPlane(device, j, plane);
12217 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", j, hr);
12219 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12221 float expected_d = j >= caps.MaxUserClipPlanes - 1 ? 2 * D3DMAXUSERCLIPPLANES - 1 : j;
12222 memset(plane, 0xff, sizeof(plane));
12223 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12224 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12225 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == expected_d,
12226 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12227 j, plane[0], plane[1], plane[2], plane[3]);
12230 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0xffffffff);
12231 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12232 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12233 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12234 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
12235 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x80000000);
12236 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12237 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12238 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12239 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
12241 refcount = IDirect3DDevice9_Release(device);
12242 ok(!refcount, "Device has %u references left.\n", refcount);
12245 IDirect3D9_Release(d3d);
12246 DestroyWindow(window);
12249 static void test_swapchain_multisample_reset(void)
12251 IDirect3DSwapChain9 *swapchain;
12252 D3DPRESENT_PARAMETERS d3dpp;
12253 IDirect3DDevice9 *device;
12254 DWORD quality_levels;
12255 IDirect3D9 *d3d;
12256 ULONG refcount;
12257 HWND window;
12258 HRESULT hr;
12260 window = create_window();
12261 ok(!!window, "Failed to create a window.\n");
12262 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12263 ok(!!d3d, "Failed to create a D3D object.\n");
12265 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12266 D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels) == D3DERR_NOTAVAILABLE)
12268 skip("Multisampling not supported for D3DFMT_A8R8G8B8.\n");
12269 IDirect3D9_Release(d3d);
12270 DestroyWindow(window);
12271 return;
12274 if (!(device = create_device(d3d, window, NULL)))
12276 skip("Failed to create a 3D device.\n");
12277 IDirect3D9_Release(d3d);
12278 DestroyWindow(window);
12279 return;
12282 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
12283 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12285 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
12286 ok(hr == D3D_OK, "Failed to get the implicit swapchain, hr %#x.\n", hr);
12287 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
12288 ok(hr == D3D_OK, "Failed to get present parameters, hr %#x.\n", hr);
12289 ok(d3dpp.MultiSampleType == D3DMULTISAMPLE_NONE,
12290 "Got unexpected multisample type %#x.\n", d3dpp.MultiSampleType);
12291 IDirect3DSwapChain9_Release(swapchain);
12293 d3dpp.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
12294 d3dpp.MultiSampleQuality = quality_levels - 1;
12295 hr = IDirect3DDevice9_Reset(device, &d3dpp);
12296 ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
12298 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
12299 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12301 refcount = IDirect3DDevice9_Release(device);
12302 ok(!refcount, "Device has %u references left.\n", refcount);
12303 IDirect3D9_Release(d3d);
12304 DestroyWindow(window);
12307 static void test_stretch_rect(void)
12309 IDirect3DTexture9 *src_texture, *dst_texture;
12310 IDirect3DSurface9 *src_surface, *dst_surface;
12311 IDirect3DSurface9 *src_rt, *dst_rt;
12312 D3DFORMAT src_format, dst_format;
12313 IDirect3DSurface9 *src, *dst;
12314 D3DPOOL src_pool, dst_pool;
12315 BOOL can_stretch_textures;
12316 IDirect3DDevice9 *device;
12317 HRESULT expected_hr;
12318 unsigned int i, j;
12319 IDirect3D9 *d3d;
12320 ULONG refcount;
12321 D3DCAPS9 caps;
12322 HWND window;
12323 HRESULT hr;
12325 static const D3DFORMAT formats[] =
12327 D3DFMT_A8R8G8B8,
12328 D3DFMT_X8R8G8B8,
12329 D3DFMT_R5G6B5,
12332 window = create_window();
12333 ok(!!window, "Failed to create a window.\n");
12334 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12335 ok(!!d3d, "Failed to create a D3D object.\n");
12337 if (!(device = create_device(d3d, window, NULL)))
12339 skip("Failed to create a 3D device.\n");
12340 IDirect3D9_Release(d3d);
12341 DestroyWindow(window);
12342 return;
12345 memset(&caps, 0, sizeof(caps));
12346 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12347 ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr);
12348 can_stretch_textures = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES;
12350 for (i = 0; i < ARRAY_SIZE(formats); ++i)
12352 src_format = formats[i];
12353 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12354 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, src_format))
12355 || FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12356 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, src_format)))
12358 skip("Format %#x not supported.\n", src_format);
12359 continue;
12362 for (j = 0; j < ARRAY_SIZE(formats); ++j)
12364 dst_format = formats[j];
12365 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12366 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, dst_format))
12367 || FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12368 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, dst_format)))
12370 skip("Format %#x not supported.\n", dst_format);
12371 continue;
12374 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, src_format,
12375 D3DMULTISAMPLE_NONE, 0, FALSE, &src_rt, NULL);
12376 ok(hr == D3D_OK, "Failed to create render target, hr %#x.\n", hr);
12377 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, dst_format,
12378 D3DMULTISAMPLE_NONE, 0, FALSE, &dst_rt, NULL);
12379 ok(hr == D3D_OK, "Failed to create render target, hr %#x.\n", hr);
12381 hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst_rt, NULL, D3DTEXF_NONE);
12382 ok(hr == D3D_OK, "Got hr %#x (formats %#x/%#x).\n", hr, src_format, dst_format);
12384 for (src_pool = D3DPOOL_DEFAULT; src_pool <= D3DPOOL_SCRATCH; ++src_pool)
12386 for (dst_pool = D3DPOOL_DEFAULT; dst_pool <= D3DPOOL_SCRATCH; ++dst_pool)
12388 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0,
12389 src_format, src_pool, &src_texture, NULL);
12390 ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr);
12391 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0,
12392 dst_format, dst_pool, &dst_texture, NULL);
12393 ok(hr == D3D_OK, "Failed to create texture, hr %#x.\n", hr);
12394 hr = IDirect3DTexture9_GetSurfaceLevel(src_texture, 0, &src);
12395 ok(hr == D3D_OK, "Failed to get surface, hr %#x.\n", hr);
12396 hr = IDirect3DTexture9_GetSurfaceLevel(dst_texture, 0, &dst);
12397 ok(hr == D3D_OK, "Failed to get surface, hr %#x.\n", hr);
12398 IDirect3DTexture9_Release(src_texture);
12399 IDirect3DTexture9_Release(dst_texture);
12401 hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_NONE);
12402 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n",
12403 hr, src_format, dst_format, src_pool, dst_pool);
12405 /* render target <-> texture */
12406 if (src_pool == D3DPOOL_DEFAULT && can_stretch_textures)
12407 expected_hr = D3D_OK;
12408 else
12409 expected_hr = D3DERR_INVALIDCALL;
12410 hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_rt, NULL, D3DTEXF_NONE);
12411 ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n",
12412 hr, expected_hr, src_format, dst_format, src_pool);
12413 hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst, NULL, D3DTEXF_NONE);
12414 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n",
12415 hr, src_format, dst_format, dst_pool);
12417 if (src_pool == D3DPOOL_MANAGED || dst_pool == D3DPOOL_MANAGED)
12419 IDirect3DSurface9_Release(src);
12420 IDirect3DSurface9_Release(dst);
12421 continue;
12424 if (src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT)
12425 expected_hr = D3D_OK;
12426 else
12427 expected_hr = D3DERR_INVALIDCALL;
12429 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
12430 src_format, src_pool, &src_surface, NULL);
12431 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12432 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
12433 dst_format, dst_pool, &dst_surface, NULL);
12434 ok(hr == D3D_OK, "Failed to create surface, hr %#x.\n", hr);
12436 hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_surface, NULL, D3DTEXF_NONE);
12437 ok(hr == expected_hr, "Got hr %#x, expected %#x (formats %#x/%#x, pools %#x/%#x).\n",
12438 hr, expected_hr, src_format, dst_format, src_pool, dst_pool);
12440 /* offscreen plain <-> texture */
12441 hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst_surface, NULL, D3DTEXF_NONE);
12442 todo_wine_if(src_pool == D3DPOOL_DEFAULT && dst_pool == D3DPOOL_DEFAULT)
12443 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n",
12444 hr, src_format, dst_format, src_pool, dst_pool);
12445 hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst, NULL, D3DTEXF_NONE);
12446 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pools %#x/%#x).\n",
12447 hr, src_format, dst_format, src_pool, dst_pool);
12449 /* offscreen plain <-> render target */
12450 expected_hr = src_pool == D3DPOOL_DEFAULT ? D3D_OK : D3DERR_INVALIDCALL;
12451 hr = IDirect3DDevice9_StretchRect(device, src_surface, NULL, dst_rt, NULL, D3DTEXF_NONE);
12452 ok(hr == expected_hr, "Got hr %#x, expected hr %#x (formats %#x/%#x, pool %#x).\n",
12453 hr, expected_hr, src_format, dst_format, src_pool);
12454 hr = IDirect3DDevice9_StretchRect(device, src_rt, NULL, dst_surface, NULL, D3DTEXF_NONE);
12455 todo_wine_if(dst_pool == D3DPOOL_DEFAULT)
12456 ok(hr == D3DERR_INVALIDCALL, "Got hr %#x (formats %#x/%#x, pool %#x).\n",
12457 hr, src_format, dst_format, dst_pool);
12459 IDirect3DSurface9_Release(src_surface);
12460 IDirect3DSurface9_Release(dst_surface);
12462 IDirect3DSurface9_Release(src);
12463 IDirect3DSurface9_Release(dst);
12467 IDirect3DSurface9_Release(src_rt);
12468 IDirect3DSurface9_Release(dst_rt);
12472 refcount = IDirect3DDevice9_Release(device);
12473 ok(!refcount, "Device has %u references left.\n", refcount);
12474 IDirect3D9_Release(d3d);
12475 DestroyWindow(window);
12478 static void test_device_caps(void)
12480 IDirect3DDevice9 *device;
12481 IDirect3D9 *d3d;
12482 ULONG refcount;
12483 D3DCAPS9 caps;
12484 HWND window;
12485 HRESULT hr;
12487 window = create_window();
12488 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12489 ok(!!d3d, "Failed to create a D3D object.\n");
12491 if (!(device = create_device(d3d, window, NULL)))
12493 skip("Failed to create a D3D device.\n");
12494 IDirect3D9_Release(d3d);
12495 DestroyWindow(window);
12496 return;
12499 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12500 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
12502 ok(!(caps.Caps & ~D3DCAPS_READ_SCANLINE), "Caps field has unexpected flags %#x.\n", caps.Caps);
12503 ok(!(caps.Caps2 & ~(D3DCAPS2_NO2DDURING3DSCENE | D3DCAPS2_FULLSCREENGAMMA
12504 | D3DCAPS2_CANRENDERWINDOWED | D3DCAPS2_CANCALIBRATEGAMMA | D3DCAPS2_RESERVED
12505 | D3DCAPS2_CANMANAGERESOURCE | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_CANAUTOGENMIPMAP
12506 | D3DCAPS2_CANSHARERESOURCE)),
12507 "Caps2 field has unexpected flags %#x.\n", caps.Caps2);
12508 /* AMD doesn't filter all the ddraw / d3d9 caps. Consider that behavior
12509 * broken. */
12510 ok(!(caps.Caps3 & ~(D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD
12511 | D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION | D3DCAPS3_COPY_TO_VIDMEM
12512 | D3DCAPS3_COPY_TO_SYSTEMMEM | D3DCAPS3_DXVAHD | D3DCAPS3_DXVAHD_LIMITED
12513 | D3DCAPS3_RESERVED)),
12514 "Caps3 field has unexpected flags %#x.\n", caps.Caps3);
12515 ok(!(caps.PrimitiveMiscCaps & ~(D3DPMISCCAPS_MASKZ | D3DPMISCCAPS_LINEPATTERNREP
12516 | D3DPMISCCAPS_CULLNONE | D3DPMISCCAPS_CULLCW | D3DPMISCCAPS_CULLCCW
12517 | D3DPMISCCAPS_COLORWRITEENABLE | D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
12518 | D3DPMISCCAPS_CLIPTLVERTS | D3DPMISCCAPS_TSSARGTEMP | D3DPMISCCAPS_BLENDOP
12519 | D3DPMISCCAPS_NULLREFERENCE | D3DPMISCCAPS_INDEPENDENTWRITEMASKS
12520 | D3DPMISCCAPS_PERSTAGECONSTANT | D3DPMISCCAPS_FOGANDSPECULARALPHA
12521 | D3DPMISCCAPS_SEPARATEALPHABLEND | D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
12522 | D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING | D3DPMISCCAPS_FOGVERTEXCLAMPED
12523 | D3DPMISCCAPS_POSTBLENDSRGBCONVERT)),
12524 "PrimitiveMiscCaps field has unexpected flags %#x.\n", caps.PrimitiveMiscCaps);
12525 ok(!(caps.RasterCaps & ~(D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_PAT | D3DPRASTERCAPS_ZTEST
12526 | D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_ANTIALIASEDGES
12527 | D3DPRASTERCAPS_MIPMAPLODBIAS | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZBUFFERLESSHSR
12528 | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_ANISOTROPY | D3DPRASTERCAPS_WBUFFER
12529 | D3DPRASTERCAPS_WFOG | D3DPRASTERCAPS_ZFOG | D3DPRASTERCAPS_COLORPERSPECTIVE
12530 | D3DPRASTERCAPS_SCISSORTEST | D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
12531 | D3DPRASTERCAPS_DEPTHBIAS | D3DPRASTERCAPS_MULTISAMPLE_TOGGLE)),
12532 "RasterCaps field has unexpected flags %#x.\n", caps.RasterCaps);
12533 /* D3DPBLENDCAPS_SRCCOLOR2 and D3DPBLENDCAPS_INVSRCCOLOR2 are only
12534 * advertised on the reference rasterizer and WARP. */
12535 ok(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12536 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12537 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12538 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12539 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR))
12540 || broken(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12541 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12542 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12543 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12544 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR
12545 | D3DPBLENDCAPS_SRCCOLOR2 | D3DPBLENDCAPS_INVSRCCOLOR2))),
12546 "SrcBlendCaps field has unexpected flags %#x.\n", caps.SrcBlendCaps);
12547 ok(!(caps.DestBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12548 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12549 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12550 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12551 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR))
12552 || broken(!(caps.SrcBlendCaps & ~(D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR
12553 | D3DPBLENDCAPS_INVSRCCOLOR | D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA
12554 | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_DESTCOLOR
12555 | D3DPBLENDCAPS_INVDESTCOLOR | D3DPBLENDCAPS_SRCALPHASAT | D3DPBLENDCAPS_BOTHSRCALPHA
12556 | D3DPBLENDCAPS_BOTHINVSRCALPHA | D3DPBLENDCAPS_BLENDFACTOR
12557 | D3DPBLENDCAPS_SRCCOLOR2 | D3DPBLENDCAPS_INVSRCCOLOR2))),
12558 "DestBlendCaps field has unexpected flags %#x.\n", caps.DestBlendCaps);
12559 ok(!(caps.TextureCaps & ~(D3DPTEXTURECAPS_PERSPECTIVE | D3DPTEXTURECAPS_POW2
12560 | D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_SQUAREONLY
12561 | D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE | D3DPTEXTURECAPS_ALPHAPALETTE
12562 | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PROJECTED
12563 | D3DPTEXTURECAPS_CUBEMAP | D3DPTEXTURECAPS_VOLUMEMAP | D3DPTEXTURECAPS_MIPMAP
12564 | D3DPTEXTURECAPS_MIPVOLUMEMAP | D3DPTEXTURECAPS_MIPCUBEMAP
12565 | D3DPTEXTURECAPS_CUBEMAP_POW2 | D3DPTEXTURECAPS_VOLUMEMAP_POW2
12566 | D3DPTEXTURECAPS_NOPROJECTEDBUMPENV)),
12567 "TextureCaps field has unexpected flags %#x.\n", caps.TextureCaps);
12568 ok(!(caps.TextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
12569 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
12570 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
12571 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_CONVOLUTIONMONO
12572 | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
12573 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
12574 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
12575 "TextureFilterCaps field has unexpected flags %#x.\n", caps.TextureFilterCaps);
12576 ok(!(caps.CubeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
12577 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
12578 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
12579 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
12580 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
12581 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
12582 "CubeTextureFilterCaps field has unexpected flags %#x.\n", caps.CubeTextureFilterCaps);
12583 ok(!(caps.VolumeTextureFilterCaps & ~(D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MINFLINEAR
12584 | D3DPTFILTERCAPS_MINFANISOTROPIC | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD
12585 | D3DPTFILTERCAPS_MINFGAUSSIANQUAD | D3DPTFILTERCAPS_MIPFPOINT
12586 | D3DPTFILTERCAPS_MIPFLINEAR | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MAGFLINEAR
12587 | D3DPTFILTERCAPS_MAGFANISOTROPIC | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD
12588 | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD)),
12589 "VolumeTextureFilterCaps field has unexpected flags %#x.\n", caps.VolumeTextureFilterCaps);
12590 ok(!(caps.LineCaps & ~(D3DLINECAPS_TEXTURE | D3DLINECAPS_ZTEST | D3DLINECAPS_BLEND
12591 | D3DLINECAPS_ALPHACMP | D3DLINECAPS_FOG | D3DLINECAPS_ANTIALIAS)),
12592 "LineCaps field has unexpected flags %#x.\n", caps.LineCaps);
12593 ok(!(caps.StencilCaps & ~(D3DSTENCILCAPS_KEEP | D3DSTENCILCAPS_ZERO | D3DSTENCILCAPS_REPLACE
12594 | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INVERT
12595 | D3DSTENCILCAPS_INCR | D3DSTENCILCAPS_DECR | D3DSTENCILCAPS_TWOSIDED)),
12596 "StencilCaps field has unexpected flags %#x.\n", caps.StencilCaps);
12597 ok(!(caps.VertexProcessingCaps & ~(D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7
12598 | D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER
12599 | D3DVTXPCAPS_TWEENING | D3DVTXPCAPS_TEXGEN_SPHEREMAP
12600 | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER)),
12601 "VertexProcessingCaps field has unexpected flags %#x.\n", caps.VertexProcessingCaps);
12602 /* Both Nvidia and AMD give 10 here. */
12603 ok(caps.MaxActiveLights <= 10,
12604 "MaxActiveLights field has unexpected value %u.\n", caps.MaxActiveLights);
12605 /* AMD gives 6, Nvidia returns 8. */
12606 ok(caps.MaxUserClipPlanes <= 8,
12607 "MaxUserClipPlanes field has unexpected value %u.\n", caps.MaxUserClipPlanes);
12609 refcount = IDirect3DDevice9_Release(device);
12610 ok(!refcount, "Device has %u references left.\n", refcount);
12611 IDirect3D9_Release(d3d);
12612 DestroyWindow(window);
12615 static void test_resource_access(void)
12617 IDirect3DSurface9 *backbuffer, *depth_stencil;
12618 D3DFORMAT colour_format, depth_format, format;
12619 BOOL depth_2d, depth_cube, depth_plain;
12620 struct device_desc device_desc;
12621 D3DSURFACE_DESC surface_desc;
12622 IDirect3DDevice9 *device;
12623 unsigned int i, j;
12624 IDirect3D9 *d3d;
12625 ULONG refcount;
12626 HWND window;
12627 HRESULT hr;
12629 enum surface_type
12631 SURFACE_2D,
12632 SURFACE_CUBE,
12633 SURFACE_RT,
12634 SURFACE_DS,
12635 SURFACE_PLAIN,
12638 enum resource_format
12640 FORMAT_COLOUR,
12641 FORMAT_ATI2,
12642 FORMAT_DEPTH,
12645 static const struct
12647 D3DPOOL pool;
12648 enum resource_format format;
12649 DWORD usage;
12650 BOOL valid;
12652 tests[] =
12654 /* 0 */
12655 {D3DPOOL_DEFAULT, FORMAT_COLOUR, 0, TRUE},
12656 {D3DPOOL_DEFAULT, FORMAT_ATI2, 0, TRUE},
12657 {D3DPOOL_DEFAULT, FORMAT_DEPTH, 0, TRUE},
12658 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, TRUE},
12659 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
12660 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
12661 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, TRUE},
12662 /* 7 */
12663 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC, TRUE},
12664 {D3DPOOL_DEFAULT, FORMAT_ATI2, D3DUSAGE_DYNAMIC, TRUE},
12665 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC, TRUE},
12666 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
12667 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET, FALSE},
12668 {D3DPOOL_DEFAULT, FORMAT_COLOUR, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
12669 {D3DPOOL_DEFAULT, FORMAT_DEPTH, D3DUSAGE_DYNAMIC | D3DUSAGE_DEPTHSTENCIL, FALSE},
12670 /* 14 */
12671 {D3DPOOL_MANAGED, FORMAT_COLOUR, 0, TRUE},
12672 {D3DPOOL_MANAGED, FORMAT_ATI2, 0, TRUE},
12673 {D3DPOOL_MANAGED, FORMAT_DEPTH, 0, FALSE},
12674 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
12675 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
12676 {D3DPOOL_MANAGED, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
12677 {D3DPOOL_MANAGED, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
12678 /* 21 */
12679 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, 0, TRUE},
12680 {D3DPOOL_SYSTEMMEM, FORMAT_ATI2, 0, TRUE},
12681 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, 0, FALSE},
12682 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
12683 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
12684 {D3DPOOL_SYSTEMMEM, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
12685 {D3DPOOL_SYSTEMMEM, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
12686 /* 28 */
12687 {D3DPOOL_SCRATCH, FORMAT_COLOUR, 0, TRUE},
12688 {D3DPOOL_SCRATCH, FORMAT_ATI2, 0, TRUE},
12689 {D3DPOOL_SCRATCH, FORMAT_DEPTH, 0, FALSE},
12690 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_RENDERTARGET, FALSE},
12691 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_RENDERTARGET, FALSE},
12692 {D3DPOOL_SCRATCH, FORMAT_COLOUR, D3DUSAGE_DEPTHSTENCIL, FALSE},
12693 {D3DPOOL_SCRATCH, FORMAT_DEPTH, D3DUSAGE_DEPTHSTENCIL, FALSE},
12695 static const struct
12697 const char *name;
12698 enum surface_type type;
12700 surface_types[] =
12702 {"2D", SURFACE_2D},
12703 {"CUBE", SURFACE_CUBE},
12704 {"RT", SURFACE_RT},
12705 {"DS", SURFACE_DS},
12706 {"PLAIN", SURFACE_PLAIN},
12709 window = create_window();
12710 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12711 ok(!!d3d, "Failed to create a D3D object.\n");
12713 device_desc.device_window = window;
12714 device_desc.width = 16;
12715 device_desc.height = 16;
12716 device_desc.flags = 0;
12717 if (!(device = create_device(d3d, window, &device_desc)))
12719 skip("Failed to create a D3D device.\n");
12720 IDirect3D9_Release(d3d);
12721 DestroyWindow(window);
12722 return;
12725 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
12726 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12727 hr = IDirect3DSurface9_GetDesc(backbuffer, &surface_desc);
12728 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12729 colour_format = surface_desc.Format;
12731 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &depth_stencil);
12732 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12733 hr = IDirect3DSurface9_GetDesc(depth_stencil, &surface_desc);
12734 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12735 depth_format = surface_desc.Format;
12737 depth_2d = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12738 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, depth_format));
12739 depth_cube = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12740 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, depth_format));
12741 depth_plain = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12742 D3DFMT_X8R8G8B8, 0, D3DRTYPE_SURFACE, depth_format));
12744 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
12745 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
12747 for (i = 0; i < ARRAY_SIZE(surface_types); ++i)
12749 for (j = 0; j < ARRAY_SIZE(tests); ++j)
12751 IDirect3DCubeTexture9 *texture_cube;
12752 IDirect3DBaseTexture9 *texture;
12753 IDirect3DTexture9 *texture_2d;
12754 IDirect3DSurface9 *surface;
12755 HRESULT expected_hr;
12756 D3DLOCKED_RECT lr;
12758 if (tests[j].format == FORMAT_ATI2)
12759 format = MAKEFOURCC('A','T','I','2');
12760 else if (tests[j].format == FORMAT_DEPTH)
12761 format = depth_format;
12762 else
12763 format = colour_format;
12765 if (tests[j].format == FORMAT_ATI2 && FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT,
12766 D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, format)))
12768 skip("ATI2N texture not supported.\n");
12769 continue;
12772 switch (surface_types[i].type)
12774 case SURFACE_2D:
12775 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1,
12776 tests[j].usage, format, tests[j].pool, &texture_2d, NULL);
12777 todo_wine_if(j == 10 || j == 13 || j == 16 || j == 23 || j == 30)
12778 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_2d)
12779 ? D3D_OK : D3DERR_INVALIDCALL),
12780 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12781 if (FAILED(hr))
12782 continue;
12784 hr = IDirect3DTexture9_GetSurfaceLevel(texture_2d, 0, &surface);
12785 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12786 IDirect3DTexture9_Release(texture_2d);
12787 break;
12789 case SURFACE_CUBE:
12790 hr = IDirect3DDevice9_CreateCubeTexture(device, 16, 1,
12791 tests[j].usage, format, tests[j].pool, &texture_cube, NULL);
12792 todo_wine_if(j == 10 || j == 13 || j == 16 || j == 23 || j == 30)
12793 ok(hr == (tests[j].valid && (tests[j].format != FORMAT_DEPTH || depth_cube)
12794 ? D3D_OK : D3DERR_INVALIDCALL),
12795 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12796 if (FAILED(hr))
12797 continue;
12799 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture_cube,
12800 D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
12801 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12802 IDirect3DCubeTexture9_Release(texture_cube);
12803 break;
12805 case SURFACE_RT:
12806 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, format,
12807 D3DMULTISAMPLE_NONE, 0, tests[j].usage & D3DUSAGE_DYNAMIC, &surface, NULL);
12808 ok(hr == (tests[j].format == FORMAT_COLOUR ? D3D_OK : D3DERR_INVALIDCALL),
12809 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12810 if (FAILED(hr))
12811 continue;
12812 break;
12814 case SURFACE_DS:
12815 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 16, 16, format,
12816 D3DMULTISAMPLE_NONE, 0, tests[j].usage & D3DUSAGE_DYNAMIC, &surface, NULL);
12817 ok(hr == (tests[j].format == FORMAT_DEPTH ? D3D_OK : D3DERR_INVALIDCALL),
12818 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12819 if (FAILED(hr))
12820 continue;
12821 break;
12823 case SURFACE_PLAIN:
12824 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device,
12825 16, 16, format, tests[j].pool, &surface, NULL);
12826 todo_wine_if(tests[j].format == FORMAT_ATI2 && tests[j].pool != D3DPOOL_MANAGED
12827 && tests[j].pool != D3DPOOL_SCRATCH)
12828 ok(hr == (tests[j].pool != D3DPOOL_MANAGED && (tests[j].format != FORMAT_DEPTH || depth_plain)
12829 && (tests[j].format != FORMAT_ATI2 || tests[j].pool == D3DPOOL_SCRATCH)
12830 ? D3D_OK : D3DERR_INVALIDCALL),
12831 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12832 if (FAILED(hr))
12833 continue;
12834 break;
12836 default:
12837 ok(0, "Invalid surface type %#x.\n", surface_types[i].type);
12838 continue;
12841 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
12842 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12843 if (surface_types[i].type == SURFACE_RT)
12845 ok(surface_desc.Usage == D3DUSAGE_RENDERTARGET, "Test %s %u: Got unexpected usage %#x.\n",
12846 surface_types[i].name, j, surface_desc.Usage);
12847 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
12848 surface_types[i].name, j, surface_desc.Pool);
12850 else if (surface_types[i].type == SURFACE_DS)
12852 ok(surface_desc.Usage == D3DUSAGE_DEPTHSTENCIL, "Test %s %u: Got unexpected usage %#x.\n",
12853 surface_types[i].name, j, surface_desc.Usage);
12854 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %s %u: Got unexpected pool %#x.\n",
12855 surface_types[i].name, j, surface_desc.Pool);
12857 else if (surface_types[i].type == SURFACE_PLAIN)
12859 ok(!surface_desc.Usage, "Test %s %u: Got unexpected usage %#x.\n",
12860 surface_types[i].name, j, surface_desc.Usage);
12861 ok(surface_desc.Pool == tests[j].pool, "Test %s %u: Got unexpected pool %#x.\n",
12862 surface_types[i].name, j, surface_desc.Pool);
12864 else
12866 ok(surface_desc.Usage == tests[j].usage, "Test %s %u: Got unexpected usage %#x.\n",
12867 surface_types[i].name, j, surface_desc.Usage);
12868 ok(surface_desc.Pool == tests[j].pool, "Test %s %u: Got unexpected pool %#x.\n",
12869 surface_types[i].name, j, surface_desc.Pool);
12872 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
12873 if (surface_desc.Pool != D3DPOOL_DEFAULT || surface_desc.Usage & D3DUSAGE_DYNAMIC
12874 || (surface_types[i].type == SURFACE_RT && tests[j].usage & D3DUSAGE_DYNAMIC)
12875 || surface_types[i].type == SURFACE_PLAIN
12876 || tests[j].format == FORMAT_ATI2)
12877 expected_hr = D3D_OK;
12878 else
12879 expected_hr = D3DERR_INVALIDCALL;
12880 todo_wine_if(expected_hr != D3D_OK)
12881 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12882 hr = IDirect3DSurface9_UnlockRect(surface);
12883 todo_wine_if(expected_hr != D3D_OK)
12884 ok(hr == expected_hr, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12886 if (SUCCEEDED(IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&texture)))
12888 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
12889 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12890 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12891 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12892 IDirect3DBaseTexture9_Release(texture);
12895 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
12896 ok(hr == (surface_desc.Usage & D3DUSAGE_RENDERTARGET ? D3D_OK : D3DERR_INVALIDCALL),
12897 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12898 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
12899 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12901 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
12902 ok(hr == (surface_desc.Usage & D3DUSAGE_DEPTHSTENCIL ? D3D_OK : D3DERR_INVALIDCALL),
12903 "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12904 hr = IDirect3DDevice9_SetDepthStencilSurface(device, depth_stencil);
12905 ok(hr == D3D_OK, "Test %s %u: Got unexpected hr %#x.\n", surface_types[i].name, j, hr);
12907 IDirect3DSurface9_Release(surface);
12911 for (i = 0; i < ARRAY_SIZE(tests); ++i)
12913 IDirect3DVolumeTexture9 *texture;
12914 D3DVOLUME_DESC volume_desc;
12915 IDirect3DVolume9 *volume;
12916 HRESULT expected_hr;
12917 D3DLOCKED_BOX lb;
12919 if (tests[j].format == FORMAT_DEPTH)
12920 continue;
12922 if (tests[j].format == FORMAT_ATI2)
12923 format = MAKEFOURCC('A','T','I','2');
12924 else
12925 format = colour_format;
12927 hr = IDirect3DDevice9_CreateVolumeTexture(device, 16, 16, 1, 1,
12928 tests[i].usage, format, tests[i].pool, &texture, NULL);
12929 todo_wine_if(tests[i].usage & D3DUSAGE_RENDERTARGET && tests[i].pool == D3DPOOL_DEFAULT)
12930 ok(hr == (!(tests[i].usage & ~D3DUSAGE_DYNAMIC) ? D3D_OK : D3DERR_INVALIDCALL),
12931 "Test %u: Got unexpected hr %#x.\n", i, hr);
12932 if (FAILED(hr))
12933 continue;
12935 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
12936 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12938 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
12939 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12940 ok(volume_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#x.\n", i, volume_desc.Usage);
12941 ok(volume_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, volume_desc.Pool);
12943 hr = IDirect3DVolume9_LockBox(volume, &lb, NULL, 0);
12944 if (volume_desc.Pool != D3DPOOL_DEFAULT || volume_desc.Usage & D3DUSAGE_DYNAMIC)
12945 expected_hr = D3D_OK;
12946 else
12947 expected_hr = D3DERR_INVALIDCALL;
12948 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
12949 hr = IDirect3DVolume9_UnlockBox(volume);
12950 ok(hr == expected_hr, "Test %u: Got unexpected hr %#x.\n", i, hr);
12952 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
12953 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12954 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12955 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12957 IDirect3DVolume9_Release(volume);
12958 IDirect3DVolumeTexture9_Release(texture);
12961 for (i = 0; i < ARRAY_SIZE(tests); ++i)
12963 D3DINDEXBUFFER_DESC ib_desc;
12964 IDirect3DIndexBuffer9 *ib;
12965 void *data;
12967 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, tests[i].usage,
12968 tests[i].format == FORMAT_COLOUR ? D3DFMT_INDEX32 : D3DFMT_INDEX16, tests[i].pool, &ib, NULL);
12969 todo_wine_if(tests[i].pool == D3DPOOL_SCRATCH || tests[i].usage & ~D3DUSAGE_DYNAMIC)
12970 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || (tests[i].usage & ~D3DUSAGE_DYNAMIC)
12971 ? D3DERR_INVALIDCALL : D3D_OK), "Test %u: Got unexpected hr %#x.\n", i, hr);
12972 if (FAILED(hr))
12973 continue;
12975 hr = IDirect3DIndexBuffer9_GetDesc(ib, &ib_desc);
12976 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12977 todo_wine_if(tests[i].usage & ~D3DUSAGE_DYNAMIC)
12978 ok(ib_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#x.\n", i, ib_desc.Usage);
12979 ok(ib_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, ib_desc.Pool);
12981 hr = IDirect3DIndexBuffer9_Lock(ib, 0, 0, &data, 0);
12982 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12983 hr = IDirect3DIndexBuffer9_Unlock(ib);
12984 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12986 hr = IDirect3DDevice9_SetIndices(device, ib);
12987 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12988 hr = IDirect3DDevice9_SetIndices(device, NULL);
12989 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
12991 IDirect3DIndexBuffer9_Release(ib);
12994 for (i = 0; i < ARRAY_SIZE(tests); ++i)
12996 D3DVERTEXBUFFER_DESC vb_desc;
12997 IDirect3DVertexBuffer9 *vb;
12998 void *data;
13000 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, tests[i].usage,
13001 tests[i].format == FORMAT_COLOUR ? 0 : D3DFVF_XYZRHW, tests[i].pool, &vb, NULL);
13002 todo_wine_if(tests[i].pool != D3DPOOL_SCRATCH && tests[i].usage & ~D3DUSAGE_DYNAMIC)
13003 ok(hr == (tests[i].pool == D3DPOOL_SCRATCH || (tests[i].usage & ~D3DUSAGE_DYNAMIC)
13004 ? D3DERR_INVALIDCALL : D3D_OK), "Test %u: Got unexpected hr %#x.\n", i, hr);
13005 if (FAILED(hr))
13006 continue;
13008 hr = IDirect3DVertexBuffer9_GetDesc(vb, &vb_desc);
13009 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
13010 todo_wine_if(tests[i].usage & ~D3DUSAGE_DYNAMIC)
13011 ok(vb_desc.Usage == tests[i].usage, "Test %u: Got unexpected usage %#x.\n", i, vb_desc.Usage);
13012 ok(vb_desc.Pool == tests[i].pool, "Test %u: Got unexpected pool %#x.\n", i, vb_desc.Pool);
13014 hr = IDirect3DVertexBuffer9_Lock(vb, 0, 0, &data, 0);
13015 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
13016 hr = IDirect3DVertexBuffer9_Unlock(vb);
13017 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
13019 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 16);
13020 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
13021 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
13022 ok(hr == D3D_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
13024 IDirect3DVertexBuffer9_Release(vb);
13027 IDirect3DSurface9_Release(depth_stencil);
13028 IDirect3DSurface9_Release(backbuffer);
13029 refcount = IDirect3DDevice9_Release(device);
13030 ok(!refcount, "Device has %u references left.\n", refcount);
13031 IDirect3D9_Release(d3d);
13032 DestroyWindow(window);
13035 START_TEST(device)
13037 WNDCLASSA wc = {0};
13038 IDirect3D9 *d3d9;
13039 DEVMODEW current_mode;
13041 memset(&current_mode, 0, sizeof(current_mode));
13042 current_mode.dmSize = sizeof(current_mode);
13043 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
13044 registry_mode.dmSize = sizeof(registry_mode);
13045 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
13046 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
13047 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
13049 skip("Current mode does not match registry mode, skipping test.\n");
13050 return;
13053 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
13055 skip("could not create D3D9 object\n");
13056 return;
13058 IDirect3D9_Release(d3d9);
13060 wc.lpfnWndProc = DefWindowProcA;
13061 wc.lpszClassName = "d3d9_test_wc";
13062 RegisterClassA(&wc);
13064 test_get_set_vertex_declaration();
13065 test_get_declaration();
13066 test_fvf_decl_conversion();
13067 test_fvf_decl_management();
13068 test_vertex_declaration_alignment();
13069 test_unused_declaration_type();
13070 test_fpu_setup();
13071 test_multi_device();
13072 test_display_formats();
13073 test_display_modes();
13074 test_swapchain();
13075 test_refcount();
13076 test_mipmap_levels();
13077 test_checkdevicemultisampletype();
13078 test_invalid_multisample();
13079 test_cursor();
13080 test_cursor_pos();
13081 test_reset_fullscreen();
13082 test_reset();
13083 test_scene();
13084 test_limits();
13085 test_depthstenciltest();
13086 test_get_rt();
13087 test_draw_primitive();
13088 test_null_stream();
13089 test_lights();
13090 test_set_stream_source();
13091 test_scissor_size();
13092 test_wndproc();
13093 test_wndproc_windowed();
13094 test_window_style();
13095 test_mode_change();
13096 test_device_window_reset();
13097 test_reset_resources();
13098 test_set_rt_vp_scissor();
13099 test_volume_get_container();
13100 test_volume_resource();
13101 test_vb_lock_flags();
13102 test_vertex_buffer_alignment();
13103 test_query_support();
13104 test_occlusion_query();
13105 test_timestamp_query();
13106 test_get_set_vertex_shader();
13107 test_vertex_shader_constant();
13108 test_get_set_pixel_shader();
13109 test_pixel_shader_constant();
13110 test_unsupported_shaders();
13111 test_texture_stage_states();
13112 test_cube_textures();
13113 test_mipmap_gen();
13114 test_filter();
13115 test_get_set_texture();
13116 test_lod();
13117 test_surface_get_container();
13118 test_surface_alignment();
13119 test_lockrect_offset();
13120 test_lockrect_invalid();
13121 test_private_data();
13122 test_getdc();
13123 test_surface_dimensions();
13124 test_surface_format_null();
13125 test_surface_double_unlock();
13126 test_surface_blocks();
13127 test_set_palette();
13128 test_swvp_buffer();
13129 test_managed_buffer();
13130 test_npot_textures();
13131 test_vidmem_accounting();
13132 test_volume_locking();
13133 test_update_volumetexture();
13134 test_create_rt_ds_fail();
13135 test_volume_blocks();
13136 test_lockbox_invalid();
13137 test_shared_handle();
13138 test_pixel_format();
13139 test_begin_end_state_block();
13140 test_shader_constant_apply();
13141 test_vdecl_apply();
13142 test_resource_type();
13143 test_mipmap_lock();
13144 test_writeonly_resource();
13145 test_lost_device();
13146 test_resource_priority();
13147 test_swapchain_parameters();
13148 test_check_device_format();
13149 test_miptree_layout();
13150 test_get_render_target_data();
13151 test_render_target_device_mismatch();
13152 test_format_unknown();
13153 test_destroyed_window();
13154 test_lockable_backbuffer();
13155 test_clip_planes_limits();
13156 test_swapchain_multisample_reset();
13157 test_stretch_rect();
13158 test_device_caps();
13159 test_resource_access();
13161 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));