d3d9/tests: Test D3DBACKBUFFER_TYPE.
[wine.git] / dlls / d3d9 / tests / device.c
blob3bf0ff2137e870d37565fa086edc85012a1f3c1d
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 COBJMACROS
26 #include <d3d9.h>
27 #include "wine/test.h"
29 struct vec3
31 float x, y, z;
34 #define CREATE_DEVICE_FULLSCREEN 0x01
35 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
36 #define CREATE_DEVICE_FPU_PRESERVE 0x04
37 #define CREATE_DEVICE_SWVP_ONLY 0x08
39 struct device_desc
41 HWND device_window;
42 unsigned int width;
43 unsigned int height;
44 DWORD flags;
47 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
48 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
50 static DEVMODEW registry_mode;
52 static const DWORD simple_vs[] =
54 0xfffe0101, /* vs_1_1 */
55 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
56 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
57 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
58 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
59 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
60 0x0000ffff, /* end */
63 static const DWORD simple_ps[] =
65 0xffff0101, /* ps_1_1 */
66 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
67 0x00000042, 0xb00f0000, /* tex t0 */
68 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
69 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
70 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
71 0x0000ffff, /* end */
74 static int get_refcount(IUnknown *object)
76 IUnknown_AddRef( object );
77 return IUnknown_Release( object );
80 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
82 unsigned int element_count, i;
83 D3DVERTEXELEMENT9 *elements;
84 BOOL equal = TRUE;
85 HRESULT hr;
87 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
88 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
89 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
90 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
91 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
93 for (i = 0; i < element_count; ++i)
95 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
97 equal = FALSE;
98 break;
102 if (!equal)
104 for (i = 0; i < element_count; ++i)
106 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
107 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
108 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
112 HeapFree(GetProcessHeap(), 0, elements);
113 return equal;
116 /* try to make sure pending X events have been processed before continuing */
117 static void flush_events(void)
119 MSG msg;
120 int diff = 200;
121 int min_timeout = 100;
122 DWORD time = GetTickCount() + diff;
124 while (diff > 0)
126 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
127 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
128 diff = time - GetTickCount();
132 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
134 D3DPRESENT_PARAMETERS present_parameters = {0};
135 IDirect3DDevice9 *device;
136 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
138 present_parameters.BackBufferWidth = 640;
139 present_parameters.BackBufferHeight = 480;
140 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
141 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
142 present_parameters.hDeviceWindow = focus_window;
143 present_parameters.Windowed = TRUE;
144 present_parameters.EnableAutoDepthStencil = TRUE;
145 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
147 if (desc)
149 present_parameters.BackBufferWidth = desc->width;
150 present_parameters.BackBufferHeight = desc->height;
151 present_parameters.hDeviceWindow = desc->device_window;
152 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
153 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
154 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
155 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
156 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
157 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
158 behavior_flags |= D3DCREATE_FPU_PRESERVE;
161 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
162 behavior_flags, &present_parameters, &device)))
163 return device;
165 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
166 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
167 behavior_flags, &present_parameters, &device)))
168 return device;
170 if (desc && desc->flags & CREATE_DEVICE_SWVP_ONLY)
171 return NULL;
172 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
174 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
175 behavior_flags, &present_parameters, &device)))
176 return device;
178 return NULL;
181 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
183 D3DPRESENT_PARAMETERS present_parameters = {0};
185 present_parameters.BackBufferWidth = 640;
186 present_parameters.BackBufferHeight = 480;
187 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
188 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
189 present_parameters.hDeviceWindow = NULL;
190 present_parameters.Windowed = TRUE;
191 present_parameters.EnableAutoDepthStencil = TRUE;
192 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
194 if (desc)
196 present_parameters.BackBufferWidth = desc->width;
197 present_parameters.BackBufferHeight = desc->height;
198 present_parameters.hDeviceWindow = desc->device_window;
199 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
202 return IDirect3DDevice9_Reset(device, &present_parameters);
205 #define CHECK_CALL(r,c,d,rc) \
206 if (SUCCEEDED(r)) {\
207 int tmp1 = get_refcount( (IUnknown *)d ); \
208 int rc_new = rc; \
209 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
210 } else {\
211 trace("%s failed: %08x\n", c, r); \
214 #define CHECK_RELEASE(obj,d,rc) \
215 if (obj) { \
216 int tmp1, rc_new = rc; \
217 IUnknown_Release( (IUnknown*)obj ); \
218 tmp1 = get_refcount( (IUnknown *)d ); \
219 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
222 #define CHECK_REFCOUNT(obj,rc) \
224 int rc_new = rc; \
225 int count = get_refcount( (IUnknown *)obj ); \
226 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
229 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
231 int rc_new = rc; \
232 int count = IUnknown_Release( (IUnknown *)obj ); \
233 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
236 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
238 int rc_new = rc; \
239 int count = IUnknown_AddRef( (IUnknown *)obj ); \
240 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
243 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
245 void *container_ptr = (void *)0x1337c0d3; \
246 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
247 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
248 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
249 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
252 static void test_get_set_vertex_declaration(void)
254 IDirect3DVertexDeclaration9 *declaration, *tmp;
255 ULONG refcount, expected_refcount;
256 IDirect3DDevice9 *device;
257 IDirect3D9 *d3d;
258 HWND window;
259 HRESULT hr;
261 static const D3DVERTEXELEMENT9 simple_decl[] =
263 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
264 D3DDECL_END()
267 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
268 0, 0, 640, 480, NULL, NULL, NULL, NULL);
269 d3d = Direct3DCreate9(D3D_SDK_VERSION);
270 ok(!!d3d, "Failed to create a D3D object.\n");
271 if (!(device = create_device(d3d, window, NULL)))
273 skip("Failed to create a D3D device, skipping tests.\n");
274 goto done;
277 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
278 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
280 /* SetVertexDeclaration() should not touch the declaration's refcount. */
281 expected_refcount = get_refcount((IUnknown *)declaration);
282 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
283 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
284 refcount = get_refcount((IUnknown *)declaration);
285 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
287 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
288 tmp = NULL;
289 expected_refcount = refcount + 1;
290 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
291 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
292 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
293 refcount = get_refcount((IUnknown *)declaration);
294 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
295 IDirect3DVertexDeclaration9_Release(tmp);
297 IDirect3DVertexDeclaration9_Release(declaration);
298 refcount = IDirect3DDevice9_Release(device);
299 ok(!refcount, "Device has %u references left.\n", refcount);
300 done:
301 IDirect3D9_Release(d3d);
302 DestroyWindow(window);
305 static void test_get_declaration(void)
307 unsigned int element_count, expected_element_count;
308 IDirect3DVertexDeclaration9 *declaration;
309 D3DVERTEXELEMENT9 *elements;
310 IDirect3DDevice9 *device;
311 IDirect3D9 *d3d;
312 ULONG refcount;
313 HWND window;
314 HRESULT hr;
316 static const D3DVERTEXELEMENT9 simple_decl[] =
318 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
319 D3DDECL_END()
322 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
323 0, 0, 640, 480, NULL, NULL, NULL, NULL);
324 d3d = Direct3DCreate9(D3D_SDK_VERSION);
325 ok(!!d3d, "Failed to create a D3D object.\n");
326 if (!(device = create_device(d3d, window, NULL)))
328 skip("Failed to create a D3D device, skipping tests.\n");
329 goto done;
332 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
333 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
335 /* First test only getting the number of elements. */
336 element_count = 0x1337c0de;
337 expected_element_count = sizeof(simple_decl) / sizeof(*simple_decl);
338 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
339 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
340 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
341 element_count, expected_element_count);
343 element_count = 0;
344 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
345 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
346 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
347 element_count, expected_element_count);
349 /* Also test the returned data. */
350 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
352 element_count = 0x1337c0de;
353 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
354 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
355 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
356 element_count, expected_element_count);
357 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
358 "Original and returned vertexdeclarations are not the same.\n");
360 memset(elements, 0, sizeof(simple_decl));
362 element_count = 0;
363 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
364 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
365 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
366 element_count, expected_element_count);
367 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
368 "Original and returned vertexdeclarations are not the same.\n");
370 HeapFree(GetProcessHeap(), 0, elements);
371 IDirect3DVertexDeclaration9_Release(declaration);
372 refcount = IDirect3DDevice9_Release(device);
373 ok(!refcount, "Device has %u references left.\n", refcount);
374 done:
375 IDirect3D9_Release(d3d);
376 DestroyWindow(window);
379 static void test_fvf_decl_conversion(void)
381 IDirect3DVertexDeclaration9 *default_decl;
382 IDirect3DVertexDeclaration9 *declaration;
383 IDirect3DDevice9 *device;
384 IDirect3D9 *d3d;
385 ULONG refcount;
386 unsigned int i;
387 HWND window;
388 HRESULT hr;
390 static const D3DVERTEXELEMENT9 default_elements[] =
392 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
393 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
394 D3DDECL_END()
396 /* Test conversions from vertex declaration to an FVF. For some reason
397 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
398 * forced to 0 - maybe this is configuration specific. */
399 static const struct
401 D3DVERTEXELEMENT9 elements[7];
402 DWORD fvf;
403 BOOL todo;
405 decl_to_fvf_tests[] =
407 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
408 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
409 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
410 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
411 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
412 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
413 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
414 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
415 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
416 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
417 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
418 /* No FVF mapping available. */
419 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
420 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
421 /* Try empty declaration. */
422 {{ D3DDECL_END()}, 0, FALSE},
423 /* Make sure textures of different sizes work. */
424 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
425 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
426 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
427 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
428 /* Make sure the TEXCOORD index works correctly - try several textures. */
431 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
432 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
433 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
434 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
435 D3DDECL_END(),
436 }, 0, FALSE,
438 /* Now try a combination test. */
441 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
442 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
443 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
444 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
445 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
446 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
447 D3DDECL_END(),
448 }, 0, FALSE,
451 /* Test conversions from FVF to a vertex declaration. These seem to always
452 * occur internally. A new declaration object is created if necessary. */
453 static const struct
455 DWORD fvf;
456 D3DVERTEXELEMENT9 elements[7];
458 fvf_to_decl_tests[] =
460 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
461 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
462 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
464 D3DFVF_XYZB5,
466 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
467 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
468 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
469 D3DDECL_END(),
473 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
475 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
476 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
477 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
478 D3DDECL_END(),
482 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
484 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
485 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
486 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
487 D3DDECL_END(),
491 D3DFVF_XYZB1,
493 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
494 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
495 D3DDECL_END(),
499 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
501 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
502 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
503 D3DDECL_END(),
507 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
509 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
510 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
511 D3DDECL_END(),
515 D3DFVF_XYZB2,
517 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
518 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
519 D3DDECL_END(),
523 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
525 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
526 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
527 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
528 D3DDECL_END(),
532 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
534 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
535 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
536 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
537 D3DDECL_END(),
541 D3DFVF_XYZB3,
543 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
544 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
545 D3DDECL_END(),
549 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
551 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
552 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
553 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
554 D3DDECL_END(),
558 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
560 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
561 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
562 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
563 D3DDECL_END(),
567 D3DFVF_XYZB4,
569 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
570 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
571 D3DDECL_END(),
575 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
577 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
578 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
579 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
580 D3DDECL_END(),
584 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
586 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
587 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
588 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
589 D3DDECL_END(),
592 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
593 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
594 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
595 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
596 /* Make sure textures of different sizes work. */
598 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
599 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
602 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
603 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
606 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
607 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
610 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
611 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
613 /* Make sure the TEXCOORD index works correctly - try several textures. */
615 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
616 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
618 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
619 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
620 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
621 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
622 D3DDECL_END(),
625 /* Now try a combination test. */
627 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
628 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
630 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
631 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
632 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
633 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
634 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
635 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
636 D3DDECL_END(),
641 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
642 0, 0, 640, 480, NULL, NULL, NULL, NULL);
643 d3d = Direct3DCreate9(D3D_SDK_VERSION);
644 ok(!!d3d, "Failed to create a D3D object.\n");
645 if (!(device = create_device(d3d, window, NULL)))
647 skip("Failed to create a D3D device, skipping tests.\n");
648 goto done;
651 for (i = 0; i < sizeof(decl_to_fvf_tests) / sizeof(*decl_to_fvf_tests); ++i)
653 DWORD fvf = 0xdeadbeef;
654 HRESULT hr;
656 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
657 * back to 0. */
658 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
659 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
661 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
662 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
663 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
664 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
666 /* Check the FVF. */
667 hr = IDirect3DDevice9_GetFVF(device, &fvf);
668 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
670 if (decl_to_fvf_tests[i].todo)
671 todo_wine ok(fvf == decl_to_fvf_tests[i].fvf,
672 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
673 i, fvf, decl_to_fvf_tests[i].fvf);
674 else
675 ok(fvf == decl_to_fvf_tests[i].fvf,
676 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
677 i, fvf, decl_to_fvf_tests[i].fvf);
679 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
680 IDirect3DVertexDeclaration9_Release(declaration);
683 /* Create a default declaration and FVF that does not match any of the
684 * tests. */
685 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
686 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
688 for (i = 0; i < sizeof(fvf_to_decl_tests) / sizeof(*fvf_to_decl_tests); ++i)
690 /* Set a default declaration to make sure it is changed. */
691 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
692 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
694 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
695 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
697 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
698 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
699 ok(!!declaration && declaration != default_decl,
700 "Test %u: Got unexpected declaration %p.\n", i, declaration);
701 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
702 "Test %u: Declaration does not match.\n", i);
703 IDirect3DVertexDeclaration9_Release(declaration);
706 /* Setting the FVF to 0 should result in no change to the default decl. */
707 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
708 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
709 hr = IDirect3DDevice9_SetFVF(device, 0);
710 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
711 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
712 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
713 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
714 IDirect3DVertexDeclaration9_Release(declaration);
716 IDirect3DVertexDeclaration9_Release(default_decl);
717 refcount = IDirect3DDevice9_Release(device);
718 ok(!refcount, "Device has %u references left.\n", refcount);
719 done:
720 IDirect3D9_Release(d3d);
721 DestroyWindow(window);
724 /* Check whether a declaration converted from FVF is shared.
725 * Check whether refcounts behave as expected. */
726 static void test_fvf_decl_management(void)
728 IDirect3DVertexDeclaration9 *declaration1;
729 IDirect3DVertexDeclaration9 *declaration2;
730 IDirect3DVertexDeclaration9 *declaration3;
731 IDirect3DVertexDeclaration9 *declaration4;
732 IDirect3DDevice9 *device;
733 IDirect3D9 *d3d;
734 ULONG refcount;
735 HWND window;
736 HRESULT hr;
738 static const D3DVERTEXELEMENT9 test_elements1[] =
739 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
740 static const D3DVERTEXELEMENT9 test_elements2[] =
741 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
743 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
744 0, 0, 640, 480, NULL, NULL, NULL, NULL);
745 d3d = Direct3DCreate9(D3D_SDK_VERSION);
746 ok(!!d3d, "Failed to create a D3D object.\n");
747 if (!(device = create_device(d3d, window, NULL)))
749 skip("Failed to create a D3D device, skipping tests.\n");
750 goto done;
753 /* Clear down any current vertex declaration. */
754 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
755 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
756 /* Conversion. */
757 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
758 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
759 /* Get converted decl (#1). */
760 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
761 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
762 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
763 /* Get converted decl again (#2). */
764 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
765 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
766 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
768 /* Conversion. */
769 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
770 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
771 /* Get converted decl (#3). */
772 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
773 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
774 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
775 /* The contents should correspond to the second conversion. */
776 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
777 /* Re-Check if the first decl was overwritten by the new Get(). */
778 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
780 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
781 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
782 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
783 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
784 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
786 refcount = get_refcount((IUnknown*)declaration1);
787 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
788 refcount = get_refcount((IUnknown*)declaration2);
789 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
790 refcount = get_refcount((IUnknown*)declaration3);
791 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
792 refcount = get_refcount((IUnknown*)declaration4);
793 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
795 IDirect3DVertexDeclaration9_Release(declaration4);
796 IDirect3DVertexDeclaration9_Release(declaration3);
797 IDirect3DVertexDeclaration9_Release(declaration2);
798 IDirect3DVertexDeclaration9_Release(declaration1);
800 refcount = IDirect3DDevice9_Release(device);
801 ok(!refcount, "Device has %u references left.\n", refcount);
802 done:
803 IDirect3D9_Release(d3d);
804 DestroyWindow(window);
807 static void test_vertex_declaration_alignment(void)
809 IDirect3DVertexDeclaration9 *declaration;
810 IDirect3DDevice9 *device;
811 IDirect3D9 *d3d;
812 unsigned int i;
813 ULONG refcount;
814 HWND window;
815 HRESULT hr;
817 static const struct
819 D3DVERTEXELEMENT9 elements[3];
820 HRESULT hr;
822 test_data[] =
826 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
827 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
828 D3DDECL_END(),
829 }, D3D_OK,
833 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
834 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
835 D3DDECL_END(),
836 }, E_FAIL,
840 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
841 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
842 D3DDECL_END(),
843 }, E_FAIL,
847 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
848 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
849 D3DDECL_END(),
850 }, E_FAIL,
854 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
855 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
856 D3DDECL_END(),
857 }, D3D_OK,
861 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
862 0, 0, 640, 480, NULL, NULL, NULL, NULL);
863 d3d = Direct3DCreate9(D3D_SDK_VERSION);
864 ok(!!d3d, "Failed to create a D3D object.\n");
865 if (!(device = create_device(d3d, window, NULL)))
867 skip("Failed to create a D3D device, skipping tests.\n");
868 goto done;
871 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
873 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
874 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
875 if (SUCCEEDED(hr))
876 IDirect3DVertexDeclaration9_Release(declaration);
879 refcount = IDirect3DDevice9_Release(device);
880 ok(!refcount, "Device has %u references left.\n", refcount);
881 done:
882 IDirect3D9_Release(d3d);
883 DestroyWindow(window);
886 static void test_unused_declaration_type(void)
888 IDirect3DVertexDeclaration9 *declaration;
889 IDirect3DDevice9 *device;
890 IDirect3D9 *d3d;
891 unsigned int i;
892 ULONG refcount;
893 HWND window;
894 HRESULT hr;
896 static const D3DVERTEXELEMENT9 test_elements[][3] =
899 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
900 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
901 D3DDECL_END(),
904 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
905 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
906 D3DDECL_END(),
909 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
910 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
911 D3DDECL_END(),
914 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
915 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
916 D3DDECL_END(),
919 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
920 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
921 D3DDECL_END(),
924 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
925 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
926 D3DDECL_END(),
929 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
930 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
931 D3DDECL_END(),
935 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
936 0, 0, 640, 480, NULL, NULL, NULL, NULL);
937 d3d = Direct3DCreate9(D3D_SDK_VERSION);
938 ok(!!d3d, "Failed to create a D3D object.\n");
939 if (!(device = create_device(d3d, window, NULL)))
941 skip("Failed to create a D3D device, skipping tests.\n");
942 goto done;
945 for (i = 0; i < sizeof(test_elements) / sizeof(*test_elements); ++i)
947 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
948 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
951 refcount = IDirect3DDevice9_Release(device);
952 ok(!refcount, "Device has %u references left.\n", refcount);
953 done:
954 IDirect3D9_Release(d3d);
955 DestroyWindow(window);
958 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
960 IDirect3DBaseTexture9* texture = NULL;
961 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
962 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
964 if (SUCCEEDED(hr)) {
965 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
966 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
967 } else
968 trace("CreateTexture failed: %08x\n", hr);
970 if (texture) IDirect3DBaseTexture9_Release( texture );
973 static void test_mipmap_levels(void)
975 IDirect3DDevice9 *device;
976 IDirect3D9 *d3d;
977 ULONG refcount;
978 HWND window;
980 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
981 0, 0, 640, 480, NULL, NULL, NULL, NULL);
982 ok(!!window, "Failed to create a window.\n");
983 d3d = Direct3DCreate9(D3D_SDK_VERSION);
984 ok(!!d3d, "Failed to create a D3D object.\n");
985 if (!(device = create_device(d3d, window, NULL)))
987 skip("Failed to create a 3D device, skipping test.\n");
988 goto cleanup;
991 check_mipmap_levels(device, 32, 32, 6);
992 check_mipmap_levels(device, 256, 1, 9);
993 check_mipmap_levels(device, 1, 256, 9);
994 check_mipmap_levels(device, 1, 1, 1);
996 refcount = IDirect3DDevice9_Release(device);
997 ok(!refcount, "Device has %u references left.\n", refcount);
998 cleanup:
999 IDirect3D9_Release(d3d);
1000 DestroyWindow(window);
1003 static void test_checkdevicemultisampletype(void)
1005 IDirect3DDevice9 *device;
1006 DWORD quality_levels;
1007 IDirect3D9 *d3d;
1008 ULONG refcount;
1009 HWND window;
1010 HRESULT hr;
1012 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1013 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1014 ok(!!window, "Failed to create a window.\n");
1015 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1016 ok(!!d3d, "Failed to create a D3D object.\n");
1017 if (!(device = create_device(d3d, window, NULL)))
1019 skip("Failed to create a 3D device, skipping test.\n");
1020 goto cleanup;
1023 quality_levels = 0;
1024 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1025 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1026 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
1027 if (hr == D3DERR_NOTAVAILABLE)
1029 skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
1030 goto cleanup;
1032 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1034 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1035 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1036 ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
1037 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1039 cleanup:
1040 if (device)
1042 refcount = IDirect3DDevice9_Release(device);
1043 ok(!refcount, "Device has %u references left.\n", refcount);
1045 IDirect3D9_Release(d3d);
1046 DestroyWindow(window);
1049 static void test_swapchain(void)
1051 IDirect3DSwapChain9 *swapchain0;
1052 IDirect3DSwapChain9 *swapchain1;
1053 IDirect3DSwapChain9 *swapchain2;
1054 IDirect3DSwapChain9 *swapchain3;
1055 IDirect3DSwapChain9 *swapchainX;
1056 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1057 D3DPRESENT_PARAMETERS d3dpp;
1058 IDirect3DDevice9 *device;
1059 IDirect3D9 *d3d;
1060 ULONG refcount;
1061 HWND window, window2;
1062 HRESULT hr;
1063 struct device_desc device_desc;
1065 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1066 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1067 ok(!!window, "Failed to create a window.\n");
1068 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1069 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1070 ok(!!window2, "Failed to create a window.\n");
1071 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1072 ok(!!d3d, "Failed to create a D3D object.\n");
1073 if (!(device = create_device(d3d, window, NULL)))
1075 skip("Failed to create a 3D device, skipping test.\n");
1076 goto cleanup;
1079 /* Get the implicit swapchain */
1080 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1081 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1082 /* Check if the back buffer count was modified */
1083 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1084 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1085 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1086 IDirect3DSwapChain9_Release(swapchain0);
1088 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1089 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1090 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1091 backbuffer = (void *)0xdeadbeef;
1092 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1093 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1094 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1095 backbuffer = (void *)0xdeadbeef;
1096 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1097 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1098 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1100 /* Check if there is a back buffer */
1101 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1102 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1103 ok(backbuffer != NULL, "The back buffer is NULL\n");
1104 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1106 /* The back buffer type value is ignored. */
1107 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1108 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1109 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1110 IDirect3DSurface9_Release(stereo_buffer);
1111 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1112 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1113 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1114 IDirect3DSurface9_Release(stereo_buffer);
1115 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1116 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1117 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1118 IDirect3DSurface9_Release(stereo_buffer);
1120 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1121 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1122 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1123 IDirect3DSurface9_Release(stereo_buffer);
1124 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1125 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1126 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1127 IDirect3DSurface9_Release(stereo_buffer);
1128 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1129 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1130 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1131 IDirect3DSurface9_Release(stereo_buffer);
1133 /* Try to get a nonexistent swapchain */
1134 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1135 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1136 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1137 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1139 /* Create a bunch of swapchains */
1140 d3dpp.BackBufferCount = 0;
1141 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1142 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1143 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1145 d3dpp.BackBufferCount = 1;
1146 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1147 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1149 d3dpp.BackBufferCount = 2;
1150 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1151 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1152 if(SUCCEEDED(hr)) {
1153 /* Swapchain 3, created with backbuffercount 2 */
1154 backbuffer = (void *) 0xdeadbeef;
1155 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1156 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1157 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1158 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1160 backbuffer = (void *) 0xdeadbeef;
1161 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1162 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1163 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1164 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1166 backbuffer = (void *) 0xdeadbeef;
1167 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1168 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1169 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1170 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1172 backbuffer = (void *) 0xdeadbeef;
1173 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1174 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1175 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1176 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1179 /* Check the back buffers of the swapchains */
1180 /* Swapchain 1, created with backbuffercount 0 */
1181 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1182 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1183 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1184 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1186 backbuffer = (void *) 0xdeadbeef;
1187 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1188 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1189 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1190 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1192 /* Swapchain 2 - created with backbuffercount 1 */
1193 backbuffer = (void *) 0xdeadbeef;
1194 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1195 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1196 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1197 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1199 backbuffer = (void *) 0xdeadbeef;
1200 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1201 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1202 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1203 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1205 backbuffer = (void *) 0xdeadbeef;
1206 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1207 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1208 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1209 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1211 /* Try getSwapChain on a manually created swapchain
1212 * it should fail, apparently GetSwapChain only returns implicit swapchains
1214 swapchainX = (void *) 0xdeadbeef;
1215 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1216 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1217 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1218 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1220 IDirect3DSwapChain9_Release(swapchain3);
1221 IDirect3DSwapChain9_Release(swapchain2);
1222 IDirect3DSwapChain9_Release(swapchain1);
1224 d3dpp.Windowed = FALSE;
1225 d3dpp.hDeviceWindow = window;
1226 d3dpp.BackBufferCount = 1;
1227 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1228 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1229 d3dpp.hDeviceWindow = window2;
1230 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1231 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1233 device_desc.width = registry_mode.dmPelsWidth;
1234 device_desc.height = registry_mode.dmPelsHeight;
1235 device_desc.device_window = window;
1236 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1237 hr = reset_device(device, &device_desc);
1238 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1240 d3dpp.hDeviceWindow = window;
1241 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1242 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1243 d3dpp.hDeviceWindow = window2;
1244 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1245 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1246 d3dpp.Windowed = TRUE;
1247 d3dpp.hDeviceWindow = window;
1248 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1249 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1250 d3dpp.hDeviceWindow = window2;
1251 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1252 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1254 refcount = IDirect3DDevice9_Release(device);
1255 ok(!refcount, "Device has %u references left.\n", refcount);
1256 cleanup:
1257 IDirect3D9_Release(d3d);
1258 DestroyWindow(window2);
1259 DestroyWindow(window);
1262 static void test_refcount(void)
1264 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1265 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1266 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1267 IDirect3DVertexShader9 *pVertexShader = NULL;
1268 IDirect3DPixelShader9 *pPixelShader = NULL;
1269 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1270 IDirect3DTexture9 *pTexture = NULL;
1271 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1272 IDirect3DVolume9 *pVolumeLevel = NULL;
1273 IDirect3DSurface9 *pStencilSurface = NULL;
1274 IDirect3DSurface9 *pOffscreenSurface = NULL;
1275 IDirect3DSurface9 *pRenderTarget = NULL;
1276 IDirect3DSurface9 *pRenderTarget2 = NULL;
1277 IDirect3DSurface9 *pRenderTarget3 = NULL;
1278 IDirect3DSurface9 *pTextureLevel = NULL;
1279 IDirect3DSurface9 *pBackBuffer = NULL;
1280 IDirect3DStateBlock9 *pStateBlock = NULL;
1281 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1282 IDirect3DSwapChain9 *pSwapChain = NULL;
1283 IDirect3DQuery9 *pQuery = NULL;
1284 D3DPRESENT_PARAMETERS d3dpp;
1285 IDirect3DDevice9 *device;
1286 ULONG refcount = 0, tmp;
1287 IDirect3D9 *d3d, *d3d2;
1288 HWND window;
1289 HRESULT hr;
1291 D3DVERTEXELEMENT9 decl[] =
1293 D3DDECL_END()
1296 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1297 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1298 ok(!!window, "Failed to create a window.\n");
1299 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1300 ok(!!d3d, "Failed to create a D3D object.\n");
1302 CHECK_REFCOUNT(d3d, 1);
1304 if (!(device = create_device(d3d, window, NULL)))
1306 skip("Failed to create a 3D device, skipping test.\n");
1307 goto cleanup;
1310 refcount = get_refcount((IUnknown *)device);
1311 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1313 CHECK_REFCOUNT(d3d, 2);
1315 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1316 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1318 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1319 CHECK_REFCOUNT(d3d, 3);
1320 CHECK_RELEASE_REFCOUNT(d3d, 2);
1323 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1324 * - the container is the device OR swapchain
1325 * - they hold a reference to the device
1326 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1327 * - they are not freed if refcount reaches 0.
1328 * - the refcount is not forwarded to the container.
1330 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1331 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1332 if (pSwapChain)
1334 CHECK_REFCOUNT( pSwapChain, 1);
1336 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1337 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1338 CHECK_REFCOUNT( pSwapChain, 1);
1339 if(pRenderTarget)
1341 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1342 CHECK_REFCOUNT( pRenderTarget, 1);
1344 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1345 CHECK_REFCOUNT(device, refcount);
1346 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1347 CHECK_REFCOUNT(device, refcount);
1349 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1350 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1351 CHECK_REFCOUNT( pRenderTarget, 2);
1352 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
1353 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
1354 CHECK_REFCOUNT(device, --refcount);
1356 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1357 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1358 CHECK_REFCOUNT(device, ++refcount);
1359 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1360 CHECK_REFCOUNT(device, --refcount);
1363 /* Render target and back buffer are identical. */
1364 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1365 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1366 if(pBackBuffer)
1368 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1369 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1370 pRenderTarget, pBackBuffer);
1371 pBackBuffer = NULL;
1373 CHECK_REFCOUNT(device, --refcount);
1375 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1376 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1377 CHECK_REFCOUNT( pSwapChain, 1);
1378 if(pStencilSurface)
1380 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1381 CHECK_REFCOUNT( pStencilSurface, 1);
1383 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1384 CHECK_REFCOUNT(device, refcount);
1385 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1386 CHECK_REFCOUNT(device, refcount);
1388 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
1389 CHECK_REFCOUNT(device, --refcount);
1391 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1392 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1393 CHECK_REFCOUNT(device, ++refcount);
1394 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1395 CHECK_REFCOUNT(device, --refcount);
1396 pStencilSurface = NULL;
1399 CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
1400 CHECK_REFCOUNT(device, --refcount);
1402 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1403 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1404 CHECK_REFCOUNT(device, ++refcount);
1405 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1406 CHECK_REFCOUNT(device, --refcount);
1407 pSwapChain = NULL;
1410 /* Buffers */
1411 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1412 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1413 if(pIndexBuffer)
1415 tmp = get_refcount( (IUnknown *)pIndexBuffer );
1417 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1418 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1419 hr = IDirect3DDevice9_SetIndices(device, NULL);
1420 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1423 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1424 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1425 if(pVertexBuffer)
1427 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1428 UINT offset = ~0;
1429 UINT stride = ~0;
1431 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1433 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1434 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1435 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1436 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1438 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1439 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1440 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1441 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1442 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1444 /* Shaders */
1445 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1446 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1447 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1448 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1449 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1450 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1451 /* Textures */
1452 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1453 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1454 if (pTexture)
1456 tmp = get_refcount( (IUnknown *)pTexture );
1458 /* SetTexture should not increase refcounts */
1459 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1460 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1461 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1462 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1464 /* This should not increment device refcount */
1465 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1466 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1467 /* But should increment texture's refcount */
1468 CHECK_REFCOUNT( pTexture, tmp+1 );
1469 /* Because the texture and surface refcount are identical */
1470 if (pTextureLevel)
1472 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1473 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1474 CHECK_REFCOUNT ( pTexture , tmp+2 );
1475 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1476 CHECK_REFCOUNT ( pTexture , tmp+1 );
1477 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1478 CHECK_REFCOUNT ( pTextureLevel, tmp );
1481 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1482 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1483 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1484 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1485 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1486 if (pVolumeTexture)
1488 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1490 /* This should not increment device refcount */
1491 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1492 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1493 /* But should increment volume texture's refcount */
1494 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1495 /* Because the volume texture and volume refcount are identical */
1496 if (pVolumeLevel)
1498 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1499 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1500 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1501 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1502 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1503 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1504 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1507 /* Surfaces */
1508 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1509 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1510 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1511 CHECK_REFCOUNT( pStencilSurface, 1 );
1512 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1513 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1514 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1515 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1516 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1517 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1518 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1519 CHECK_REFCOUNT( pRenderTarget3, 1 );
1520 /* Misc */
1521 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1522 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1524 memset(&d3dpp, 0, sizeof(d3dpp));
1525 d3dpp.Windowed = TRUE;
1526 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1527 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1528 d3dpp.EnableAutoDepthStencil = TRUE;
1529 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1530 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1531 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1532 if(pSwapChain)
1534 /* check implicit back buffer */
1535 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1536 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1537 CHECK_REFCOUNT( pSwapChain, 1);
1538 if(pBackBuffer)
1540 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1541 CHECK_REFCOUNT( pBackBuffer, 1);
1542 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
1543 CHECK_REFCOUNT(device, --refcount);
1545 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1546 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1547 CHECK_REFCOUNT(device, ++refcount);
1548 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1549 CHECK_REFCOUNT(device, --refcount);
1550 pBackBuffer = NULL;
1552 CHECK_REFCOUNT( pSwapChain, 1);
1554 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1555 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1557 hr = IDirect3DDevice9_BeginStateBlock(device);
1558 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1559 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1560 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1562 /* The implicit render target is not freed if refcount reaches 0.
1563 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1564 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1565 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1566 if(pRenderTarget2)
1568 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1569 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1570 pRenderTarget, pRenderTarget2);
1571 CHECK_REFCOUNT(device, --refcount);
1572 pRenderTarget2 = NULL;
1574 pRenderTarget = NULL;
1576 cleanup:
1577 CHECK_RELEASE(device, device, --refcount);
1579 /* Buffers */
1580 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1581 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1582 /* Shaders */
1583 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1584 CHECK_RELEASE(pVertexShader, device, --refcount);
1585 CHECK_RELEASE(pPixelShader, device, --refcount);
1586 /* Textures */
1587 CHECK_RELEASE(pTextureLevel, device, --refcount);
1588 CHECK_RELEASE(pCubeTexture, device, --refcount);
1589 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1590 /* Surfaces */
1591 CHECK_RELEASE(pStencilSurface, device, --refcount);
1592 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1593 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1594 /* Misc */
1595 CHECK_RELEASE(pStateBlock, device, --refcount);
1596 CHECK_RELEASE(pSwapChain, device, --refcount);
1597 CHECK_RELEASE(pQuery, device, --refcount);
1598 /* This will destroy device - cannot check the refcount here */
1599 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1600 CHECK_RELEASE_REFCOUNT(d3d, 0);
1601 DestroyWindow(window);
1604 static void test_cursor(void)
1606 IDirect3DSurface9 *cursor = NULL;
1607 IDirect3DDevice9 *device;
1608 CURSORINFO info;
1609 IDirect3D9 *d3d;
1610 ULONG refcount;
1611 HCURSOR cur;
1612 HWND window;
1613 HRESULT hr;
1614 BOOL ret;
1616 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1617 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1618 ok(!!window, "Failed to create a window.\n");
1620 ret = SetCursorPos(50, 50);
1621 ok(ret, "Failed to set cursor position.\n");
1622 flush_events();
1623 memset(&info, 0, sizeof(info));
1624 info.cbSize = sizeof(info);
1625 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1626 cur = info.hCursor;
1628 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1629 ok(!!d3d, "Failed to create a D3D object.\n");
1630 if (!(device = create_device(d3d, window, NULL)))
1632 skip("Failed to create a 3D device, skipping test.\n");
1633 goto cleanup;
1636 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1637 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1638 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1640 /* Initially hidden */
1641 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1642 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1644 /* Not enabled without a surface*/
1645 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1646 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1648 /* Fails */
1649 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1650 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1652 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1653 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1655 IDirect3DSurface9_Release(cursor);
1657 memset(&info, 0, sizeof(info));
1658 info.cbSize = sizeof(info);
1659 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1660 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
1661 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1663 /* Still hidden */
1664 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1665 ok(hr == FALSE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1667 /* Enabled now*/
1668 hr = IDirect3DDevice9_ShowCursor(device, TRUE);
1669 ok(hr == TRUE, "IDirect3DDevice9_ShowCursor returned %08x\n", hr);
1671 memset(&info, 0, sizeof(info));
1672 info.cbSize = sizeof(info);
1673 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1674 ok(info.flags & CURSOR_SHOWING, "The gdi cursor is hidden (%08x)\n", info.flags);
1675 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1677 refcount = IDirect3DDevice9_Release(device);
1678 ok(!refcount, "Device has %u references left.\n", refcount);
1679 cleanup:
1680 IDirect3D9_Release(d3d);
1681 DestroyWindow(window);
1684 static void test_reset(void)
1686 HRESULT hr;
1687 RECT winrect;
1688 D3DPRESENT_PARAMETERS d3dpp;
1689 D3DDISPLAYMODE d3ddm, d3ddm2;
1690 D3DVIEWPORT9 vp;
1691 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1692 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1693 IDirect3DSurface9 *surface;
1694 IDirect3DTexture9 *texture;
1695 IDirect3DVertexShader9 *shader;
1696 UINT i, adapter_mode_count;
1697 D3DLOCKED_RECT lockrect;
1698 IDirect3DDevice9 *device1 = NULL;
1699 IDirect3DDevice9 *device2 = NULL;
1700 IDirect3DSwapChain9 *swapchain;
1701 struct device_desc device_desc;
1702 IDirect3D9 *d3d;
1703 D3DCAPS9 caps;
1704 DWORD value;
1705 HWND hwnd;
1706 struct
1708 UINT w;
1709 UINT h;
1710 } *modes = NULL;
1711 UINT mode_count = 0;
1713 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1714 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1715 ok(!!hwnd, "Failed to create a window.\n");
1716 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1717 ok(!!d3d, "Failed to create a D3D object.\n");
1719 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1720 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1721 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1722 for(i = 0; i < adapter_mode_count; ++i)
1724 UINT j;
1725 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1726 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1727 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1729 for (j = 0; j < mode_count; ++j)
1731 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1732 break;
1734 if (j == mode_count)
1736 modes[j].w = d3ddm2.Width;
1737 modes[j].h = d3ddm2.Height;
1738 ++mode_count;
1741 /* We use them as invalid modes */
1742 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1743 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1744 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1745 d3ddm2.Width, d3ddm2.Height);
1746 goto cleanup;
1750 if (mode_count < 2)
1752 skip("Less than 2 modes supported, skipping mode tests\n");
1753 goto cleanup;
1756 i = 0;
1757 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1759 device_desc.width = modes[i].w;
1760 device_desc.height = modes[i].h;
1761 device_desc.device_window = hwnd;
1762 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1763 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1765 skip("Failed to create a D3D device, skipping tests.\n");
1766 goto cleanup;
1768 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1769 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1771 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1772 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1774 width = GetSystemMetrics(SM_CXSCREEN);
1775 height = GetSystemMetrics(SM_CYSCREEN);
1776 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1777 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1779 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1780 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1781 if(SUCCEEDED(hr))
1783 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1784 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1785 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1786 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1787 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1788 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1791 i = 1;
1792 vp.X = 10;
1793 vp.Y = 20;
1794 vp.MinZ = 2;
1795 vp.MaxZ = 3;
1796 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1797 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1799 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1800 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1801 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1802 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1803 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1805 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1806 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1807 d3dpp.Windowed = FALSE;
1808 d3dpp.BackBufferWidth = modes[i].w;
1809 d3dpp.BackBufferHeight = modes[i].h;
1810 d3dpp.BackBufferFormat = d3ddm.Format;
1811 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1812 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1813 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1814 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1816 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1817 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1818 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1820 ZeroMemory(&vp, sizeof(vp));
1821 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1822 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1823 if(SUCCEEDED(hr))
1825 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1826 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1827 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1828 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1829 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1830 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1833 width = GetSystemMetrics(SM_CXSCREEN);
1834 height = GetSystemMetrics(SM_CYSCREEN);
1835 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1836 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1838 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1839 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1840 memset(&d3dpp, 0, sizeof(d3dpp));
1841 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1842 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1843 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1844 d3dpp.BackBufferWidth, modes[i].w);
1845 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1846 d3dpp.BackBufferHeight, modes[i].h);
1847 IDirect3DSwapChain9_Release(swapchain);
1849 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1850 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1851 d3dpp.Windowed = TRUE;
1852 d3dpp.BackBufferWidth = 400;
1853 d3dpp.BackBufferHeight = 300;
1854 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1855 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1856 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1857 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1858 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1860 width = GetSystemMetrics(SM_CXSCREEN);
1861 height = GetSystemMetrics(SM_CYSCREEN);
1862 ok(width == orig_width, "Screen width is %d\n", width);
1863 ok(height == orig_height, "Screen height is %d\n", height);
1865 ZeroMemory(&vp, sizeof(vp));
1866 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1867 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1868 if(SUCCEEDED(hr))
1870 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1871 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1872 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1873 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1874 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1875 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1878 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1879 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1880 memset(&d3dpp, 0, sizeof(d3dpp));
1881 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1882 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1883 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1884 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1885 IDirect3DSwapChain9_Release(swapchain);
1887 winrect.left = 0;
1888 winrect.top = 0;
1889 winrect.right = 200;
1890 winrect.bottom = 150;
1891 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1892 ok(SetWindowPos(hwnd, NULL, 0, 0,
1893 winrect.right-winrect.left,
1894 winrect.bottom-winrect.top,
1895 SWP_NOMOVE|SWP_NOZORDER),
1896 "SetWindowPos failed\n");
1898 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1899 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1900 d3dpp.Windowed = TRUE;
1901 d3dpp.BackBufferWidth = 0;
1902 d3dpp.BackBufferHeight = 0;
1903 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
1904 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1905 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1906 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1907 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1909 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1910 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1911 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1912 d3dpp.BackBufferFormat, d3ddm.Format);
1913 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1914 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1915 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1916 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1917 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1918 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1919 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1920 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1921 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1922 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1923 d3dpp.FullScreen_RefreshRateInHz);
1924 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1926 ZeroMemory(&vp, sizeof(vp));
1927 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1928 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1929 if(SUCCEEDED(hr))
1931 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1932 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1933 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
1934 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
1935 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1936 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1939 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1940 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1941 memset(&d3dpp, 0, sizeof(d3dpp));
1942 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1943 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1944 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1945 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1946 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1947 d3dpp.BackBufferFormat, d3ddm.Format);
1948 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1949 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1950 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1951 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1952 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
1953 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1954 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1955 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1956 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1957 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1958 d3dpp.FullScreen_RefreshRateInHz);
1959 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1960 IDirect3DSwapChain9_Release(swapchain);
1962 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1963 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1964 d3dpp.Windowed = TRUE;
1965 d3dpp.BackBufferWidth = 400;
1966 d3dpp.BackBufferHeight = 300;
1968 /* _Reset fails if there is a resource in the default pool */
1969 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1970 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1971 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1972 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1973 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1974 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1975 IDirect3DSurface9_Release(surface);
1976 /* Reset again to get the device out of the lost state */
1977 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1978 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1979 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1980 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1982 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1984 IDirect3DVolumeTexture9 *volume_texture;
1986 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1987 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1988 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1989 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1990 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1991 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1992 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1993 hr, D3DERR_DEVICENOTRESET);
1994 IDirect3DVolumeTexture9_Release(volume_texture);
1995 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1996 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1997 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1998 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2000 else
2002 skip("Volume textures not supported.\n");
2005 /* Scratch, sysmem and managed pools are fine */
2006 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2007 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2008 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2009 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2010 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2011 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2012 IDirect3DSurface9_Release(surface);
2014 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2015 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2016 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2017 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2018 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2019 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2020 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2021 IDirect3DSurface9_Release(surface);
2023 /* The depth stencil should get reset to the auto depth stencil when present. */
2024 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2025 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2027 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2028 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2029 ok(surface == NULL, "Depth stencil should be NULL\n");
2031 d3dpp.EnableAutoDepthStencil = TRUE;
2032 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2033 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2034 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2036 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2037 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2038 ok(surface != NULL, "Depth stencil should not be NULL\n");
2039 if (surface) IDirect3DSurface9_Release(surface);
2041 d3dpp.EnableAutoDepthStencil = FALSE;
2042 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2043 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2045 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2046 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2047 ok(surface == NULL, "Depth stencil should be NULL\n");
2049 /* Will a sysmem or scratch survive while locked */
2050 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2051 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2052 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2053 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2054 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2055 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2056 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2057 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2058 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2059 IDirect3DSurface9_UnlockRect(surface);
2060 IDirect3DSurface9_Release(surface);
2062 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2063 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2064 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2065 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2066 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2067 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2068 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2069 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2070 IDirect3DSurface9_UnlockRect(surface);
2071 IDirect3DSurface9_Release(surface);
2073 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2074 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2075 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2076 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2077 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2078 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2079 IDirect3DTexture9_Release(texture);
2081 /* A reference held to an implicit surface causes failures as well */
2082 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2083 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2084 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2085 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2086 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2087 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2088 IDirect3DSurface9_Release(surface);
2089 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2090 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2091 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2092 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2094 /* Shaders are fine as well */
2095 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2096 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2097 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2098 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2099 IDirect3DVertexShader9_Release(shader);
2101 /* Try setting invalid modes */
2102 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2103 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2104 d3dpp.Windowed = FALSE;
2105 d3dpp.BackBufferWidth = 32;
2106 d3dpp.BackBufferHeight = 32;
2107 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2108 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2109 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2110 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2112 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2113 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2114 d3dpp.Windowed = FALSE;
2115 d3dpp.BackBufferWidth = 801;
2116 d3dpp.BackBufferHeight = 600;
2117 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2118 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2119 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2120 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2122 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2123 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2124 d3dpp.Windowed = FALSE;
2125 d3dpp.BackBufferWidth = 0;
2126 d3dpp.BackBufferHeight = 0;
2127 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2128 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2129 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2130 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2132 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2134 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2135 d3dpp.Windowed = TRUE;
2136 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2137 d3dpp.BackBufferFormat = d3ddm.Format;
2138 d3dpp.EnableAutoDepthStencil = FALSE;
2139 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2141 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2142 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2144 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2145 goto cleanup;
2148 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2149 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2151 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2152 d3dpp.Windowed = TRUE;
2153 d3dpp.BackBufferWidth = 400;
2154 d3dpp.BackBufferHeight = 300;
2155 d3dpp.EnableAutoDepthStencil = TRUE;
2156 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2158 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2159 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2161 if (FAILED(hr)) goto cleanup;
2163 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2164 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2165 ok(surface != NULL, "Depth stencil should not be NULL\n");
2166 if (surface) IDirect3DSurface9_Release(surface);
2168 cleanup:
2169 HeapFree(GetProcessHeap(), 0, modes);
2170 if (device2)
2172 UINT refcount = IDirect3DDevice9_Release(device2);
2173 ok(!refcount, "Device has %u references left.\n", refcount);
2175 if (device1)
2177 UINT refcount = IDirect3DDevice9_Release(device1);
2178 ok(!refcount, "Device has %u references left.\n", refcount);
2180 IDirect3D9_Release(d3d);
2181 DestroyWindow(hwnd);
2184 /* Test adapter display modes */
2185 static void test_display_modes(void)
2187 D3DDISPLAYMODE dmode;
2188 IDirect3D9 *d3d;
2190 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2191 ok(!!d3d, "Failed to create a D3D object.\n");
2193 #define TEST_FMT(x,r) do { \
2194 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2195 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2196 } while(0)
2198 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2199 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2200 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2201 /* D3DFMT_R5G6B5 */
2202 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2203 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2204 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2205 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2206 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2207 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2208 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2209 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2210 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2211 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2212 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2213 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2215 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2216 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2218 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2219 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2220 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2222 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2223 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2224 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2225 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2226 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2227 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2229 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2230 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2231 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2232 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2233 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2234 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2235 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2236 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2237 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2238 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2240 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2241 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2242 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2243 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2244 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2245 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2246 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2247 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2248 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2249 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2251 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2252 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2253 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2254 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2255 /* Floating point formats */
2256 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2257 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2258 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2260 /* IEEE formats */
2261 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2262 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2263 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2265 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2267 TEST_FMT(0, D3DERR_INVALIDCALL);
2269 IDirect3D9_Release(d3d);
2272 static void test_scene(void)
2274 IDirect3DSurface9 *surface1, *surface2, *surface3;
2275 IDirect3DSurface9 *backBuffer, *rt, *ds;
2276 RECT rect = {0, 0, 128, 128};
2277 IDirect3DDevice9 *device;
2278 IDirect3D9 *d3d;
2279 ULONG refcount;
2280 D3DCAPS9 caps;
2281 HWND window;
2282 HRESULT hr;
2284 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2285 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2286 ok(!!window, "Failed to create a window.\n");
2287 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2288 ok(!!d3d, "Failed to create a D3D object.\n");
2289 if (!(device = create_device(d3d, window, NULL)))
2291 skip("Failed to create a 3D device, skipping test.\n");
2292 goto cleanup;
2295 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2296 memset(&caps, 0, sizeof(caps));
2297 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2298 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2300 /* Test an EndScene without BeginScene. Should return an error */
2301 hr = IDirect3DDevice9_EndScene(device);
2302 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2304 /* Test a normal BeginScene / EndScene pair, this should work */
2305 hr = IDirect3DDevice9_BeginScene(device);
2306 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2307 hr = IDirect3DDevice9_EndScene(device);
2308 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2310 /* Test another EndScene without having begun a new scene. Should return an error */
2311 hr = IDirect3DDevice9_EndScene(device);
2312 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2314 /* Two nested BeginScene and EndScene calls */
2315 hr = IDirect3DDevice9_BeginScene(device);
2316 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2317 hr = IDirect3DDevice9_BeginScene(device);
2318 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2319 hr = IDirect3DDevice9_EndScene(device);
2320 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2321 hr = IDirect3DDevice9_EndScene(device);
2322 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2324 /* Create some surfaces to test stretchrect between the scenes */
2325 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2326 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2327 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2328 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2329 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2330 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2331 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2332 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2333 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2334 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2335 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2336 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2338 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2339 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2340 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2341 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2343 /* First make sure a simple StretchRect call works */
2344 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2345 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2346 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2347 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2348 if (0) /* Disabled for now because it crashes in wine */
2350 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2351 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2352 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2355 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2356 * BeginScene - Endscene pair with normal surfaces and render targets, but
2357 * not depth stencil surfaces. */
2358 hr = IDirect3DDevice9_BeginScene(device);
2359 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2361 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2362 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2363 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2364 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2365 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2366 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2367 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2369 hr = IDirect3DDevice9_EndScene(device);
2370 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2372 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2373 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2374 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2376 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2377 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2378 hr = IDirect3DDevice9_BeginScene(device);
2379 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2380 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2381 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2382 hr = IDirect3DDevice9_EndScene(device);
2383 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2385 IDirect3DSurface9_Release(rt);
2386 IDirect3DSurface9_Release(ds);
2387 IDirect3DSurface9_Release(backBuffer);
2388 IDirect3DSurface9_Release(surface1);
2389 IDirect3DSurface9_Release(surface2);
2390 IDirect3DSurface9_Release(surface3);
2391 refcount = IDirect3DDevice9_Release(device);
2392 ok(!refcount, "Device has %u references left.\n", refcount);
2393 cleanup:
2394 IDirect3D9_Release(d3d);
2395 DestroyWindow(window);
2398 static void test_limits(void)
2400 IDirect3DTexture9 *texture;
2401 IDirect3DDevice9 *device;
2402 IDirect3D9 *d3d;
2403 unsigned int i;
2404 ULONG refcount;
2405 HWND window;
2406 HRESULT hr;
2408 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2409 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2410 ok(!!window, "Failed to create a window.\n");
2411 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2412 ok(!!d3d, "Failed to create a D3D object.\n");
2413 if (!(device = create_device(d3d, window, NULL)))
2415 skip("Failed to create a 3D device, skipping test.\n");
2416 goto cleanup;
2419 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2420 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2422 /* There are 16 pixel samplers. We should be able to access all of them */
2423 for (i = 0; i < 16; ++i)
2425 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2426 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2427 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2428 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2429 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2430 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2433 /* Now test all 8 textures stage states */
2434 for (i = 0; i < 8; ++i)
2436 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2437 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2440 /* Investigations show that accessing higher samplers / textures stage
2441 * states does not return an error either. Writing to too high samplers
2442 * (approximately sampler 40) causes memory corruption in Windows, so
2443 * there is no bounds checking. */
2444 IDirect3DTexture9_Release(texture);
2445 refcount = IDirect3D9_Release(device);
2446 ok(!refcount, "Device has %u references left.\n", refcount);
2447 cleanup:
2448 IDirect3D9_Release(d3d);
2449 DestroyWindow(window);
2452 static void test_depthstenciltest(void)
2454 HRESULT hr;
2455 IDirect3DDevice9 *pDevice = NULL;
2456 D3DPRESENT_PARAMETERS d3dpp;
2457 D3DDISPLAYMODE d3ddm;
2458 IDirect3DSurface9 *pDepthStencil = NULL;
2459 IDirect3DSurface9 *pDepthStencil2 = NULL;
2460 IDirect3D9 *d3d;
2461 DWORD state;
2462 HWND hwnd;
2464 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2465 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2466 ok(!!hwnd, "Failed to create a window.\n");
2467 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2468 ok(!!d3d, "Failed to create a D3D object.\n");
2470 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2471 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2472 d3dpp.Windowed = TRUE;
2473 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2474 d3dpp.BackBufferWidth = 800;
2475 d3dpp.BackBufferHeight = 600;
2476 d3dpp.BackBufferFormat = d3ddm.Format;
2477 d3dpp.EnableAutoDepthStencil = TRUE;
2478 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2480 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2481 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2482 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2483 if(!pDevice)
2485 skip("Failed to create a d3d device\n");
2486 goto cleanup;
2489 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2490 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2492 /* Try to clear */
2493 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2494 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2496 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2497 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2499 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2500 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2501 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2502 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2504 /* This left the render states untouched! */
2505 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2506 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2507 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2508 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2509 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2510 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2511 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2512 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2513 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2514 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2515 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2516 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2518 /* This is supposed to fail now */
2519 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2520 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2522 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2523 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2525 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2526 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2528 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2529 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2530 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2532 /* Now it works again */
2533 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2534 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2536 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2537 if(pDevice) IDirect3D9_Release(pDevice);
2539 /* Now see if autodepthstencil disable is honored. First, without a format set */
2540 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2541 d3dpp.Windowed = TRUE;
2542 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2543 d3dpp.BackBufferWidth = 800;
2544 d3dpp.BackBufferHeight = 600;
2545 d3dpp.BackBufferFormat = d3ddm.Format;
2546 d3dpp.EnableAutoDepthStencil = FALSE;
2547 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2549 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2550 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2551 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2552 if(!pDevice)
2554 skip("Failed to create a d3d device\n");
2555 goto cleanup;
2558 pDepthStencil = NULL;
2559 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2560 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2561 if(pDepthStencil) {
2562 IDirect3DSurface9_Release(pDepthStencil);
2563 pDepthStencil = NULL;
2566 /* Check the depth test state */
2567 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2568 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2569 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2571 if(pDevice) IDirect3D9_Release(pDevice);
2573 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2574 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2575 d3dpp.Windowed = TRUE;
2576 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2577 d3dpp.BackBufferWidth = 800;
2578 d3dpp.BackBufferHeight = 600;
2579 d3dpp.BackBufferFormat = d3ddm.Format;
2580 d3dpp.EnableAutoDepthStencil = FALSE;
2581 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2583 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2584 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2585 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2586 if(!pDevice)
2588 skip("Failed to create a d3d device\n");
2589 goto cleanup;
2592 pDepthStencil = NULL;
2593 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2594 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2595 if(pDepthStencil) {
2596 IDirect3DSurface9_Release(pDepthStencil);
2597 pDepthStencil = NULL;
2600 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2601 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2602 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2604 cleanup:
2605 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2606 if (pDevice)
2608 UINT refcount = IDirect3D9_Release(pDevice);
2609 ok(!refcount, "Device has %u references left.\n", refcount);
2611 IDirect3D9_Release(d3d);
2612 DestroyWindow(hwnd);
2615 static void test_get_rt(void)
2617 IDirect3DSurface9 *backbuffer, *rt;
2618 IDirect3DDevice9 *device;
2619 IDirect3D9 *d3d9;
2620 D3DCAPS9 caps;
2621 HWND window;
2622 HRESULT hr;
2623 ULONG ref;
2624 UINT i;
2626 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2627 0, 0, 128, 128, 0, 0, 0, 0);
2628 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2629 ok(!!d3d9, "Failed to create a D3D object.\n");
2630 device = create_device(d3d9, window, NULL);
2631 if (!device)
2633 skip("Failed to create a D3D device, skipping tests.\n");
2634 goto done;
2637 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2638 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2639 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2641 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2642 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2644 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2646 rt = backbuffer;
2647 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2648 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2649 ok(!rt, "Got rt %p.\n", rt);
2652 IDirect3DSurface9_Release(backbuffer);
2654 ref = IDirect3DDevice9_Release(device);
2655 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2656 done:
2657 IDirect3D9_Release(d3d9);
2658 DestroyWindow(window);
2661 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
2662 static void test_draw_indexed(void)
2664 static const struct {
2665 float position[3];
2666 DWORD color;
2667 } quad[] = {
2668 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2669 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2670 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2671 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2673 WORD indices[] = {0, 1, 2, 3, 0, 2};
2675 static const D3DVERTEXELEMENT9 decl_elements[] = {
2676 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2677 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2678 D3DDECL_END()
2681 IDirect3DVertexDeclaration9 *vertex_declaration;
2682 IDirect3DVertexBuffer9 *vertex_buffer;
2683 IDirect3DIndexBuffer9 *index_buffer;
2684 IDirect3DDevice9 *device;
2685 IDirect3D9 *d3d9;
2686 ULONG refcount;
2687 HWND window;
2688 HRESULT hr;
2689 void *ptr;
2691 window = CreateWindowA("d3d9_test_wc", "d3d9_test", 0,
2692 0, 0, 640, 480, 0, 0, 0, 0);
2693 ok(!!window, "Failed to create a window.\n");
2694 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2695 ok(!!d3d9, "Failed to create a D3D object.\n");
2696 if (!(device = create_device(d3d9, window, NULL)))
2698 skip("Failed to create a 3D device, skipping test.\n");
2699 goto cleanup;
2702 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2703 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
2704 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2705 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2707 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2708 ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
2709 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2710 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
2711 memcpy(ptr, quad, sizeof(quad));
2712 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2713 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2714 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2715 ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
2717 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
2718 ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
2719 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2720 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
2721 memcpy(ptr, indices, sizeof(indices));
2722 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2723 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2724 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2725 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
2726 hr = IDirect3DDevice9_BeginScene(device);
2727 ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
2729 /* NULL index buffer. Should fail */
2730 hr = IDirect3DDevice9_SetIndices(device, NULL);
2731 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
2732 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2733 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2734 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
2735 hr, D3DERR_INVALIDCALL);
2737 /* Valid index buffer, NULL vertex declaration. Should fail */
2738 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2739 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
2740 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2741 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2742 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
2743 hr, D3DERR_INVALIDCALL);
2745 /* Valid index buffer and vertex declaration. Should succeed */
2746 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2747 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2748 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2749 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2750 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
2752 hr = IDirect3DDevice9_EndScene(device);
2753 ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2755 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2756 ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2758 IDirect3DVertexBuffer9_Release(vertex_buffer);
2759 IDirect3DIndexBuffer9_Release(index_buffer);
2760 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2761 refcount = IDirect3DDevice9_Release(device);
2762 ok(!refcount, "Device has %u references left.\n", refcount);
2763 cleanup:
2764 IDirect3D9_Release(d3d9);
2765 DestroyWindow(window);
2768 static void test_null_stream(void)
2770 IDirect3DVertexBuffer9 *buffer = NULL;
2771 IDirect3DDevice9 *device;
2772 IDirect3D9 *d3d9;
2773 ULONG refcount;
2774 HWND window;
2775 HRESULT hr;
2776 IDirect3DVertexShader9 *shader = NULL;
2777 IDirect3DVertexDeclaration9 *decl = NULL;
2778 static const DWORD shader_code[] =
2780 0xfffe0101, /* vs_1_1 */
2781 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2782 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2783 0x0000ffff /* end */
2785 static const D3DVERTEXELEMENT9 decl_elements[] = {
2786 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2787 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2788 D3DDECL_END()
2791 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2792 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2793 ok(!!window, "Failed to create a window.\n");
2794 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2795 ok(!!d3d9, "Failed to create a D3D object.\n");
2796 if (!(device = create_device(d3d9, window, NULL)))
2798 skip("Failed to create a 3D device, skipping test.\n");
2799 goto cleanup;
2802 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2803 if(FAILED(hr)) {
2804 skip("No vertex shader support\n");
2805 goto cleanup;
2807 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2808 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2809 if (FAILED(hr)) {
2810 skip("Vertex declaration handling not possible.\n");
2811 goto cleanup;
2813 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2814 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2815 if (FAILED(hr)) {
2816 skip("Vertex buffer handling not possible.\n");
2817 goto cleanup;
2820 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
2821 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2822 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
2823 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2824 hr = IDirect3DDevice9_SetVertexShader(device, shader);
2825 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
2826 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2827 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
2829 hr = IDirect3DDevice9_BeginScene(device);
2830 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2831 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
2832 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2833 hr = IDirect3DDevice9_EndScene(device);
2834 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2836 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2837 IDirect3DDevice9_SetVertexShader(device, NULL);
2838 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2840 cleanup:
2841 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
2842 if (decl) IDirect3DVertexDeclaration9_Release(decl);
2843 if (shader) IDirect3DVertexShader9_Release(shader);
2844 if (device)
2846 refcount = IDirect3DDevice9_Release(device);
2847 ok(!refcount, "Device has %u references left.\n", refcount);
2849 IDirect3D9_Release(d3d9);
2850 DestroyWindow(window);
2853 static void test_lights(void)
2855 IDirect3DDevice9 *device;
2856 IDirect3D9 *d3d9;
2857 ULONG refcount;
2858 HWND window;
2859 HRESULT hr;
2860 unsigned int i;
2861 BOOL enabled;
2862 D3DCAPS9 caps;
2864 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2865 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2866 ok(!!window, "Failed to create a window.\n");
2867 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2868 ok(!!d3d9, "Failed to create a D3D object.\n");
2869 if (!(device = create_device(d3d9, window, NULL)))
2871 skip("Failed to create a 3D device, skipping test.\n");
2872 goto cleanup;
2875 memset(&caps, 0, sizeof(caps));
2876 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2877 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
2879 for(i = 1; i <= caps.MaxActiveLights; i++) {
2880 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
2881 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2882 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
2883 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
2884 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2887 /* TODO: Test the rendering results in this situation */
2888 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
2889 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2890 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
2891 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2892 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2893 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
2894 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2896 for(i = 1; i <= caps.MaxActiveLights; i++) {
2897 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2898 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2901 refcount = IDirect3DDevice9_Release(device);
2902 ok(!refcount, "Device has %u references left.\n", refcount);
2903 cleanup:
2904 IDirect3D9_Release(d3d9);
2905 DestroyWindow(window);
2908 static void test_set_stream_source(void)
2910 IDirect3DVertexBuffer9 *vb;
2911 IDirect3DDevice9 *device;
2912 IDirect3D9 *d3d9;
2913 ULONG refcount;
2914 HWND window;
2915 HRESULT hr;
2917 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2918 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2919 ok(!!window, "Failed to create a window.\n");
2920 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2921 ok(!!d3d9, "Failed to create a D3D object.\n");
2922 if (!(device = create_device(d3d9, window, NULL)))
2924 skip("Failed to create a 3D device, skipping test.\n");
2925 goto cleanup;
2928 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
2929 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
2931 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
2932 * (Radeon 9000 verified) reject them, so accept both results. Wine
2933 * currently rejects this to be able to optimize the vbo conversion, but
2934 * writes a WARN. */
2935 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
2936 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2937 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
2938 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2939 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
2940 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2941 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
2942 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2943 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
2944 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2946 /* Try to set the NULL buffer with an offset and stride 0 */
2947 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2948 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2949 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2950 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2951 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2952 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2953 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2954 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2955 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2956 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2958 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2959 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2961 IDirect3DVertexBuffer9_Release(vb);
2962 refcount = IDirect3DDevice9_Release(device);
2963 ok(!refcount, "Device has %u references left.\n", refcount);
2964 cleanup:
2965 IDirect3D9_Release(d3d9);
2966 DestroyWindow(window);
2969 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
2970 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
2971 * a fixed number of combinations are possible in fullscreen mode. In windowed
2972 * mode more combinations are allowed due to format conversion and this is
2973 * likely driver dependent. */
2974 static void test_display_formats(void)
2976 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
2977 unsigned int backbuffer, display;
2978 unsigned int windowed;
2979 IDirect3D9 *d3d9;
2980 BOOL should_pass;
2981 BOOL has_modes;
2982 HRESULT hr;
2984 static const struct
2986 const char *name;
2987 D3DFORMAT format;
2988 D3DFORMAT alpha_format;
2989 BOOL display;
2990 BOOL windowed;
2992 formats[] =
2994 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
2995 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
2996 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
2997 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
2998 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
2999 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3000 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3003 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3004 ok(!!d3d9, "Failed to create a D3D object.\n");
3006 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
3008 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3010 for (windowed = 0; windowed <= 1; ++windowed)
3012 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
3014 should_pass = FALSE;
3016 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3018 D3DFORMAT backbuffer_format;
3020 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3021 backbuffer_format = formats[display].format;
3022 else
3023 backbuffer_format = formats[backbuffer].format;
3025 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3026 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3027 if (hr == D3D_OK)
3029 if (windowed)
3031 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3032 backbuffer_format, formats[display].format);
3033 should_pass = (hr == D3D_OK);
3035 else
3036 should_pass = (formats[display].format == formats[backbuffer].format
3037 || (formats[display].alpha_format
3038 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3042 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3043 formats[display].format, formats[backbuffer].format, windowed);
3044 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3045 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3046 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3051 IDirect3D9_Release(d3d9);
3054 static void test_scissor_size(void)
3056 struct device_desc device_desc;
3057 IDirect3D9 *d3d9_ptr;
3058 unsigned int i;
3059 static struct {
3060 int winx; int winy; int backx; int backy; DWORD flags;
3061 } scts[] = { /* scissor tests */
3062 {800, 600, 640, 480, 0},
3063 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3064 {640, 480, 800, 600, 0},
3065 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3068 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3069 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3071 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
3072 IDirect3DDevice9 *device_ptr = 0;
3073 HRESULT hr;
3074 HWND hwnd = 0;
3075 RECT scissorrect;
3077 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3078 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3080 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3082 scts[i].backx = registry_mode.dmPelsWidth;
3083 scts[i].backy = registry_mode.dmPelsHeight;
3086 device_desc.device_window = hwnd;
3087 device_desc.width = scts[i].backx;
3088 device_desc.height = scts[i].backy;
3089 device_desc.flags = scts[i].flags;
3090 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3092 skip("Failed to create a 3D device, skipping test.\n");
3093 DestroyWindow(hwnd);
3094 goto err_out;
3097 /* Check for the default scissor rect size */
3098 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3099 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3100 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3101 && scissorrect.top == 0 && scissorrect.left == 0,
3102 "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3103 scts[i].backx, scts[i].backy);
3105 /* check the scissorrect values after a reset */
3106 device_desc.width = registry_mode.dmPelsWidth;
3107 device_desc.height = registry_mode.dmPelsHeight;
3108 device_desc.flags = scts[i].flags;
3109 hr = reset_device(device_ptr, &device_desc);
3110 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3111 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3112 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3114 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3115 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3116 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3117 && scissorrect.top == 0 && scissorrect.left == 0,
3118 "Scissorrect missmatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3119 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3121 if(device_ptr) {
3122 ULONG ref;
3124 ref = IDirect3DDevice9_Release(device_ptr);
3125 DestroyWindow(hwnd);
3126 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3130 err_out:
3131 IDirect3D9_Release(d3d9_ptr);
3134 static void test_multi_device(void)
3136 IDirect3DDevice9 *device1, *device2;
3137 HWND window1, window2;
3138 IDirect3D9 *d3d9;
3139 ULONG refcount;
3141 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3142 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3143 ok(!!window1, "Failed to create a window.\n");
3144 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3145 ok(!!d3d9, "Failed to create a D3D object.\n");
3146 if (!(device1 = create_device(d3d9, window1, NULL)))
3148 skip("Failed to create a 3D device, skipping test.\n");
3149 IDirect3D9_Release(d3d9);
3150 DestroyWindow(window1);
3151 return;
3153 IDirect3D9_Release(d3d9);
3155 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3156 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3157 ok(!!window2, "Failed to create a window.\n");
3158 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3159 ok(!!d3d9, "Failed to create a D3D object.\n");
3160 device2 = create_device(d3d9, window2, NULL);
3161 IDirect3D9_Release(d3d9);
3163 refcount = IDirect3DDevice9_Release(device2);
3164 ok(!refcount, "Device has %u references left.\n", refcount);
3165 refcount = IDirect3DDevice9_Release(device1);
3166 ok(!refcount, "Device has %u references left.\n", refcount);
3167 DestroyWindow(window2);
3168 DestroyWindow(window1);
3171 static HWND filter_messages;
3173 enum message_window
3175 DEVICE_WINDOW,
3176 FOCUS_WINDOW,
3179 struct message
3181 UINT message;
3182 enum message_window window;
3183 BOOL check_wparam;
3184 WPARAM expect_wparam;
3187 static const struct message *expect_messages;
3188 static HWND device_window, focus_window;
3189 static LONG windowposchanged_received, syscommand_received;
3191 struct wndproc_thread_param
3193 HWND dummy_window;
3194 HANDLE window_created;
3195 HANDLE test_finished;
3196 BOOL running_in_foreground;
3199 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3201 if (filter_messages && filter_messages == hwnd)
3203 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3204 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3207 if (expect_messages)
3209 HWND w;
3211 switch (expect_messages->window)
3213 case DEVICE_WINDOW:
3214 w = device_window;
3215 break;
3217 case FOCUS_WINDOW:
3218 w = focus_window;
3219 break;
3221 default:
3222 w = NULL;
3223 break;
3226 if (hwnd == w && expect_messages->message == message)
3228 if (expect_messages->check_wparam)
3229 ok(wparam == expect_messages->expect_wparam,
3230 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3231 wparam, message, expect_messages->expect_wparam);
3233 ++expect_messages;
3237 /* KDE randomly does something with the hidden window during the
3238 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3239 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3240 * just flag WM_WINDOWPOSCHANGED as bad. */
3241 if (message == WM_WINDOWPOSCHANGED)
3242 InterlockedIncrement(&windowposchanged_received);
3243 else if (message == WM_SYSCOMMAND)
3244 InterlockedIncrement(&syscommand_received);
3246 return DefWindowProcA(hwnd, message, wparam, lparam);
3249 static DWORD WINAPI wndproc_thread(void *param)
3251 struct wndproc_thread_param *p = param;
3252 DWORD res;
3253 BOOL ret;
3255 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3256 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3257 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3258 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3260 ret = SetEvent(p->window_created);
3261 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3263 for (;;)
3265 MSG msg;
3267 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3268 res = WaitForSingleObject(p->test_finished, 100);
3269 if (res == WAIT_OBJECT_0) break;
3270 if (res != WAIT_TIMEOUT)
3272 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3273 break;
3277 DestroyWindow(p->dummy_window);
3279 return 0;
3282 static void test_wndproc(void)
3284 struct wndproc_thread_param thread_params;
3285 struct device_desc device_desc;
3286 IDirect3DDevice9 *device;
3287 WNDCLASSA wc = {0};
3288 IDirect3D9 *d3d9;
3289 HANDLE thread;
3290 LONG_PTR proc;
3291 ULONG ref;
3292 DWORD res, tid;
3293 HWND tmp;
3294 UINT i, adapter_mode_count;
3295 HRESULT hr;
3296 D3DDISPLAYMODE d3ddm;
3297 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3298 DEVMODEW devmode;
3299 LONG change_ret;
3300 BOOL ret;
3302 static const struct message create_messages[] =
3304 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3305 /* Do not test wparam here. If device creation succeeds,
3306 * wparam is WA_ACTIVE. If device creation fails (testbot)
3307 * wparam is set to WA_INACTIVE on some Windows versions. */
3308 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3309 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3310 {0, 0, FALSE, 0},
3312 static const struct message focus_loss_messages[] =
3314 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3315 * not reliable on X11 WMs. When the window focus follows the
3316 * mouse pointer the message is not sent.
3317 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3318 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3319 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3320 * not deterministic. */
3321 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3322 /* Windows sends WM_ACTIVATE to the device window, indicating that
3323 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3324 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3325 * leaves the device window active, breaking re-activation in the
3326 * lost device test.
3327 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3328 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3329 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3330 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3331 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3332 * not deterministic. It may be sent after the focus window handling
3333 * or before. */
3334 {0, 0, FALSE, 0},
3336 static const struct message focus_loss_messages_nowc[] =
3338 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3339 * not reliable on X11 WMs. When the window focus follows the
3340 * mouse pointer the message is not sent.
3341 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3342 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3343 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3344 {0, 0, FALSE, 0},
3346 static const struct message reactivate_messages[] =
3348 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3349 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3350 /* optional WM_MOVE here if size changed */
3351 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3352 {0, 0, FALSE, 0},
3354 static const struct message reactivate_messages_nowc[] =
3356 /* We're activating the device window before activating the
3357 * focus window, so no ACTIVATEAPP message is sent. */
3358 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3359 {0, 0, FALSE, 0},
3361 static const struct message focus_loss_messages_hidden[] =
3363 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3364 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3365 {0, 0, FALSE, 0},
3367 static const struct message focus_loss_messages_filtered[] =
3369 /* WM_ACTIVATE is delivered to the window proc because it is
3370 * generated by SetForegroundWindow before the d3d routine
3371 * starts it work. Don't check for it due to focus-follows-mouse
3372 * WMs though. */
3373 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3374 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3375 {0, 0, FALSE, 0},
3377 static const struct message reactivate_messages_filtered[] =
3379 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3380 {0, 0, FALSE, 0},
3382 static const struct message sc_restore_messages[] =
3384 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3385 * processed it. Our wndproc has no way to prevent d3d from
3386 * handling the message. The second DefWindowProc call done by
3387 * our wndproc doesn't do any changes to the window because it
3388 * is already restored due to d3d's handling. */
3389 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3390 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3391 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3392 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3393 {0, 0, FALSE, 0},
3395 static const struct message sc_minimize_messages[] =
3397 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3398 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3399 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3400 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3401 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3402 {0, 0, FALSE, 0},
3404 static const struct message sc_maximize_messages[] =
3406 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3407 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3408 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3409 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3410 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3411 {0, 0, FALSE, 0},
3413 static const struct
3415 DWORD create_flags;
3416 const struct message *focus_loss_messages, *reactivate_messages;
3417 BOOL iconic;
3419 tests[] =
3421 {0, focus_loss_messages, reactivate_messages, TRUE},
3422 {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, reactivate_messages_nowc, FALSE},
3425 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3426 ok(!!d3d9, "Failed to create a D3D object.\n");
3428 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3429 for (i = 0; i < adapter_mode_count; ++i)
3431 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3432 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3434 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3435 continue;
3436 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3437 * refuses to create a device at these sizes. */
3438 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3439 continue;
3441 if (!user32_width)
3443 user32_width = d3ddm.Width;
3444 user32_height = d3ddm.Height;
3445 continue;
3448 /* Make sure the d3d mode is smaller in width or height and at most
3449 * equal in the other dimension than the mode passed to
3450 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3451 * the ChangeDisplaySettings parameters + 12. */
3452 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3453 continue;
3454 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3456 d3d_width = d3ddm.Width;
3457 d3d_height = d3ddm.Height;
3458 break;
3460 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3462 d3d_width = user32_width;
3463 d3d_height = user32_height;
3464 user32_width = d3ddm.Width;
3465 user32_height = d3ddm.Height;
3466 break;
3470 if (!d3d_width)
3472 skip("Could not find adequate modes, skipping mode tests.\n");
3473 IDirect3D9_Release(d3d9);
3474 return;
3477 wc.lpfnWndProc = test_proc;
3478 wc.lpszClassName = "d3d9_test_wndproc_wc";
3479 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3481 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3482 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3483 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3484 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3486 memset(&devmode, 0, sizeof(devmode));
3487 devmode.dmSize = sizeof(devmode);
3488 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
3490 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3491 devmode.dmPelsWidth = user32_width;
3492 devmode.dmPelsHeight = user32_height;
3493 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3494 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3496 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3497 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3498 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3499 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3500 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3501 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3503 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3504 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3506 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3507 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3508 (LONG_PTR)test_proc, proc);
3509 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3510 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3511 (LONG_PTR)test_proc, proc);
3513 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3514 device_window, focus_window, thread_params.dummy_window);
3516 tmp = GetFocus();
3517 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3518 if (thread_params.running_in_foreground)
3520 tmp = GetForegroundWindow();
3521 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3522 thread_params.dummy_window, tmp);
3524 else
3525 skip("Not running in foreground, skip foreground window test\n");
3527 flush_events();
3529 expect_messages = create_messages;
3531 device_desc.device_window = device_window;
3532 device_desc.width = d3d_width;
3533 device_desc.height = d3d_height;
3534 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3535 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3537 skip("Failed to create a D3D device, skipping tests.\n");
3538 goto done;
3541 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3542 expect_messages->message, expect_messages->window, i);
3543 expect_messages = NULL;
3545 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3547 tmp = GetFocus();
3548 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3549 tmp = GetForegroundWindow();
3550 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3552 SetForegroundWindow(focus_window);
3553 flush_events();
3555 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3556 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3557 (LONG_PTR)test_proc, proc, i);
3559 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3560 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3561 (LONG_PTR)test_proc, i);
3563 /* Change the mode while the device is in use and then drop focus. */
3564 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3565 devmode.dmPelsWidth = user32_width;
3566 devmode.dmPelsHeight = user32_height;
3567 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3568 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3570 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3571 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3572 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3573 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3574 if (hr == D3DERR_DEVICENOTRESET)
3575 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3576 else
3577 todo_wine ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3579 expect_messages = tests[i].focus_loss_messages;
3580 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3581 * manually changing the focus. It generates the same messages, but the task
3582 * bar still shows the previous foreground window as active, and the window has
3583 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3584 * the device is difficult, see below. */
3585 SetForegroundWindow(GetDesktopWindow());
3586 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3587 expect_messages->message, expect_messages->window, i);
3588 expect_messages = NULL;
3589 tmp = GetFocus();
3590 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3591 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3593 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3594 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3596 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3597 ok(ret, "Failed to get display mode.\n");
3598 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3599 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3600 devmode.dmPelsWidth, devmode.dmPelsHeight);
3602 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3603 * done before the focus window is restored. This makes sense to some extent
3604 * because minimizing the window on focus loss is the application's job if this
3605 * flag is set. */
3606 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3608 ShowWindow(device_window, SW_MINIMIZE);
3609 ShowWindow(device_window, SW_RESTORE);
3611 flush_events();
3613 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3614 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3615 * restore is triggered by the user. */
3616 expect_messages = tests[i].reactivate_messages;
3617 ShowWindow(focus_window, SW_MINIMIZE);
3618 ShowWindow(focus_window, SW_RESTORE);
3619 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3620 SetForegroundWindow(focus_window);
3621 flush_events();
3622 SetForegroundWindow(focus_window);
3623 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3624 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3625 expect_messages->message, expect_messages->window, i);
3626 expect_messages = NULL;
3628 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3629 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3631 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3632 ok(ret, "Failed to get display mode.\n");
3633 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3634 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3635 devmode.dmPelsWidth, devmode.dmPelsHeight);
3637 hr = reset_device(device, &device_desc);
3638 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3640 ShowWindow(device_window, SW_HIDE);
3641 flush_events();
3643 expect_messages = focus_loss_messages_hidden;
3644 windowposchanged_received = 0;
3645 SetForegroundWindow(GetDesktopWindow());
3646 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3647 expect_messages->message, expect_messages->window, i);
3648 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3649 expect_messages = NULL;
3650 flush_events();
3652 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3653 ok(ret, "Failed to get display mode.\n");
3654 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3655 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3657 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3658 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3659 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3660 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3661 flush_events();
3663 syscommand_received = 0;
3664 expect_messages = sc_restore_messages;
3665 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3666 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3667 expect_messages->message, expect_messages->window, i);
3668 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3669 expect_messages = NULL;
3670 flush_events();
3672 expect_messages = sc_minimize_messages;
3673 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3674 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3675 expect_messages->message, expect_messages->window, i);
3676 expect_messages = NULL;
3677 flush_events();
3679 expect_messages = sc_maximize_messages;
3680 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3681 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3682 expect_messages->message, expect_messages->window, i);
3683 expect_messages = NULL;
3684 flush_events();
3686 SetForegroundWindow(GetDesktopWindow());
3687 ShowWindow(device_window, SW_MINIMIZE);
3688 ShowWindow(device_window, SW_RESTORE);
3689 ShowWindow(focus_window, SW_MINIMIZE);
3690 ShowWindow(focus_window, SW_RESTORE);
3691 SetForegroundWindow(focus_window);
3692 flush_events();
3694 /* Releasing a device in lost state breaks follow-up tests on native. */
3695 hr = reset_device(device, &device_desc);
3696 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3698 filter_messages = focus_window;
3700 ref = IDirect3DDevice9_Release(device);
3701 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3703 /* Fix up the mode until Wine's device release behavior is fixed. */
3704 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3705 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3707 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3708 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3709 (LONG_PTR)test_proc, proc, i);
3711 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3712 * on native in the test below. It isn't needed anyways. Creating the third
3713 * device will show it again. */
3714 filter_messages = NULL;
3715 ShowWindow(device_window, SW_HIDE);
3716 /* Remove the maximized state from the SYSCOMMAND test while we're not
3717 * interfering with a device. */
3718 ShowWindow(focus_window, SW_SHOWNORMAL);
3719 filter_messages = focus_window;
3721 device_desc.device_window = focus_window;
3722 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3724 skip("Failed to create a D3D device, skipping tests.\n");
3725 goto done;
3727 filter_messages = NULL;
3728 SetForegroundWindow(focus_window); /* For KDE. */
3729 flush_events();
3731 expect_messages = focus_loss_messages_filtered;
3732 windowposchanged_received = 0;
3733 SetForegroundWindow(GetDesktopWindow());
3734 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3735 expect_messages->message, expect_messages->window, i);
3736 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3737 expect_messages = NULL;
3739 /* The window is iconic even though no message was sent. */
3740 ok(!IsIconic(focus_window) == !tests[i].iconic,
3741 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
3743 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3744 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3746 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3747 ShowWindow(focus_window, SW_MINIMIZE);
3749 syscommand_received = 0;
3750 expect_messages = sc_restore_messages;
3751 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3752 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3753 expect_messages->message, expect_messages->window, i);
3754 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3755 expect_messages = NULL;
3756 flush_events();
3758 /* For FVWM. */
3759 ShowWindow(focus_window, SW_RESTORE);
3760 flush_events();
3762 expect_messages = sc_minimize_messages;
3763 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3764 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3765 expect_messages->message, expect_messages->window, i);
3766 expect_messages = NULL;
3767 flush_events();
3769 expect_messages = sc_maximize_messages;
3770 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3771 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3772 expect_messages->message, expect_messages->window, i);
3773 expect_messages = NULL;
3774 flush_events();
3776 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
3777 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
3778 SetForegroundWindow(GetDesktopWindow());
3779 flush_events();
3780 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
3781 flush_events();
3783 expect_messages = reactivate_messages_filtered;
3784 windowposchanged_received = 0;
3785 SetForegroundWindow(focus_window);
3786 flush_events();
3787 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3788 expect_messages->message, expect_messages->window, i);
3789 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
3790 ok(!windowposchanged_received || broken(1),
3791 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3792 expect_messages = NULL;
3794 filter_messages = focus_window;
3795 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3796 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3798 hr = reset_device(device, &device_desc);
3799 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3801 ref = IDirect3DDevice9_Release(device);
3802 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3804 device_desc.device_window = device_window;
3805 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3807 skip("Failed to create a D3D device, skipping tests.\n");
3808 goto done;
3811 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3812 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3813 (LONG_PTR)test_proc, i);
3815 ref = IDirect3DDevice9_Release(device);
3816 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3818 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3819 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3820 (LONG_PTR)DefWindowProcA, proc, i);
3822 done:
3823 filter_messages = NULL;
3824 DestroyWindow(device_window);
3825 DestroyWindow(focus_window);
3826 SetEvent(thread_params.test_finished);
3827 WaitForSingleObject(thread, INFINITE);
3828 CloseHandle(thread);
3831 IDirect3D9_Release(d3d9);
3832 CloseHandle(thread_params.test_finished);
3833 CloseHandle(thread_params.window_created);
3834 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3837 static void test_wndproc_windowed(void)
3839 struct wndproc_thread_param thread_params;
3840 struct device_desc device_desc;
3841 IDirect3DDevice9 *device;
3842 WNDCLASSA wc = {0};
3843 IDirect3D9 *d3d9;
3844 HANDLE thread;
3845 LONG_PTR proc;
3846 HRESULT hr;
3847 ULONG ref;
3848 DWORD res, tid;
3849 HWND tmp;
3851 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3852 ok(!!d3d9, "Failed to create a D3D object.\n");
3854 wc.lpfnWndProc = test_proc;
3855 wc.lpszClassName = "d3d9_test_wndproc_wc";
3856 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3858 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3859 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3860 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3861 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3863 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3864 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3865 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3866 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3867 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3868 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3869 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3870 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3872 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3873 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3875 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3876 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3877 (LONG_PTR)test_proc, proc);
3878 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3879 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3880 (LONG_PTR)test_proc, proc);
3882 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3883 device_window, focus_window, thread_params.dummy_window);
3885 tmp = GetFocus();
3886 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3887 if (thread_params.running_in_foreground)
3889 tmp = GetForegroundWindow();
3890 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3891 thread_params.dummy_window, tmp);
3893 else
3894 skip("Not running in foreground, skip foreground window test\n");
3896 filter_messages = focus_window;
3898 device_desc.device_window = device_window;
3899 device_desc.width = 640;
3900 device_desc.height = 480;
3901 device_desc.flags = 0;
3902 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3904 skip("Failed to create a D3D device, skipping tests.\n");
3905 goto done;
3908 tmp = GetFocus();
3909 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3910 tmp = GetForegroundWindow();
3911 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3912 thread_params.dummy_window, tmp);
3914 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3915 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3916 (LONG_PTR)test_proc, proc);
3918 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3919 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3920 (LONG_PTR)test_proc, proc);
3922 filter_messages = NULL;
3924 device_desc.width = registry_mode.dmPelsWidth;
3925 device_desc.height = registry_mode.dmPelsHeight;
3926 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3927 hr = reset_device(device, &device_desc);
3928 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3930 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3931 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3932 (LONG_PTR)test_proc, proc);
3934 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3935 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3937 device_desc.flags = 0;
3938 hr = reset_device(device, &device_desc);
3939 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3941 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3942 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3943 (LONG_PTR)test_proc, proc);
3945 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3946 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3947 (LONG_PTR)test_proc, proc);
3949 filter_messages = focus_window;
3951 ref = IDirect3DDevice9_Release(device);
3952 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3954 filter_messages = device_window;
3956 device_desc.device_window = focus_window;
3957 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3959 skip("Failed to create a D3D device, skipping tests.\n");
3960 goto done;
3963 filter_messages = NULL;
3965 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3966 hr = reset_device(device, &device_desc);
3967 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3969 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3970 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3971 (LONG_PTR)test_proc, proc);
3973 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3974 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3976 device_desc.flags = 0;
3977 hr = reset_device(device, &device_desc);
3978 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3980 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3981 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3982 (LONG_PTR)test_proc, proc);
3984 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3985 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3986 (LONG_PTR)test_proc, proc);
3988 filter_messages = device_window;
3990 ref = IDirect3DDevice9_Release(device);
3991 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3993 device_desc.device_window = device_window;
3994 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3996 skip("Failed to create a D3D device, skipping tests.\n");
3997 goto done;
4000 filter_messages = NULL;
4002 device_desc.device_window = device_window;
4003 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4004 hr = reset_device(device, &device_desc);
4005 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4007 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4008 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4009 (LONG_PTR)test_proc, proc);
4011 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4012 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4014 device_desc.flags = 0;
4015 hr = reset_device(device, &device_desc);
4016 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4018 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4019 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4020 (LONG_PTR)test_proc, proc);
4022 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4023 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4024 (LONG_PTR)test_proc, proc);
4026 filter_messages = device_window;
4028 ref = IDirect3DDevice9_Release(device);
4029 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4031 done:
4032 filter_messages = NULL;
4033 IDirect3D9_Release(d3d9);
4035 SetEvent(thread_params.test_finished);
4036 WaitForSingleObject(thread, INFINITE);
4037 CloseHandle(thread_params.test_finished);
4038 CloseHandle(thread_params.window_created);
4039 CloseHandle(thread);
4041 DestroyWindow(device_window);
4042 DestroyWindow(focus_window);
4043 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4046 static void test_reset_fullscreen(void)
4048 WNDCLASSEXA wc = {0};
4049 IDirect3DDevice9 *device = NULL;
4050 IDirect3D9 *d3d;
4051 ATOM atom;
4052 struct device_desc device_desc;
4053 static const struct message messages[] =
4055 /* Windows usually sends wparam = TRUE, except on the testbot,
4056 * where it randomly sends FALSE. Ignore it. */
4057 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4058 {0, 0, FALSE, 0},
4061 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4062 ok(!!d3d, "Failed to create a D3D object.\n");
4063 expect_messages = messages;
4065 wc.cbSize = sizeof(wc);
4066 wc.lpfnWndProc = test_proc;
4067 wc.lpszClassName = "test_reset_fullscreen";
4069 atom = RegisterClassExA(&wc);
4070 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4072 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4073 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4074 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4077 * Create a device in windowed mode.
4078 * Since the device is windowed and we haven't called any methods that
4079 * could show the window (such as ShowWindow or SetWindowPos) yet,
4080 * WM_ACTIVATEAPP will not have been sent.
4082 if (!(device = create_device(d3d, device_window, NULL)))
4084 skip("Unable to create device. Skipping test.\n");
4085 goto cleanup;
4089 * Switch to fullscreen mode.
4090 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4091 * message to be sent.
4093 device_desc.width = registry_mode.dmPelsWidth;
4094 device_desc.height = registry_mode.dmPelsHeight;
4095 device_desc.device_window = device_window;
4096 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4097 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4099 flush_events();
4100 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4101 expect_messages = NULL;
4103 cleanup:
4104 if (device) IDirect3DDevice9_Release(device);
4105 IDirect3D9_Release(d3d);
4106 DestroyWindow(device_window);
4107 device_window = focus_window = NULL;
4108 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4112 static inline void set_fpu_cw(WORD cw)
4114 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4115 #define D3D9_TEST_SET_FPU_CW 1
4116 __asm__ volatile ("fnclex");
4117 __asm__ volatile ("fldcw %0" : : "m" (cw));
4118 #elif defined(__i386__) && defined(_MSC_VER)
4119 #define D3D9_TEST_SET_FPU_CW 1
4120 __asm fnclex;
4121 __asm fldcw cw;
4122 #endif
4125 static inline WORD get_fpu_cw(void)
4127 WORD cw = 0;
4128 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4129 #define D3D9_TEST_GET_FPU_CW 1
4130 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4131 #elif defined(__i386__) && defined(_MSC_VER)
4132 #define D3D9_TEST_GET_FPU_CW 1
4133 __asm fnstcw cw;
4134 #endif
4135 return cw;
4138 static WORD callback_cw, callback_set_cw;
4139 static DWORD callback_tid;
4141 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4143 *out = NULL;
4144 return E_NOINTERFACE;
4147 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4149 callback_cw = get_fpu_cw();
4150 set_fpu_cw(callback_set_cw);
4151 callback_tid = GetCurrentThreadId();
4152 return 2;
4155 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4157 callback_cw = get_fpu_cw();
4158 set_fpu_cw(callback_set_cw);
4159 callback_tid = GetCurrentThreadId();
4160 return 1;
4163 static const IUnknownVtbl dummy_object_vtbl =
4165 dummy_object_QueryInterface,
4166 dummy_object_AddRef,
4167 dummy_object_Release,
4170 static const GUID d3d9_private_data_test_guid =
4172 0xfdb37466,
4173 0x428f,
4174 0x4edf,
4175 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4178 static void test_fpu_setup(void)
4180 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4181 struct device_desc device_desc;
4182 IDirect3DDevice9 *device;
4183 HWND window = NULL;
4184 IDirect3D9 *d3d9;
4185 WORD cw;
4186 IDirect3DSurface9 *surface;
4187 HRESULT hr;
4188 IUnknown dummy_object = {&dummy_object_vtbl};
4190 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4191 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4192 ok(!!window, "Failed to create a window.\n");
4193 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4194 ok(!!d3d9, "Failed to create a D3D object.\n");
4196 device_desc.device_window = window;
4197 device_desc.width = 640;
4198 device_desc.height = 480;
4199 device_desc.flags = 0;
4201 set_fpu_cw(0xf60);
4202 cw = get_fpu_cw();
4203 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4205 if (!(device = create_device(d3d9, window, &device_desc)))
4207 skip("Failed to create a 3D device, skipping test.\n");
4208 set_fpu_cw(0x37f);
4209 goto done;
4212 cw = get_fpu_cw();
4213 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4215 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4216 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4218 callback_set_cw = 0xf60;
4219 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4220 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4221 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4222 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4223 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4224 cw = get_fpu_cw();
4225 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4227 callback_cw = 0;
4228 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4229 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4230 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4231 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4232 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4234 callback_set_cw = 0x7f;
4235 set_fpu_cw(0x7f);
4237 IDirect3DSurface9_Release(surface);
4239 callback_cw = 0;
4240 IDirect3DDevice9_Release(device);
4241 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4242 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4244 cw = get_fpu_cw();
4245 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4246 set_fpu_cw(0xf60);
4247 cw = get_fpu_cw();
4248 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4250 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4251 device = create_device(d3d9, window, &device_desc);
4252 ok(device != NULL, "CreateDevice failed.\n");
4254 cw = get_fpu_cw();
4255 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4257 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4258 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4260 callback_cw = 0;
4261 callback_set_cw = 0x37f;
4262 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4263 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4264 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4265 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4266 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4267 cw = get_fpu_cw();
4268 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4270 IDirect3DSurface9_Release(surface);
4272 callback_cw = 0;
4273 IDirect3DDevice9_Release(device);
4274 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4275 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4277 done:
4278 IDirect3D9_Release(d3d9);
4279 DestroyWindow(window);
4280 #endif
4283 static void test_window_style(void)
4285 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4286 LONG device_style, device_exstyle;
4287 LONG focus_style, focus_exstyle;
4288 struct device_desc device_desc;
4289 LONG style, expected_style;
4290 IDirect3DDevice9 *device;
4291 IDirect3D9 *d3d9;
4292 HRESULT hr;
4293 ULONG ref;
4294 BOOL ret;
4295 static const struct
4297 DWORD device_flags;
4298 LONG style, focus_loss_style, exstyle;
4300 tests[] =
4302 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4303 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4305 unsigned int i;
4307 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4308 ok(!!d3d9, "Failed to create a D3D object.\n");
4309 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4311 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
4313 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4314 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4315 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4316 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4318 device_style = GetWindowLongA(device_window, GWL_STYLE);
4319 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4320 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4321 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4323 GetWindowRect(focus_window, &focus_rect);
4324 GetWindowRect(device_window, &device_rect);
4326 device_desc.device_window = device_window;
4327 device_desc.width = registry_mode.dmPelsWidth;
4328 device_desc.height = registry_mode.dmPelsHeight;
4329 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4330 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4332 skip("Failed to create a D3D device, skipping tests.\n");
4333 DestroyWindow(device_window);
4334 DestroyWindow(focus_window);
4335 break;
4338 style = GetWindowLongA(device_window, GWL_STYLE);
4339 expected_style = device_style | tests[i].style;
4340 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4341 expected_style, style, i);
4342 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4343 expected_style = device_exstyle | tests[i].exstyle;
4344 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4345 expected_style, style, i);
4347 style = GetWindowLongA(focus_window, GWL_STYLE);
4348 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4349 focus_style, style, i);
4350 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4351 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4352 focus_exstyle, style, i);
4354 GetWindowRect(device_window, &r);
4355 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4356 todo_wine ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}, i=%u.\n",
4357 device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
4358 r.left, r.top, r.right, r.bottom, i);
4359 else
4360 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}, i=%u.\n",
4361 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4362 r.left, r.top, r.right, r.bottom, i);
4363 GetClientRect(device_window, &r2);
4364 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4365 GetWindowRect(focus_window, &r);
4366 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}, i=%u.\n",
4367 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
4368 r.left, r.top, r.right, r.bottom, i);
4370 device_desc.flags = 0;
4371 hr = reset_device(device, &device_desc);
4372 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4374 style = GetWindowLongA(device_window, GWL_STYLE);
4375 expected_style = device_style | tests[i].style;
4376 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4377 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4378 expected_style, style, i);
4379 else
4380 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4381 expected_style, style, i);
4382 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4383 expected_style = device_exstyle | tests[i].exstyle;
4384 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4385 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4386 expected_style, style, i);
4387 else
4388 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4389 expected_style, style, i);
4391 style = GetWindowLongA(focus_window, GWL_STYLE);
4392 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4393 focus_style, style, i);
4394 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4395 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4396 focus_exstyle, style, i);
4398 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4399 hr = reset_device(device, &device_desc);
4400 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4401 ret = SetForegroundWindow(GetDesktopWindow());
4402 ok(ret, "Failed to set foreground window.\n");
4404 style = GetWindowLongA(device_window, GWL_STYLE);
4405 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4406 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4407 expected_style, style);
4408 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4409 expected_style = device_exstyle | tests[i].exstyle;
4410 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4411 expected_style, style);
4413 style = GetWindowLongA(focus_window, GWL_STYLE);
4414 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4415 focus_style, style);
4416 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4417 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4418 focus_exstyle, style);
4420 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4421 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4422 * like a good idea to reset it first. */
4423 ShowWindow(focus_window, SW_MINIMIZE);
4424 ShowWindow(focus_window, SW_RESTORE);
4425 ret = SetForegroundWindow(focus_window);
4426 ok(ret, "Failed to set foreground window.\n");
4427 flush_events();
4428 hr = reset_device(device, &device_desc);
4429 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4431 ref = IDirect3DDevice9_Release(device);
4432 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4434 DestroyWindow(device_window);
4435 DestroyWindow(focus_window);
4437 IDirect3D9_Release(d3d9);
4440 static const POINT *expect_pos;
4442 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4444 if (message == WM_MOUSEMOVE)
4446 if (expect_pos && expect_pos->x && expect_pos->y)
4448 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4450 ClientToScreen(window, &p);
4451 if (expect_pos->x == p.x && expect_pos->y == p.y)
4452 ++expect_pos;
4456 return DefWindowProcA(window, message, wparam, lparam);
4459 static void test_cursor_pos(void)
4461 IDirect3DSurface9 *cursor;
4462 IDirect3DDevice9 *device;
4463 WNDCLASSA wc = {0};
4464 IDirect3D9 *d3d9;
4465 UINT refcount;
4466 HWND window;
4467 HRESULT hr;
4468 BOOL ret;
4470 /* Note that we don't check for movement we're not supposed to receive.
4471 * That's because it's hard to distinguish from the user accidentally
4472 * moving the mouse. */
4473 static const POINT points[] =
4475 {50, 50},
4476 {75, 75},
4477 {100, 100},
4478 {125, 125},
4479 {150, 150},
4480 {125, 125},
4481 {150, 150},
4482 {150, 150},
4483 {0, 0},
4486 wc.lpfnWndProc = test_cursor_proc;
4487 wc.lpszClassName = "d3d9_test_cursor_wc";
4488 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4489 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4490 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4491 ShowWindow(window, SW_SHOW);
4492 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4493 ok(!!d3d9, "Failed to create a D3D object.\n");
4495 device = create_device(d3d9, window, NULL);
4496 if (!device)
4498 skip("Failed to create a D3D device, skipping tests.\n");
4499 goto done;
4502 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4503 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4504 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4505 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4506 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4507 IDirect3DSurface9_Release(cursor);
4508 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4509 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4511 flush_events();
4512 expect_pos = points;
4514 ret = SetCursorPos(50, 50);
4515 ok(ret, "Failed to set cursor position.\n");
4516 flush_events();
4518 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4519 flush_events();
4520 /* SetCursorPosition() eats duplicates. */
4521 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4522 flush_events();
4524 ret = SetCursorPos(100, 100);
4525 ok(ret, "Failed to set cursor position.\n");
4526 flush_events();
4527 /* Even if the position was set with SetCursorPos(). */
4528 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4529 flush_events();
4531 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4532 flush_events();
4533 ret = SetCursorPos(150, 150);
4534 ok(ret, "Failed to set cursor position.\n");
4535 flush_events();
4536 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4537 flush_events();
4539 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4540 flush_events();
4541 /* SetCursorPos() doesn't. */
4542 ret = SetCursorPos(150, 150);
4543 ok(ret, "Failed to set cursor position.\n");
4544 flush_events();
4546 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4547 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4549 refcount = IDirect3DDevice9_Release(device);
4550 ok(!refcount, "Device has %u references left.\n", refcount);
4551 done:
4552 DestroyWindow(window);
4553 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4554 IDirect3D9_Release(d3d9);
4557 static void test_mode_change(void)
4559 RECT d3d_rect, focus_rect, r;
4560 struct device_desc device_desc;
4561 IDirect3DSurface9 *backbuffer;
4562 IDirect3DDevice9 *device;
4563 D3DSURFACE_DESC desc;
4564 IDirect3D9 *d3d9;
4565 DEVMODEW devmode;
4566 ULONG refcount;
4567 UINT adapter_mode_count, i;
4568 HRESULT hr;
4569 DWORD ret;
4570 LONG change_ret;
4571 D3DDISPLAYMODE d3ddm;
4572 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4574 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4575 ok(!!d3d9, "Failed to create a D3D object.\n");
4577 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4578 for (i = 0; i < adapter_mode_count; ++i)
4580 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4581 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4583 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4584 continue;
4585 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4586 * refuses to create a device at these sizes. */
4587 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4588 continue;
4590 if (!user32_width)
4592 user32_width = d3ddm.Width;
4593 user32_height = d3ddm.Height;
4594 continue;
4597 /* Make sure the d3d mode is smaller in width or height and at most
4598 * equal in the other dimension than the mode passed to
4599 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4600 * the ChangeDisplaySettings parameters + 12. */
4601 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4602 continue;
4603 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4605 d3d_width = d3ddm.Width;
4606 d3d_height = d3ddm.Height;
4607 break;
4609 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4611 d3d_width = user32_width;
4612 d3d_height = user32_height;
4613 user32_width = d3ddm.Width;
4614 user32_height = d3ddm.Height;
4615 break;
4619 if (!d3d_width)
4621 skip("Could not find adequate modes, skipping mode tests.\n");
4622 IDirect3D9_Release(d3d9);
4623 return;
4626 memset(&devmode, 0, sizeof(devmode));
4627 devmode.dmSize = sizeof(devmode);
4628 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4629 devmode.dmPelsWidth = user32_width;
4630 devmode.dmPelsHeight = user32_height;
4631 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4632 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4634 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4635 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4636 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4637 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4639 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4640 GetWindowRect(focus_window, &focus_rect);
4642 device_desc.device_window = device_window;
4643 device_desc.width = d3d_width;
4644 device_desc.height = d3d_height;
4645 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4646 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4648 skip("Failed to create a D3D device, skipping tests.\n");
4649 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4650 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4651 goto done;
4654 devmode.dmPelsWidth = user32_width;
4655 devmode.dmPelsHeight = user32_height;
4656 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4657 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4659 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4660 ok(ret, "Failed to get display mode.\n");
4661 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4662 "Expected resolution %ux%u, got %ux%u.\n",
4663 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4665 GetWindowRect(device_window, &r);
4666 ok(EqualRect(&r, &d3d_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4667 d3d_rect.left, d3d_rect.top, d3d_rect.right, d3d_rect.bottom,
4668 r.left, r.top, r.right, r.bottom);
4669 GetWindowRect(focus_window, &r);
4670 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4671 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
4672 r.left, r.top, r.right, r.bottom);
4674 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4675 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
4676 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
4677 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
4678 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4679 desc.Width, d3d_width);
4680 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4681 desc.Height, d3d_height);
4682 IDirect3DSurface9_Release(backbuffer);
4684 refcount = IDirect3DDevice9_Release(device);
4685 ok(!refcount, "Device has %u references left.\n", refcount);
4687 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4688 ok(ret, "Failed to get display mode.\n");
4689 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4690 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4691 "Expected resolution %ux%u, got %ux%u.\n",
4692 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4694 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4695 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4697 /* The mode restore also happens when the device was created at the original screen size. */
4699 device_desc.device_window = device_window;
4700 device_desc.width = registry_mode.dmPelsWidth;
4701 device_desc.height = registry_mode.dmPelsHeight;
4702 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4703 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4705 devmode.dmPelsWidth = user32_width;
4706 devmode.dmPelsHeight = user32_height;
4707 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4708 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4710 refcount = IDirect3DDevice9_Release(device);
4711 ok(!refcount, "Device has %u references left.\n", refcount);
4713 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4714 ok(ret, "Failed to get display mode.\n");
4715 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4716 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4717 "Expected resolution %ux%u, got %ux%u.\n",
4718 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4720 done:
4721 DestroyWindow(device_window);
4722 DestroyWindow(focus_window);
4723 IDirect3D9_Release(d3d9);
4726 static void test_device_window_reset(void)
4728 RECT fullscreen_rect, device_rect, r;
4729 struct device_desc device_desc;
4730 IDirect3DDevice9 *device;
4731 WNDCLASSA wc = {0};
4732 IDirect3D9 *d3d9;
4733 LONG_PTR proc;
4734 HRESULT hr;
4735 ULONG ref;
4737 wc.lpfnWndProc = test_proc;
4738 wc.lpszClassName = "d3d9_test_wndproc_wc";
4739 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4741 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4742 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4743 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4744 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4745 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4746 ok(!!d3d9, "Failed to create a D3D object.\n");
4748 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4749 GetWindowRect(device_window, &device_rect);
4751 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4752 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4753 (LONG_PTR)test_proc, proc);
4754 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4755 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4756 (LONG_PTR)test_proc, proc);
4758 device_desc.device_window = NULL;
4759 device_desc.width = registry_mode.dmPelsWidth;
4760 device_desc.height = registry_mode.dmPelsHeight;
4761 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4762 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4764 skip("Failed to create a D3D device, skipping tests.\n");
4765 goto done;
4768 GetWindowRect(focus_window, &r);
4769 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4770 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4771 r.left, r.top, r.right, r.bottom);
4772 GetWindowRect(device_window, &r);
4773 ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4774 device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
4775 r.left, r.top, r.right, r.bottom);
4777 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4778 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4779 (LONG_PTR)test_proc, proc);
4780 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4781 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4783 device_desc.device_window = device_window;
4784 hr = reset_device(device, &device_desc);
4785 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4787 GetWindowRect(focus_window, &r);
4788 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4789 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4790 r.left, r.top, r.right, r.bottom);
4791 GetWindowRect(device_window, &r);
4792 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4793 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4794 r.left, r.top, r.right, r.bottom);
4796 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4797 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4798 (LONG_PTR)test_proc, proc);
4799 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4800 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4802 ref = IDirect3DDevice9_Release(device);
4803 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4805 done:
4806 IDirect3D9_Release(d3d9);
4807 DestroyWindow(device_window);
4808 DestroyWindow(focus_window);
4809 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4812 static void test_reset_resources(void)
4814 IDirect3DSurface9 *surface, *rt;
4815 IDirect3DTexture9 *texture;
4816 IDirect3DDevice9 *device;
4817 IDirect3D9 *d3d9;
4818 unsigned int i;
4819 D3DCAPS9 caps;
4820 HWND window;
4821 HRESULT hr;
4822 ULONG ref;
4824 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
4825 0, 0, 640, 480, 0, 0, 0, 0);
4826 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4827 ok(!!d3d9, "Failed to create a D3D object.\n");
4829 if (!(device = create_device(d3d9, window, NULL)))
4831 skip("Failed to create a D3D device, skipping tests.\n");
4832 goto done;
4835 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4836 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4838 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
4839 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
4840 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
4841 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
4842 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
4843 IDirect3DSurface9_Release(surface);
4845 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
4847 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
4848 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4849 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
4850 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4851 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
4852 IDirect3DTexture9_Release(texture);
4853 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
4854 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
4855 IDirect3DSurface9_Release(surface);
4858 hr = reset_device(device, NULL);
4859 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4861 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
4862 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
4863 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4864 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4865 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
4866 IDirect3DSurface9_Release(surface);
4867 IDirect3DSurface9_Release(rt);
4869 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
4871 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
4872 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4875 ref = IDirect3DDevice9_Release(device);
4876 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4878 done:
4879 IDirect3D9_Release(d3d9);
4880 DestroyWindow(window);
4883 static void test_set_rt_vp_scissor(void)
4885 IDirect3DStateBlock9 *stateblock;
4886 IDirect3DDevice9 *device;
4887 IDirect3DSurface9 *rt;
4888 IDirect3D9 *d3d9;
4889 D3DVIEWPORT9 vp;
4890 UINT refcount;
4891 HWND window;
4892 HRESULT hr;
4893 RECT rect;
4895 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
4896 0, 0, 640, 480, 0, 0, 0, 0);
4897 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4898 ok(!!d3d9, "Failed to create a D3D object.\n");
4899 if (!(device = create_device(d3d9, window, NULL)))
4901 skip("Failed to create a D3D device, skipping tests.\n");
4902 DestroyWindow(window);
4903 return;
4906 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
4907 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
4908 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4910 hr = IDirect3DDevice9_GetViewport(device, &vp);
4911 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4912 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4913 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4914 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
4915 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
4916 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4917 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4919 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4920 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4921 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
4922 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4923 rect.left, rect.top, rect.right, rect.bottom);
4925 hr = IDirect3DDevice9_BeginStateBlock(device);
4926 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
4928 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4929 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4931 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
4932 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
4933 IDirect3DStateBlock9_Release(stateblock);
4935 hr = IDirect3DDevice9_GetViewport(device, &vp);
4936 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4937 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4938 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4939 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4940 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4941 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4942 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4944 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4945 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4946 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
4947 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4948 rect.left, rect.top, rect.right, rect.bottom);
4950 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4951 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4953 vp.X = 10;
4954 vp.Y = 20;
4955 vp.Width = 30;
4956 vp.Height = 40;
4957 vp.MinZ = 0.25f;
4958 vp.MaxZ = 0.75f;
4959 hr = IDirect3DDevice9_SetViewport(device, &vp);
4960 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
4962 SetRect(&rect, 50, 60, 70, 80);
4963 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
4964 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
4966 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4967 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4969 hr = IDirect3DDevice9_GetViewport(device, &vp);
4970 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4971 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4972 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4973 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4974 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4975 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4976 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4978 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4979 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4980 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
4981 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4982 rect.left, rect.top, rect.right, rect.bottom);
4984 IDirect3DSurface9_Release(rt);
4985 refcount = IDirect3DDevice9_Release(device);
4986 ok(!refcount, "Device has %u references left.\n", refcount);
4987 IDirect3D9_Release(d3d9);
4988 DestroyWindow(window);
4991 static void test_volume_get_container(void)
4993 IDirect3DVolumeTexture9 *texture = NULL;
4994 IDirect3DVolume9 *volume = NULL;
4995 IDirect3DDevice9 *device;
4996 IUnknown *container;
4997 IDirect3D9 *d3d9;
4998 ULONG refcount;
4999 D3DCAPS9 caps;
5000 HWND window;
5001 HRESULT hr;
5003 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5004 0, 0, 640, 480, 0, 0, 0, 0);
5005 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5006 ok(!!d3d9, "Failed to create a D3D object.\n");
5007 if (!(device = create_device(d3d9, window, NULL)))
5009 skip("Failed to create a D3D device, skipping tests.\n");
5010 IDirect3D9_Release(d3d9);
5011 DestroyWindow(window);
5012 return;
5015 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5016 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5017 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5019 skip("No volume texture support, skipping tests.\n");
5020 IDirect3DDevice9_Release(device);
5021 IDirect3D9_Release(d3d9);
5022 DestroyWindow(window);
5023 return;
5026 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5027 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5028 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5029 ok(!!texture, "Got unexpected texture %p.\n", texture);
5031 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5032 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5033 ok(!!volume, "Got unexpected volume %p.\n", volume);
5035 /* These should work... */
5036 container = NULL;
5037 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5038 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5039 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5040 IUnknown_Release(container);
5042 container = NULL;
5043 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5044 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5045 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5046 IUnknown_Release(container);
5048 container = NULL;
5049 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5050 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5051 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5052 IUnknown_Release(container);
5054 container = NULL;
5055 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5056 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5057 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5058 IUnknown_Release(container);
5060 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5061 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5062 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5063 ok(!container, "Got unexpected container %p.\n", container);
5065 IDirect3DVolume9_Release(volume);
5066 IDirect3DVolumeTexture9_Release(texture);
5067 refcount = IDirect3DDevice9_Release(device);
5068 ok(!refcount, "Device has %u references left.\n", refcount);
5069 IDirect3D9_Release(d3d9);
5070 DestroyWindow(window);
5073 static void test_volume_resource(void)
5075 IDirect3DVolumeTexture9 *texture;
5076 IDirect3DResource9 *resource;
5077 IDirect3DVolume9 *volume;
5078 IDirect3DDevice9 *device;
5079 IDirect3D9 *d3d9;
5080 ULONG refcount;
5081 D3DCAPS9 caps;
5082 HWND window;
5083 HRESULT hr;
5085 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5086 0, 0, 640, 480, 0, 0, 0, 0);
5087 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5088 ok(!!d3d9, "Failed to create a D3D object.\n");
5089 if (!(device = create_device(d3d9, window, NULL)))
5091 skip("Failed to create a D3D device, skipping tests.\n");
5092 IDirect3D9_Release(d3d9);
5093 DestroyWindow(window);
5094 return;
5097 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5098 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5099 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5101 skip("No volume texture support, skipping tests.\n");
5102 IDirect3DDevice9_Release(device);
5103 IDirect3D9_Release(d3d9);
5104 DestroyWindow(window);
5105 return;
5108 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5109 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5110 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5111 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5112 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5113 IDirect3DVolumeTexture9_Release(texture);
5115 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5116 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5118 IDirect3DVolume9_Release(volume);
5119 refcount = IDirect3DDevice9_Release(device);
5120 ok(!refcount, "Device has %u references left.\n", refcount);
5121 IDirect3D9_Release(d3d9);
5122 DestroyWindow(window);
5125 static void test_vb_lock_flags(void)
5127 static const struct
5129 DWORD flags;
5130 const char *debug_string;
5131 HRESULT win7_result;
5133 test_data[] =
5135 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5136 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5137 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5138 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5139 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5140 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5141 /* Completely bogus flags aren't an error. */
5142 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5144 IDirect3DVertexBuffer9 *buffer;
5145 IDirect3DDevice9 *device;
5146 IDirect3D9 *d3d9;
5147 unsigned int i;
5148 ULONG refcount;
5149 HWND window;
5150 HRESULT hr;
5151 void *data;
5153 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5154 0, 0, 640, 480, 0, 0, 0, 0);
5155 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5156 ok(!!d3d9, "Failed to create a D3D object.\n");
5157 if (!(device = create_device(d3d9, window, NULL)))
5159 skip("Failed to create a D3D device, skipping tests.\n");
5160 IDirect3D9_Release(d3d9);
5161 DestroyWindow(window);
5162 return;
5165 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5166 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5168 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5170 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5171 /* Windows XP always returns D3D_OK even with flags that don't make
5172 * sense. Windows 7 returns an error. At least one game (Shaiya)
5173 * depends on the Windows XP result, so mark the Windows 7 behavior as
5174 * broken. */
5175 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5176 hr, test_data[i].debug_string);
5177 if (SUCCEEDED(hr))
5179 ok(!!data, "Got unexpected data %p.\n", data);
5180 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5181 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5185 IDirect3DVertexBuffer9_Release(buffer);
5186 refcount = IDirect3DDevice9_Release(device);
5187 ok(!refcount, "Device has %u references left.\n", refcount);
5188 IDirect3D9_Release(d3d9);
5189 DestroyWindow(window);
5192 static const char *debug_d3dpool(D3DPOOL pool)
5194 switch (pool)
5196 case D3DPOOL_DEFAULT:
5197 return "D3DPOOL_DEFAULT";
5198 case D3DPOOL_SYSTEMMEM:
5199 return "D3DPOOL_SYSTEMMEM";
5200 case D3DPOOL_SCRATCH:
5201 return "D3DPOOL_SCRATCH";
5202 case D3DPOOL_MANAGED:
5203 return "D3DPOOL_MANAGED";
5204 default:
5205 return "unknown pool";
5209 static void test_vertex_buffer_alignment(void)
5211 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5212 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5213 IDirect3DVertexBuffer9 *buffer = NULL;
5214 const unsigned int align = 16;
5215 IDirect3DDevice9 *device;
5216 unsigned int i, j;
5217 IDirect3D9 *d3d9;
5218 ULONG refcount;
5219 HWND window;
5220 HRESULT hr;
5221 void *data;
5223 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5224 0, 0, 640, 480, 0, 0, 0, 0);
5225 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5226 ok(!!d3d9, "Failed to create a D3D object.\n");
5227 if (!(device = create_device(d3d9, window, NULL)))
5229 skip("Failed to create a D3D device, skipping tests.\n");
5230 IDirect3D9_Release(d3d9);
5231 DestroyWindow(window);
5232 return;
5235 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
5237 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5239 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5240 if (pools[j] == D3DPOOL_SCRATCH)
5241 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5242 else
5243 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5244 debug_d3dpool(pools[j]), sizes[i], hr);
5245 if (FAILED(hr))
5246 continue;
5248 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5249 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5250 ok(!((DWORD_PTR)data & (align - 1)),
5251 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5252 data, align, sizes[i], debug_d3dpool(pools[j]));
5253 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5254 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5255 IDirect3DVertexBuffer9_Release(buffer);
5259 refcount = IDirect3DDevice9_Release(device);
5260 ok(!refcount, "Device has %u references left.\n", refcount);
5261 IDirect3D9_Release(d3d9);
5262 DestroyWindow(window);
5265 static void test_query_support(void)
5267 static const D3DQUERYTYPE queries[] =
5269 D3DQUERYTYPE_VCACHE,
5270 D3DQUERYTYPE_RESOURCEMANAGER,
5271 D3DQUERYTYPE_VERTEXSTATS,
5272 D3DQUERYTYPE_EVENT,
5273 D3DQUERYTYPE_OCCLUSION,
5274 D3DQUERYTYPE_TIMESTAMP,
5275 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5276 D3DQUERYTYPE_TIMESTAMPFREQ,
5277 D3DQUERYTYPE_PIPELINETIMINGS,
5278 D3DQUERYTYPE_INTERFACETIMINGS,
5279 D3DQUERYTYPE_VERTEXTIMINGS,
5280 D3DQUERYTYPE_PIXELTIMINGS,
5281 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5282 D3DQUERYTYPE_CACHEUTILIZATION,
5284 IDirect3DQuery9 *query = NULL;
5285 IDirect3DDevice9 *device;
5286 IDirect3D9 *d3d9;
5287 unsigned int i;
5288 ULONG refcount;
5289 BOOL supported;
5290 HWND window;
5291 HRESULT hr;
5293 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5294 0, 0, 640, 480, 0, 0, 0, 0);
5295 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5296 ok(!!d3d9, "Failed to create a D3D object.\n");
5297 if (!(device = create_device(d3d9, window, NULL)))
5299 skip("Failed to create a D3D device, skipping tests.\n");
5300 IDirect3D9_Release(d3d9);
5301 DestroyWindow(window);
5302 return;
5305 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
5307 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5308 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5310 supported = hr == D3D_OK;
5312 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5313 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5315 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5316 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5318 if (query)
5320 IDirect3DQuery9_Release(query);
5321 query = NULL;
5325 refcount = IDirect3DDevice9_Release(device);
5326 ok(!refcount, "Device has %u references left.\n", refcount);
5327 IDirect3D9_Release(d3d9);
5328 DestroyWindow(window);
5331 static void test_occlusion_query_states(void)
5333 static const float quad[] =
5335 -1.0f, -1.0f, 0.0f,
5336 -1.0f, 1.0f, 0.0f,
5337 1.0f, 1.0f, 0.0f,
5338 1.0f, -1.0f, 0.0f,
5340 struct device_desc device_desc;
5341 IDirect3DQuery9 *query = NULL;
5342 unsigned int data_size, i;
5343 IDirect3DDevice9 *device;
5344 IDirect3D9 *d3d9;
5345 ULONG refcount;
5346 HWND window;
5347 HRESULT hr;
5348 union
5350 WORD word[4];
5351 DWORD dword[2];
5352 } data;
5353 BOOL broken_occlusion = FALSE;
5354 DWORD expected = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5356 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5357 0, 0, 640, 480, 0, 0, 0, 0);
5358 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5359 ok(!!d3d9, "Failed to create a D3D object.\n");
5360 device_desc.device_window = window;
5361 device_desc.width = registry_mode.dmPelsWidth;
5362 device_desc.height = registry_mode.dmPelsHeight;
5363 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5364 if (!(device = create_device(d3d9, window, &device_desc)))
5366 skip("Failed to create a D3D device, skipping tests.\n");
5367 IDirect3D9_Release(d3d9);
5368 DestroyWindow(window);
5369 return;
5372 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5373 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5374 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5375 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5376 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5377 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5379 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5380 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5381 if (!query)
5383 skip("Occlusion queries are not supported, skipping tests.\n");
5384 IDirect3DDevice9_Release(device);
5385 IDirect3D9_Release(d3d9);
5386 DestroyWindow(window);
5387 return;
5390 data_size = IDirect3DQuery9_GetDataSize(query);
5391 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5393 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5394 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5395 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5396 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5398 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5399 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5400 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5401 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5402 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5403 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5405 data.dword[0] = 0x12345678;
5406 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5407 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5408 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5409 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5410 if (hr == D3D_OK)
5411 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5413 hr = IDirect3DDevice9_BeginScene(device);
5414 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5415 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5416 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5417 hr = IDirect3DDevice9_EndScene(device);
5418 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5420 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5421 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5422 for (i = 0; i < 500; ++i)
5424 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5425 break;
5426 Sleep(10);
5428 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5430 memset(&data, 0xff, sizeof(data));
5431 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5432 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5433 ok(data.dword[0] == expected || broken(!data.dword[0]),
5434 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5435 if (!data.dword[0])
5437 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5438 broken_occlusion = TRUE;
5441 memset(&data, 0xff, sizeof(data));
5442 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5443 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5444 if (!broken_occlusion)
5445 ok(data.word[0] == (WORD)expected,
5446 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5447 ok(data.word[1] == 0xffff,
5448 "data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5450 memset(&data, 0xf0, sizeof(data));
5451 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5452 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5453 if (!broken_occlusion)
5454 ok(data.dword[0] == expected,
5455 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5456 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5457 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5458 on AMD and Nvidia respectively). */
5459 if (0)
5461 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5462 data.dword[1]);
5465 memset(&data, 0xff, sizeof(data));
5466 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5467 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5468 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5470 /* This crashes on Windows. */
5471 if (0)
5473 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5474 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5477 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5478 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5479 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5480 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5481 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5482 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5484 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5486 IDirect3DQuery9_Release(query);
5487 refcount = IDirect3DDevice9_Release(device);
5488 ok(!refcount, "Device has %u references left.\n", refcount);
5489 IDirect3D9_Release(d3d9);
5490 DestroyWindow(window);
5493 static void test_timestamp_query(void)
5495 static const float quad[] =
5497 -1.0f, -1.0f, 0.0f,
5498 -1.0f, 1.0f, 0.0f,
5499 1.0f, 1.0f, 0.0f,
5500 1.0f, -1.0f, 0.0f,
5502 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5503 unsigned int data_size, i;
5504 IDirect3DDevice9 *device;
5505 IDirect3D9 *d3d9;
5506 ULONG refcount;
5507 HWND window;
5508 HRESULT hr;
5509 DWORD timestamp[2], freq[2];
5510 WORD disjoint[2];
5512 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5513 0, 0, 640, 480, 0, 0, 0, 0);
5514 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5515 ok(!!d3d9, "Failed to create a D3D object.\n");
5516 if (!(device = create_device(d3d9, window, NULL)))
5518 skip("Failed to create a D3D device, skipping tests.\n");
5519 IDirect3D9_Release(d3d9);
5520 DestroyWindow(window);
5521 return;
5524 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5525 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5526 if (FAILED(hr))
5528 skip("Timestamp queries are not supported, skipping tests.\n");
5529 IDirect3DDevice9_Release(device);
5530 IDirect3D9_Release(d3d9);
5531 DestroyWindow(window);
5532 return;
5534 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5535 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5537 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5538 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5539 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5540 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5542 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
5543 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5544 data_size = IDirect3DQuery9_GetDataSize(query);
5545 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5547 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
5548 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5549 for (i = 0; i < 500; ++i)
5551 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5552 break;
5553 Sleep(10);
5555 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5557 memset(freq, 0xff, sizeof(freq));
5558 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5559 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5560 ok(freq[1] == 0xffffffff,
5561 "freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
5562 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
5563 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5564 ok(freq[1] != 0xffffffff, "high bytes of freq were not modified (0x%.8x).\n",
5565 freq[1]);
5567 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5568 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5569 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5570 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5572 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5573 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5574 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5575 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5576 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5577 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5579 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5580 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5582 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5583 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5584 hr = IDirect3DDevice9_BeginScene(device);
5585 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5586 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5587 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5588 hr = IDirect3DDevice9_EndScene(device);
5589 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5591 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5592 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5593 for (i = 0; i < 500; ++i)
5595 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5596 break;
5597 Sleep(10);
5599 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5601 memset(timestamp, 0xff, sizeof(timestamp));
5602 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5603 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5604 ok(timestamp[1] == 0xffffffff,
5605 "timestamp was modified outside of the expected size (0x%.8x).\n",
5606 timestamp[1]);
5608 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5609 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5610 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5611 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5612 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5613 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5615 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5616 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5617 for (i = 0; i < 500; ++i)
5619 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5620 break;
5621 Sleep(10);
5623 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5625 memset(disjoint, 0xff, sizeof(disjoint));
5626 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5627 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5628 ok(disjoint[1] == 0xffff,
5629 "disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
5630 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
5631 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5632 ok(disjoint[1] != 0xffff, "high bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
5634 /* It's not strictly necessary for the TIMESTAMP query to be inside
5635 * a TIMESTAMP_DISJOINT query. */
5636 hr = IDirect3DDevice9_BeginScene(device);
5637 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5638 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5639 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5640 hr = IDirect3DDevice9_EndScene(device);
5641 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5643 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5644 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5645 for (i = 0; i < 500; ++i)
5647 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5648 break;
5649 Sleep(10);
5651 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5652 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5653 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5655 IDirect3DQuery9_Release(query);
5656 IDirect3DQuery9_Release(disjoint_query);
5657 IDirect3DQuery9_Release(freq_query);
5658 refcount = IDirect3DDevice9_Release(device);
5659 ok(!refcount, "Device has %u references left.\n", refcount);
5660 IDirect3D9_Release(d3d9);
5661 DestroyWindow(window);
5664 static void test_get_set_vertex_shader(void)
5666 IDirect3DVertexShader9 *current_shader = NULL;
5667 IDirect3DVertexShader9 *shader = NULL;
5668 const IDirect3DVertexShader9Vtbl *shader_vtbl;
5669 IDirect3DDevice9 *device;
5670 ULONG refcount, i;
5671 IDirect3D9 *d3d;
5672 D3DCAPS9 caps;
5673 HWND window;
5674 HRESULT hr;
5676 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5677 0, 0, 640, 480, 0, 0, 0, 0);
5678 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5679 ok(!!d3d, "Failed to create a D3D object.\n");
5680 if (!(device = create_device(d3d, window, NULL)))
5682 skip("Failed to create a D3D device, skipping tests.\n");
5683 IDirect3D9_Release(d3d);
5684 DestroyWindow(window);
5685 return;
5688 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5689 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5690 if (!(caps.VertexShaderVersion & 0xffff))
5692 skip("No vertex shader support, skipping tests.\n");
5693 IDirect3DDevice9_Release(device);
5694 IDirect3D9_Release(d3d);
5695 DestroyWindow(window);
5696 return;
5699 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
5700 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5701 ok(!!shader, "Got unexpected shader %p.\n", shader);
5703 /* SetVertexShader() should not touch the shader's refcount. */
5704 i = get_refcount((IUnknown *)shader);
5705 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5706 refcount = get_refcount((IUnknown *)shader);
5707 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5708 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5710 /* GetVertexShader() should increase the shader's refcount by one. */
5711 i = refcount + 1;
5712 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
5713 refcount = get_refcount((IUnknown *)shader);
5714 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
5715 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5716 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
5717 IDirect3DVertexShader9_Release(current_shader);
5719 /* SetVertexShader() with a bogus shader vtbl */
5720 shader_vtbl = shader->lpVtbl;
5721 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
5722 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5723 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5724 shader->lpVtbl = NULL;
5725 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5726 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5727 shader->lpVtbl = shader_vtbl;
5729 IDirect3DVertexShader9_Release(shader);
5730 refcount = IDirect3DDevice9_Release(device);
5731 ok(!refcount, "Device has %u references left.\n", refcount);
5732 IDirect3D9_Release(d3d);
5733 DestroyWindow(window);
5736 static void test_vertex_shader_constant(void)
5738 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};
5739 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
5740 IDirect3DDevice9 *device;
5741 IDirect3D9 *d3d;
5742 ULONG refcount;
5743 D3DCAPS9 caps;
5744 DWORD consts;
5745 HWND window;
5746 HRESULT hr;
5748 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5749 0, 0, 640, 480, 0, 0, 0, 0);
5750 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5751 ok(!!d3d, "Failed to create a D3D object.\n");
5752 if (!(device = create_device(d3d, window, NULL)))
5754 skip("Failed to create a D3D device, skipping tests.\n");
5755 IDirect3D9_Release(d3d);
5756 DestroyWindow(window);
5757 return;
5760 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5761 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5762 if (!(caps.VertexShaderVersion & 0xffff))
5764 skip("No vertex shader support, skipping tests.\n");
5765 IDirect3DDevice9_Release(device);
5766 IDirect3D9_Release(d3d);
5767 DestroyWindow(window);
5768 return;
5770 consts = caps.MaxVertexShaderConst;
5772 /* A simple check that the stuff works at all. */
5773 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
5774 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5776 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
5777 * consts from MAX - 1. */
5778 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
5779 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5780 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
5781 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5782 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
5783 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5784 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
5785 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5787 /* Constant -1. */
5788 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
5789 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5791 refcount = IDirect3DDevice9_Release(device);
5792 ok(!refcount, "Device has %u references left.\n", refcount);
5793 IDirect3D9_Release(d3d);
5794 DestroyWindow(window);
5797 static void test_get_set_pixel_shader(void)
5799 IDirect3DPixelShader9 *current_shader = NULL;
5800 IDirect3DPixelShader9 *shader = NULL;
5801 const IDirect3DPixelShader9Vtbl *shader_vtbl;
5802 IDirect3DDevice9 *device;
5803 ULONG refcount, i;
5804 IDirect3D9 *d3d;
5805 D3DCAPS9 caps;
5806 HWND window;
5807 HRESULT hr;
5809 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5810 0, 0, 640, 480, 0, 0, 0, 0);
5811 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5812 ok(!!d3d, "Failed to create a D3D object.\n");
5813 if (!(device = create_device(d3d, window, NULL)))
5815 skip("Failed to create a D3D device, skipping tests.\n");
5816 IDirect3D9_Release(d3d);
5817 DestroyWindow(window);
5818 return;
5821 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5822 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5823 if (!(caps.PixelShaderVersion & 0xffff))
5825 skip("No pixel shader support, skipping tests.\n");
5826 IDirect3DDevice9_Release(device);
5827 IDirect3D9_Release(d3d);
5828 DestroyWindow(window);
5829 return;
5832 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
5833 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5834 ok(!!shader, "Got unexpected shader %p.\n", shader);
5836 /* SetPixelShader() should not touch the shader's refcount. */
5837 i = get_refcount((IUnknown *)shader);
5838 hr = IDirect3DDevice9_SetPixelShader(device, shader);
5839 refcount = get_refcount((IUnknown *)shader);
5840 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
5841 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5843 /* GetPixelShader() should increase the shader's refcount by one. */
5844 i = refcount + 1;
5845 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
5846 refcount = get_refcount((IUnknown *)shader);
5847 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
5848 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5849 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
5850 IDirect3DPixelShader9_Release(current_shader);
5852 /* SetPixelShader() with a bogus shader vtbl */
5853 shader_vtbl = shader->lpVtbl;
5854 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
5855 hr = IDirect3DDevice9_SetPixelShader(device, shader);
5856 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
5857 shader->lpVtbl = NULL;
5858 hr = IDirect3DDevice9_SetPixelShader(device, shader);
5859 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
5860 shader->lpVtbl = shader_vtbl;
5862 IDirect3DPixelShader9_Release(shader);
5863 refcount = IDirect3DDevice9_Release(device);
5864 ok(!refcount, "Device has %u references left.\n", refcount);
5865 IDirect3D9_Release(d3d);
5866 DestroyWindow(window);
5869 static void test_pixel_shader_constant(void)
5871 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};
5872 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
5873 IDirect3DDevice9 *device;
5874 DWORD consts = 0;
5875 IDirect3D9 *d3d;
5876 ULONG refcount;
5877 D3DCAPS9 caps;
5878 HWND window;
5879 HRESULT hr;
5881 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5882 0, 0, 640, 480, 0, 0, 0, 0);
5883 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5884 ok(!!d3d, "Failed to create a D3D object.\n");
5885 if (!(device = create_device(d3d, window, NULL)))
5887 skip("Failed to create a D3D device, skipping tests.\n");
5888 IDirect3D9_Release(d3d);
5889 DestroyWindow(window);
5890 return;
5893 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5894 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5895 if (!(caps.PixelShaderVersion & 0xffff))
5897 skip("No pixel shader support, skipping tests.\n");
5898 IDirect3DDevice9_Release(device);
5899 IDirect3D9_Release(d3d);
5900 DestroyWindow(window);
5901 return;
5904 /* A simple check that the stuff works at all. */
5905 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
5906 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5908 /* Is there really no max pixel shader constant value??? Test how far I can go. */
5909 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
5910 consts = consts - 1;
5911 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
5913 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
5914 * pointless given the way the constant limit was determined. */
5915 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
5916 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5918 /* Constant -1. */
5919 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
5920 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5922 refcount = IDirect3DDevice9_Release(device);
5923 ok(!refcount, "Device has %u references left.\n", refcount);
5924 IDirect3D9_Release(d3d);
5925 DestroyWindow(window);
5928 static void test_unsupported_shaders(void)
5930 static const DWORD vs_3_0[] =
5932 0xfffe0300, /* vs_3_0 */
5933 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
5934 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
5935 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
5936 0x0000ffff, /* end */
5939 #if 0
5940 float4 main(const float4 color : COLOR) : SV_TARGET
5942 float4 o;
5944 o = color;
5946 return o;
5948 #endif
5949 static const DWORD ps_4_0[] =
5951 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
5952 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
5953 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
5954 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
5955 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
5956 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
5957 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
5958 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
5959 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
5960 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
5961 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
5962 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
5963 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
5964 0x00000000, 0x00000000, 0x00000000,
5966 #if 0
5967 vs_1_1
5968 dcl_position v0
5969 def c255, 1.0, 1.0, 1.0, 1.0
5970 add r0, v0, c255
5971 mov oPos, r0
5972 #endif
5973 static const DWORD vs_1_255[] =
5975 0xfffe0101,
5976 0x0000001f, 0x80000000, 0x900f0000,
5977 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
5978 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
5979 0x00000001, 0xc00f0000, 0x80e40000,
5980 0x0000ffff
5982 #if 0
5983 vs_1_1
5984 dcl_position v0
5985 def c256, 1.0, 1.0, 1.0, 1.0
5986 add r0, v0, c256
5987 mov oPos, r0
5988 #endif
5989 static const DWORD vs_1_256[] =
5991 0xfffe0101,
5992 0x0000001f, 0x80000000, 0x900f0000,
5993 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
5994 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
5995 0x00000001, 0xc00f0000, 0x80e40000,
5996 0x0000ffff
5998 #if 0
5999 vs_3_0
6000 dcl_position v0
6001 dcl_position o0
6002 def c256, 1.0, 1.0, 1.0, 1.0
6003 add r0, v0, c256
6004 mov o0, r0
6005 #endif
6006 static const DWORD vs_3_256[] =
6008 0xfffe0300,
6009 0x0200001f, 0x80000000, 0x900f0000,
6010 0x0200001f, 0x80000000, 0xe00f0000,
6011 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6012 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6013 0x02000001, 0xe00f0000, 0x80e40000,
6014 0x0000ffff
6016 #if 0
6017 /* This shader source generates syntax errors with the native shader assembler
6018 * due to the constant register index values.
6019 * The bytecode was modified by hand to use the intended values. */
6020 vs_3_0
6021 dcl_position v0
6022 dcl_position o0
6023 defi i16, 1, 1, 1, 1
6024 rep i16
6025 add r0, r0, v0
6026 endrep
6027 mov o0, r0
6028 #endif
6029 static const DWORD vs_3_i16[] =
6031 0xfffe0300,
6032 0x0200001f, 0x80000000, 0x900f0000,
6033 0x0200001f, 0x80000000, 0xe00f0000,
6034 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6035 0x01000026, 0xf0e40010,
6036 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6037 0x00000027,
6038 0x02000001, 0xe00f0000, 0x80e40000,
6039 0x0000ffff
6041 #if 0
6042 /* This shader source generates syntax errors with the native shader assembler
6043 * due to the constant register index values.
6044 * The bytecode was modified by hand to use the intended values. */
6045 vs_3_0
6046 dcl_position v0
6047 dcl_position o0
6048 defb b16, true
6049 mov r0, v0
6050 if b16
6051 add r0, r0, v0
6052 endif
6053 mov o0, r0
6054 #endif
6055 static const DWORD vs_3_b16[] =
6057 0xfffe0300,
6058 0x0200001f, 0x80000000, 0x900f0000,
6059 0x0200001f, 0x80000000, 0xe00f0000,
6060 0x0200002f, 0xe00f0810, 0x00000001,
6061 0x02000001, 0x800f0000, 0x90e40000,
6062 0x01000028, 0xe0e40810,
6063 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6064 0x0000002b,
6065 0x02000001, 0xe00f0000, 0x80e40000,
6066 0x0000ffff
6068 #if 0
6069 /* This shader source generates syntax errors with the native shader assembler
6070 * due to the constant register index values.
6071 * The bytecode was modified by hand to use the intended values. */
6072 ps_1_1
6073 def c8, 1.0, 1.0, 1.0, 1.0
6074 add r0, v0, c8
6075 #endif
6076 static const DWORD ps_1_8[] =
6078 0xffff0101,
6079 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6080 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6081 0x0000ffff
6083 #if 0
6084 /* This shader source generates syntax errors with the native shader assembler
6085 * due to the constant register index values.
6086 * The bytecode was modified by hand to use the intended values. */
6087 ps_2_0
6088 def c32, 1.0, 1.0, 1.0, 1.0
6089 add oC0, v0, c32
6090 #endif
6091 static const DWORD ps_2_32[] =
6093 0xffff0200,
6094 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6095 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6096 0x0000ffff
6098 #if 0
6099 /* This shader source generates syntax errors with the native shader assembler
6100 * due to the constant register index values.
6101 * The bytecode was modified by hand to use the intended values. */
6102 ps_3_0
6103 dcl_color0 v0
6104 def c224, 1.0, 1.0, 1.0, 1.0
6105 add oC0, v0, c224
6106 #endif
6107 static const DWORD ps_3_224[] =
6109 0xffff0300,
6110 0x0200001f, 0x8000000a, 0x900f0000,
6111 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6112 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6113 0x0000ffff
6115 #if 0
6116 /* This shader source generates syntax errors with the native shader assembler
6117 * due to the constant register index values.
6118 * The bytecode was modified by hand to use the intended values. */
6119 ps_2_0
6120 defb b0, true
6121 defi i0, 1, 1, 1, 1
6122 rep i0
6123 if b0
6124 add r0, r0, v0
6125 endif
6126 endrep
6127 mov oC0, r0
6128 #endif
6129 static const DWORD ps_2_0_boolint[] =
6131 0xffff0200,
6132 0x0200002f, 0xe00f0800, 0x00000001,
6133 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6134 0x01000026, 0xf0e40000,
6135 0x01000028, 0xe0e40800,
6136 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6137 0x0000002b,
6138 0x00000027,
6139 0x02000001, 0x800f0800, 0x80e40000,
6140 0x0000ffff
6143 IDirect3DVertexShader9 *vs = NULL;
6144 IDirect3DPixelShader9 *ps = NULL;
6145 IDirect3DDevice9 *device;
6146 IDirect3D9 * d3d;
6147 ULONG refcount;
6148 D3DCAPS9 caps;
6149 HWND window;
6150 HRESULT hr;
6152 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6153 0, 0, 640, 480, 0, 0, 0, 0);
6154 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6155 ok(!!d3d, "Failed to create a D3D object.\n");
6156 if (!(device = create_device(d3d, window, NULL)))
6158 skip("Failed to create a D3D device, skipping tests.\n");
6159 IDirect3D9_Release(d3d);
6160 DestroyWindow(window);
6161 return;
6164 /* These should always fail, regardless of supported shader version. */
6165 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6166 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6167 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6168 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6169 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6170 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6172 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6173 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6174 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6176 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6177 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6178 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6180 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6181 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6183 else
6185 skip("GPU supports SM2+, skipping SM1 test.\n");
6188 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6190 else
6192 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6194 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6195 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6196 IDirect3DVertexShader9_Release(vs);
6197 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6198 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6199 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6200 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6201 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6202 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6203 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6204 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6207 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6209 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6210 goto cleanup;
6212 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6213 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6214 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6215 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6216 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6217 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6218 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6219 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6220 if (ps)
6221 IDirect3DPixelShader9_Release(ps);
6223 cleanup:
6224 refcount = IDirect3DDevice9_Release(device);
6225 ok(!refcount, "Device has %u references left.\n", refcount);
6226 IDirect3D9_Release(d3d);
6227 DestroyWindow(window);
6230 /* Test the default texture stage state values */
6231 static void test_texture_stage_states(void)
6233 IDirect3DDevice9 *device;
6234 IDirect3D9 *d3d;
6235 unsigned int i;
6236 ULONG refcount;
6237 D3DCAPS9 caps;
6238 DWORD value;
6239 HWND window;
6240 HRESULT hr;
6242 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6243 0, 0, 640, 480, 0, 0, 0, 0);
6244 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6245 ok(!!d3d, "Failed to create a D3D object.\n");
6246 if (!(device = create_device(d3d, window, NULL)))
6248 skip("Failed to create a D3D device, skipping tests.\n");
6249 IDirect3D9_Release(d3d);
6250 DestroyWindow(window);
6251 return;
6254 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6255 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6257 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6259 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6260 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6261 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6262 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6263 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6264 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6265 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6266 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6267 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6268 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6269 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6270 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6271 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6272 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6273 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6274 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6275 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6276 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6277 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6278 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6279 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6280 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6281 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6282 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6283 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6284 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6285 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6286 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6287 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6288 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6289 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6290 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6291 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6292 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6293 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6294 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6295 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6296 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6297 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6298 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6299 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6300 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6301 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6302 ok(value == D3DTTFF_DISABLE,
6303 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6304 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6305 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6306 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6307 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6308 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6309 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6310 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6311 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6312 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6313 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6314 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6315 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6318 refcount = IDirect3DDevice9_Release(device);
6319 ok(!refcount, "Device has %u references left.\n", refcount);
6320 IDirect3D9_Release(d3d);
6321 DestroyWindow(window);
6324 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6326 IDirect3DCubeTexture9 *texture;
6327 IDirect3D9 *d3d;
6328 HRESULT hr;
6330 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6331 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6332 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6333 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6334 IDirect3D9_Release(d3d);
6335 if (FAILED(hr))
6337 skip("No cube mipmap generation support, skipping tests.\n");
6338 return;
6341 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6342 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6343 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6344 IDirect3DCubeTexture9_Release(texture);
6346 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6347 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6348 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6349 IDirect3DCubeTexture9_Release(texture);
6352 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6354 IDirect3DCubeTexture9 *texture;
6355 IDirect3DSurface9 *surface;
6356 D3DSURFACE_DESC desc;
6357 DWORD levels;
6358 HRESULT hr;
6359 D3DCAPS9 caps;
6361 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6362 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6363 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6364 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6366 skip("Failed to create cube texture, skipping tests.\n");
6367 return;
6370 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6371 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6372 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6373 else
6374 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6376 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6377 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6378 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6379 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6380 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6381 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6383 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6384 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6385 IDirect3DSurface9_Release(surface);
6386 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6387 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6388 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6389 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6391 IDirect3DCubeTexture9_Release(texture);
6394 static void test_cube_textures(void)
6396 IDirect3DCubeTexture9 *texture;
6397 IDirect3DDevice9 *device;
6398 IDirect3D9 *d3d;
6399 ULONG refcount;
6400 D3DCAPS9 caps;
6401 HWND window;
6402 HRESULT hr;
6404 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6405 0, 0, 640, 480, 0, 0, 0, 0);
6406 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6407 ok(!!d3d, "Failed to create a D3D object.\n");
6408 if (!(device = create_device(d3d, window, NULL)))
6410 skip("Failed to create a D3D device, skipping tests.\n");
6411 IDirect3D9_Release(d3d);
6412 DestroyWindow(window);
6413 return;
6416 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6417 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6419 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
6421 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6422 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
6423 IDirect3DCubeTexture9_Release(texture);
6424 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6425 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
6426 IDirect3DCubeTexture9_Release(texture);
6427 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6428 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
6429 IDirect3DCubeTexture9_Release(texture);
6431 else
6433 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6434 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
6435 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6436 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
6437 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6438 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
6440 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
6441 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
6442 IDirect3DCubeTexture9_Release(texture);
6444 test_cube_texture_mipmap_gen(device);
6445 test_cube_texture_levels(device);
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_mipmap_gen(void)
6455 D3DTEXTUREFILTERTYPE filter_type;
6456 IDirect3DTexture9 *texture;
6457 IDirect3DSurface9 *surface;
6458 IDirect3DDevice9 *device;
6459 D3DSURFACE_DESC desc;
6460 D3DLOCKED_RECT lr;
6461 IDirect3D9 *d3d;
6462 ULONG refcount;
6463 unsigned int i;
6464 DWORD levels;
6465 HWND window;
6466 HRESULT hr;
6468 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6469 ok(!!d3d, "Failed to create a D3D object.\n");
6471 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6472 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
6474 skip("No mipmap generation support, skipping tests.\n");
6475 IDirect3D9_Release(d3d);
6476 return;
6479 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6480 0, 0, 640, 480, 0, 0, 0, 0);
6481 if (!(device = create_device(d3d, window, NULL)))
6483 skip("Failed to create a D3D device, skipping tests.\n");
6484 IDirect3D9_Release(d3d);
6485 DestroyWindow(window);
6486 return;
6489 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6490 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6491 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6492 IDirect3DTexture9_Release(texture);
6494 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6495 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6496 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6498 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6499 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
6500 "Got unexpected filter_type %#x.\n", filter_type);
6501 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
6502 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6503 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
6504 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6505 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6506 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
6507 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
6508 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6510 levels = IDirect3DTexture9_GetLevelCount(texture);
6511 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6513 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
6515 surface = NULL;
6516 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
6517 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6518 if (surface)
6519 IDirect3DSurface9_Release(surface);
6521 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
6522 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6524 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
6525 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6526 if (SUCCEEDED(hr))
6528 hr = IDirect3DTexture9_UnlockRect(texture, i);
6529 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
6532 IDirect3DTexture9_Release(texture);
6534 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
6535 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6536 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6537 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
6538 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6539 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6541 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
6542 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6543 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6544 levels = IDirect3DTexture9_GetLevelCount(texture);
6545 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6546 IDirect3DTexture9_Release(texture);
6548 refcount = IDirect3DDevice9_Release(device);
6549 ok(!refcount, "Device has %u references left.\n", refcount);
6550 IDirect3D9_Release(d3d);
6551 DestroyWindow(window);
6554 static void test_filter(void)
6556 static const struct
6558 DWORD magfilter, minfilter, mipfilter;
6559 BOOL has_texture;
6560 HRESULT result;
6562 tests[] =
6564 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6565 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6566 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6567 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
6568 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
6570 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6571 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6572 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
6573 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
6575 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6576 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6577 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
6578 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
6579 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
6581 IDirect3DTexture9 *texture;
6582 IDirect3DDevice9 *device;
6583 IDirect3D9 *d3d;
6584 unsigned int i;
6585 ULONG refcount;
6586 DWORD passes;
6587 HWND window;
6588 HRESULT hr;
6590 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6591 ok(!!d3d, "Failed to create a D3D object.\n");
6593 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6594 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6596 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
6597 IDirect3D9_Release(d3d);
6598 return;
6601 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6602 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6604 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
6605 IDirect3D9_Release(d3d);
6606 return;
6609 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6610 0, 0, 640, 480, 0, 0, 0, 0);
6611 if (!(device = create_device(d3d, window, NULL)))
6613 skip("Failed to create a D3D device, skipping tests.\n");
6614 IDirect3D9_Release(d3d);
6615 DestroyWindow(window);
6616 return;
6619 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
6620 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
6621 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6623 /* Needed for ValidateDevice(). */
6624 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6625 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6627 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
6629 if (tests[i].has_texture)
6631 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
6632 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6634 else
6636 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6637 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6640 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
6641 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6642 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
6643 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6644 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
6645 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6647 passes = 0xdeadbeef;
6648 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
6649 ok(hr == tests[i].result,
6650 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
6651 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
6652 tests[i].mipfilter, tests[i].has_texture);
6653 if (SUCCEEDED(hr))
6654 ok(!!passes, "Got unexpected passes %#x.\n", passes);
6655 else
6656 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
6659 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6660 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6661 IDirect3DTexture9_Release(texture);
6663 refcount = IDirect3DDevice9_Release(device);
6664 ok(!refcount, "Device has %u references left.\n", refcount);
6665 IDirect3D9_Release(d3d);
6666 DestroyWindow(window);
6669 static void test_get_set_texture(void)
6671 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
6672 IDirect3DBaseTexture9 *texture;
6673 IDirect3DDevice9 *device;
6674 IDirect3D9 *d3d;
6675 ULONG refcount;
6676 HWND window;
6677 HRESULT hr;
6679 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6680 0, 0, 640, 480, 0, 0, 0, 0);
6681 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6682 ok(!!d3d, "Failed to create a D3D object.\n");
6683 if (!(device = create_device(d3d, window, NULL)))
6685 skip("Failed to create a D3D device, skipping tests.\n");
6686 IDirect3D9_Release(d3d);
6687 DestroyWindow(window);
6688 return;
6691 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
6692 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6693 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6694 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
6695 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6696 ok(!texture, "Got unexpected texture %p.\n", texture);
6698 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
6699 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
6700 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6701 texture_vtbl = texture->lpVtbl;
6702 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
6703 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6704 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6705 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6706 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6707 texture->lpVtbl = NULL;
6708 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6709 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6710 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6711 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6712 texture->lpVtbl = texture_vtbl;
6713 IDirect3DBaseTexture9_Release(texture);
6715 refcount = IDirect3DDevice9_Release(device);
6716 ok(!refcount, "Device has %u references left.\n", refcount);
6717 IDirect3D9_Release(d3d);
6718 DestroyWindow(window);
6721 static void test_lod(void)
6723 IDirect3DTexture9 *texture;
6724 IDirect3DDevice9 *device;
6725 IDirect3D9 *d3d;
6726 ULONG refcount;
6727 HWND window;
6728 HRESULT hr;
6729 DWORD ret;
6731 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6732 0, 0, 640, 480, 0, 0, 0, 0);
6733 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6734 ok(!!d3d, "Failed to create a D3D object.\n");
6735 if (!(device = create_device(d3d, window, NULL)))
6737 skip("Failed to create a D3D device, skipping tests.\n");
6738 IDirect3D9_Release(d3d);
6739 DestroyWindow(window);
6740 return;
6743 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
6744 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6745 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6747 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
6748 * return a HRESULT, so it can't return a normal error. Instead, the call
6749 * is simply ignored. */
6750 ret = IDirect3DTexture9_SetLOD(texture, 0);
6751 ok(!ret, "Got unexpected ret %u.\n", ret);
6752 ret = IDirect3DTexture9_SetLOD(texture, 1);
6753 ok(!ret, "Got unexpected ret %u.\n", ret);
6754 ret = IDirect3DTexture9_SetLOD(texture, 2);
6755 ok(!ret, "Got unexpected ret %u.\n", ret);
6756 ret = IDirect3DTexture9_GetLOD(texture);
6757 ok(!ret, "Got unexpected ret %u.\n", ret);
6759 IDirect3DTexture9_Release(texture);
6760 refcount = IDirect3DDevice9_Release(device);
6761 ok(!refcount, "Device has %u references left.\n", refcount);
6762 IDirect3D9_Release(d3d);
6763 DestroyWindow(window);
6766 static void test_surface_get_container(void)
6768 IDirect3DTexture9 *texture = NULL;
6769 IDirect3DSurface9 *surface = NULL;
6770 IDirect3DDevice9 *device;
6771 IUnknown *container;
6772 IDirect3D9 *d3d;
6773 ULONG refcount;
6774 HWND window;
6775 HRESULT hr;
6777 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6778 0, 0, 640, 480, 0, 0, 0, 0);
6779 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6780 ok(!!d3d, "Failed to create a D3D object.\n");
6781 if (!(device = create_device(d3d, window, NULL)))
6783 skip("Failed to create a D3D device, skipping tests.\n");
6784 IDirect3D9_Release(d3d);
6785 DestroyWindow(window);
6786 return;
6789 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
6790 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6791 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6792 ok(!!texture, "Got unexpected texture %p.\n", texture);
6794 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6795 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
6796 ok(!!surface, "Got unexpected surface %p.\n", surface);
6798 /* These should work... */
6799 container = NULL;
6800 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
6801 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6802 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6803 IUnknown_Release(container);
6805 container = NULL;
6806 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
6807 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6808 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6809 IUnknown_Release(container);
6811 container = NULL;
6812 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
6813 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6814 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6815 IUnknown_Release(container);
6817 container = NULL;
6818 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
6819 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6820 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6821 IUnknown_Release(container);
6823 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
6824 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
6825 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
6826 ok(!container, "Got unexpected container %p.\n", container);
6828 IDirect3DSurface9_Release(surface);
6829 IDirect3DTexture9_Release(texture);
6830 refcount = IDirect3DDevice9_Release(device);
6831 ok(!refcount, "Device has %u references left.\n", refcount);
6832 IDirect3D9_Release(d3d);
6833 DestroyWindow(window);
6836 static void test_surface_alignment(void)
6838 IDirect3DSurface9 *surface;
6839 IDirect3DDevice9 *device;
6840 D3DLOCKED_RECT lr;
6841 unsigned int i, j;
6842 IDirect3D9 *d3d;
6843 ULONG refcount;
6844 HWND window;
6845 HRESULT hr;
6847 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6848 0, 0, 640, 480, 0, 0, 0, 0);
6849 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6850 ok(!!d3d, "Failed to create a D3D object.\n");
6851 if (!(device = create_device(d3d, window, NULL)))
6853 skip("Failed to create a D3D device, skipping tests.\n");
6854 IDirect3D9_Release(d3d);
6855 DestroyWindow(window);
6856 return;
6859 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
6860 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
6861 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
6862 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6864 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
6865 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6866 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
6867 /* Some applications also depend on the exact pitch, rather than just the
6868 * alignment. */
6869 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
6870 hr = IDirect3DSurface9_UnlockRect(surface);
6871 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6872 IDirect3DSurface9_Release(surface);
6874 for (i = 0; i < 5; ++i)
6876 IDirect3DTexture9 *texture;
6877 unsigned int level_count;
6878 D3DSURFACE_DESC desc;
6879 int expected_pitch;
6881 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
6882 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
6883 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6884 if (FAILED(hr))
6886 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
6887 continue;
6890 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
6891 for (j = 0; j < level_count; ++j)
6893 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
6894 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
6895 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
6896 hr = IDirect3DTexture9_UnlockRect(texture, j);
6897 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
6899 expected_pitch = ((desc.Width + 3) >> 2) << 3;
6900 if (i > 0)
6901 expected_pitch <<= 1;
6902 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
6903 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
6905 IDirect3DTexture9_Release(texture);
6908 refcount = IDirect3DDevice9_Release(device);
6909 ok(!refcount, "Device has %u references left.\n", refcount);
6910 IDirect3D9_Release(d3d);
6911 DestroyWindow(window);
6914 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
6915 * different from regular formats. This test verifies we return the correct
6916 * memory offsets. */
6917 static void test_lockrect_offset(void)
6919 static const struct
6921 D3DFORMAT format;
6922 const char *name;
6923 unsigned int block_width;
6924 unsigned int block_height;
6925 unsigned int block_size;
6927 dxt_formats[] =
6929 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
6930 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
6931 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
6932 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
6933 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
6934 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
6935 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
6937 unsigned int expected_offset, offset, i;
6938 const RECT rect = {60, 60, 68, 68};
6939 IDirect3DSurface9 *surface;
6940 D3DLOCKED_RECT locked_rect;
6941 IDirect3DDevice9 *device;
6942 int expected_pitch;
6943 IDirect3D9 *d3d;
6944 ULONG refcount;
6945 HWND window;
6946 BYTE *base;
6947 HRESULT hr;
6949 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6950 0, 0, 640, 480, 0, 0, 0, 0);
6951 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6952 ok(!!d3d, "Failed to create a D3D object.\n");
6953 if (!(device = create_device(d3d, window, NULL)))
6955 skip("Failed to create a D3D device, skipping tests.\n");
6956 IDirect3D9_Release(d3d);
6957 DestroyWindow(window);
6958 return;
6961 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
6963 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6964 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
6966 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
6967 continue;
6970 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6971 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
6972 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6974 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
6975 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6977 base = locked_rect.pBits;
6978 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
6979 * dxt_formats[i].block_size;
6980 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
6981 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
6983 hr = IDirect3DSurface9_UnlockRect(surface);
6984 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6986 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6987 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6989 offset = (BYTE *)locked_rect.pBits - base;
6990 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
6991 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
6992 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
6993 offset, dxt_formats[i].name, expected_offset);
6995 hr = IDirect3DSurface9_UnlockRect(surface);
6996 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6998 IDirect3DSurface9_Release(surface);
7001 refcount = IDirect3DDevice9_Release(device);
7002 ok(!refcount, "Device has %u references left.\n", refcount);
7003 IDirect3D9_Release(d3d);
7004 DestroyWindow(window);
7007 static void test_lockrect_invalid(void)
7009 static const struct
7011 RECT rect;
7012 HRESULT win7_result;
7014 test_data[] =
7016 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7017 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7018 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7019 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7020 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7021 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7022 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7023 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7024 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7025 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7026 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7027 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7028 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7030 static const RECT test_rect_2 = {0, 0, 8, 8};
7031 IDirect3DSurface9 *surface = NULL;
7032 D3DLOCKED_RECT locked_rect;
7033 IDirect3DDevice9 *device;
7034 IDirect3D9 *d3d;
7035 unsigned int i;
7036 ULONG refcount;
7037 HWND window;
7038 BYTE *base;
7039 HRESULT hr;
7041 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7042 0, 0, 640, 480, 0, 0, 0, 0);
7043 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7044 ok(!!d3d, "Failed to create a D3D object.\n");
7045 if (!(device = create_device(d3d, window, NULL)))
7047 skip("Failed to create a D3D device, skipping tests.\n");
7048 IDirect3D9_Release(d3d);
7049 DestroyWindow(window);
7050 return;
7053 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7054 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7055 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7056 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7057 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7058 base = locked_rect.pBits;
7059 hr = IDirect3DSurface9_UnlockRect(surface);
7060 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7062 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
7064 unsigned int offset, expected_offset;
7065 const RECT *rect = &test_data[i].rect;
7067 locked_rect.pBits = (BYTE *)0xdeadbeef;
7068 locked_rect.Pitch = 0xdeadbeef;
7070 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7071 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7072 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7073 * one broken. */
7074 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7075 "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x.\n",
7076 rect->left, rect->top, rect->right, rect->bottom, hr);
7077 if (FAILED(hr))
7078 continue;
7080 offset = (BYTE *)locked_rect.pBits - base;
7081 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7082 ok(offset == expected_offset,
7083 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d].\n",
7084 offset, expected_offset, rect->left, rect->top, rect->right, rect->bottom);
7086 hr = IDirect3DSurface9_UnlockRect(surface);
7087 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7090 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7091 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x.\n", hr);
7092 locked_rect.pBits = (BYTE *)0xdeadbeef;
7093 locked_rect.Pitch = 1;
7094 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7095 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7096 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p\n",
7097 locked_rect.pBits);
7098 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d\n", locked_rect.Pitch);
7099 hr = IDirect3DSurface9_UnlockRect(surface);
7100 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7102 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7103 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
7104 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
7105 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7106 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
7107 hr, test_data[0].rect.left, test_data[0].rect.top, test_data[0].rect.right, test_data[0].rect.bottom);
7108 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7109 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d].\n",
7110 hr, test_rect_2.left, test_rect_2.top, test_rect_2.right, test_rect_2.bottom);
7111 hr = IDirect3DSurface9_UnlockRect(surface);
7112 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7114 IDirect3DSurface9_Release(surface);
7115 refcount = IDirect3DDevice9_Release(device);
7116 ok(!refcount, "Device has %u references left.\n", refcount);
7117 IDirect3D9_Release(d3d);
7118 DestroyWindow(window);
7121 static void test_private_data(void)
7123 ULONG refcount, expected_refcount;
7124 IDirect3DTexture9 *texture;
7125 IDirect3DSurface9 *surface, *surface2;
7126 IDirect3DDevice9 *device;
7127 IDirect3D9 *d3d;
7128 IUnknown *ptr;
7129 HWND window;
7130 HRESULT hr;
7131 DWORD size;
7132 DWORD data[4] = {1, 2, 3, 4};
7133 static const GUID d3d9_private_data_test_guid2 =
7135 0x2e5afac2,
7136 0x87b5,
7137 0x4c10,
7138 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7141 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7142 0, 0, 640, 480, 0, 0, 0, 0);
7143 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7144 ok(!!d3d, "Failed to create a D3D object.\n");
7145 if (!(device = create_device(d3d, window, NULL)))
7147 skip("Failed to create a D3D device, skipping tests.\n");
7148 IDirect3D9_Release(d3d);
7149 DestroyWindow(window);
7150 return;
7153 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7154 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7155 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7157 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7158 device, 0, D3DSPD_IUNKNOWN);
7159 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7160 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7161 device, 5, D3DSPD_IUNKNOWN);
7162 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7163 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7164 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7165 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7167 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7168 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7169 sizeof(device), D3DSPD_IUNKNOWN);
7170 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7171 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7172 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7173 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7174 size = sizeof(ptr);
7175 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7176 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7177 IUnknown_Release(ptr);
7178 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7179 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7181 refcount = get_refcount((IUnknown *)device);
7182 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7183 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7184 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7185 expected_refcount = refcount + 1;
7186 refcount = get_refcount((IUnknown *)device);
7187 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7188 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7189 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7190 expected_refcount = refcount - 1;
7191 refcount = get_refcount((IUnknown *)device);
7192 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7194 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7195 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7196 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7197 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7198 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7199 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7200 refcount = get_refcount((IUnknown *)device);
7201 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7203 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7204 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7205 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7206 size = 2 * sizeof(ptr);
7207 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7208 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7209 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7210 expected_refcount = refcount + 2;
7211 refcount = get_refcount((IUnknown *)device);
7212 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7213 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
7214 IUnknown_Release(ptr);
7215 expected_refcount--;
7217 ptr = (IUnknown *)0xdeadbeef;
7218 size = 1;
7219 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7220 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7221 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7222 size = 2 * sizeof(ptr);
7223 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7224 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7225 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7226 refcount = get_refcount((IUnknown *)device);
7227 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7228 size = 1;
7229 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7230 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7231 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7232 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7233 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
7234 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7235 size = 0xdeadbabe;
7236 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
7237 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7238 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7239 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7240 /* GetPrivateData with size = NULL causes an access violation on Windows if the
7241 * requested data exists. */
7243 /* Destroying the surface frees the held reference. */
7244 IDirect3DSurface9_Release(surface);
7245 expected_refcount = refcount - 2;
7246 refcount = get_refcount((IUnknown *)device);
7247 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7249 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
7250 &texture, NULL);
7251 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7252 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7253 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
7254 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
7255 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
7257 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7258 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7260 memset(data, 0, sizeof(data));
7261 size = sizeof(data);
7262 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
7263 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7264 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
7265 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7266 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
7267 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
7269 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
7270 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7272 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7273 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7274 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
7275 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7277 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7278 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7280 IDirect3DSurface9_Release(surface2);
7281 IDirect3DSurface9_Release(surface);
7282 IDirect3DTexture9_Release(texture);
7284 refcount = IDirect3DDevice9_Release(device);
7285 ok(!refcount, "Device has %u references left.\n", refcount);
7286 IDirect3D9_Release(d3d);
7287 DestroyWindow(window);
7290 static void test_getdc(void)
7292 static const struct
7294 const char *name;
7295 D3DFORMAT format;
7296 BOOL getdc_supported;
7298 testdata[] =
7300 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, TRUE },
7301 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, TRUE },
7302 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, TRUE },
7303 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, TRUE },
7304 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, TRUE },
7305 {"D3DFMT_R8G8B8", D3DFMT_R8G8B8, TRUE },
7306 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, FALSE}, /* Untested, card on windows didn't support it. */
7307 {"D3DFMT_V8U8", D3DFMT_V8U8, FALSE},
7308 {"D3DFMT_Q8W8V8U8", D3DFMT_Q8W8V8U8, FALSE},
7309 {"D3DFMT_A8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
7310 {"D3DFMT_X8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
7311 {"D3DFMT_R3G3B2", D3DFMT_R3G3B2, FALSE},
7312 {"D3DFMT_P8", D3DFMT_P8, FALSE},
7313 {"D3DFMT_L8", D3DFMT_L8, FALSE},
7314 {"D3DFMT_A8L8", D3DFMT_A8L8, FALSE},
7315 {"D3DFMT_DXT1", D3DFMT_DXT1, FALSE},
7316 {"D3DFMT_DXT2", D3DFMT_DXT2, FALSE},
7317 {"D3DFMT_DXT3", D3DFMT_DXT3, FALSE},
7318 {"D3DFMT_DXT4", D3DFMT_DXT4, FALSE},
7319 {"D3DFMT_DXT5", D3DFMT_DXT5, FALSE},
7321 IDirect3DTexture9 *texture;
7322 IDirect3DSurface9 *surface;
7323 IDirect3DDevice9 *device;
7324 IDirect3D9 *d3d;
7325 unsigned int i;
7326 ULONG refcount;
7327 HWND window;
7328 HRESULT hr;
7329 HDC dc;
7331 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7332 0, 0, 640, 480, 0, 0, 0, 0);
7333 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7334 ok(!!d3d, "Failed to create a D3D object.\n");
7335 if (!(device = create_device(d3d, window, NULL)))
7337 skip("Failed to create a D3D device, skipping tests.\n");
7338 IDirect3D9_Release(d3d);
7339 DestroyWindow(window);
7340 return;
7343 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
7345 texture = NULL;
7346 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7347 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
7348 if (FAILED(hr))
7350 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
7351 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
7352 if (FAILED(hr))
7354 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7355 continue;
7357 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7358 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7361 dc = (void *)0x1234;
7362 hr = IDirect3DSurface9_GetDC(surface, &dc);
7363 if (testdata[i].getdc_supported)
7364 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7365 else
7366 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7368 if (SUCCEEDED(hr))
7370 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7371 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
7373 else
7375 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
7378 IDirect3DSurface9_Release(surface);
7379 if (texture)
7380 IDirect3DTexture9_Release(texture);
7383 refcount = IDirect3DDevice9_Release(device);
7384 ok(!refcount, "Device has %u references left.\n", refcount);
7385 IDirect3D9_Release(d3d);
7386 DestroyWindow(window);
7389 static void test_surface_dimensions(void)
7391 IDirect3DSurface9 *surface;
7392 IDirect3DDevice9 *device;
7393 IDirect3D9 *d3d;
7394 ULONG refcount;
7395 HWND window;
7396 HRESULT hr;
7398 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7399 0, 0, 640, 480, 0, 0, 0, 0);
7400 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7401 ok(!!d3d, "Failed to create a D3D object.\n");
7402 if (!(device = create_device(d3d, window, NULL)))
7404 skip("Failed to create a D3D device, skipping tests.\n");
7405 IDirect3D9_Release(d3d);
7406 DestroyWindow(window);
7407 return;
7410 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
7411 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7412 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7413 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
7414 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7415 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7417 refcount = IDirect3DDevice9_Release(device);
7418 ok(!refcount, "Device has %u references left.\n", refcount);
7419 IDirect3D9_Release(d3d);
7420 DestroyWindow(window);
7423 static void test_surface_format_null(void)
7425 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
7426 IDirect3DTexture9 *texture;
7427 IDirect3DSurface9 *surface;
7428 IDirect3DSurface9 *rt, *ds;
7429 D3DLOCKED_RECT locked_rect;
7430 IDirect3DDevice9 *device;
7431 D3DSURFACE_DESC desc;
7432 IDirect3D9 *d3d;
7433 ULONG refcount;
7434 HWND window;
7435 HRESULT hr;
7437 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7438 ok(!!d3d, "Failed to create a D3D object.\n");
7440 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7441 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
7442 if (hr != D3D_OK)
7444 skip("No D3DFMT_NULL support, skipping test.\n");
7445 IDirect3D9_Release(d3d);
7446 return;
7449 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7450 0, 0, 640, 480, 0, 0, 0, 0);
7451 if (!(device = create_device(d3d, window, NULL)))
7453 skip("Failed to create a D3D device, skipping tests.\n");
7454 IDirect3D9_Release(d3d);
7455 DestroyWindow(window);
7456 return;
7459 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7460 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
7461 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
7463 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7464 D3DFMT_NULL, D3DFMT_D24S8);
7465 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
7467 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
7468 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
7469 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
7471 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
7472 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
7474 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
7475 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
7477 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
7478 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
7480 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
7481 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
7483 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
7484 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
7486 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
7487 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
7489 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
7490 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
7492 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
7493 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
7495 IDirect3DSurface9_Release(rt);
7496 IDirect3DSurface9_Release(ds);
7498 hr = IDirect3DSurface9_GetDesc(surface, &desc);
7499 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7500 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
7501 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
7503 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7504 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7505 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
7506 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
7508 hr = IDirect3DSurface9_UnlockRect(surface);
7509 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7511 IDirect3DSurface9_Release(surface);
7513 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
7514 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
7515 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7516 IDirect3DTexture9_Release(texture);
7518 refcount = IDirect3DDevice9_Release(device);
7519 ok(!refcount, "Device has %u references left.\n", refcount);
7520 IDirect3D9_Release(d3d);
7521 DestroyWindow(window);
7524 static void test_surface_double_unlock(void)
7526 static const D3DPOOL pools[] =
7528 D3DPOOL_DEFAULT,
7529 D3DPOOL_SCRATCH,
7530 D3DPOOL_SYSTEMMEM,
7532 IDirect3DSurface9 *surface;
7533 IDirect3DDevice9 *device;
7534 D3DLOCKED_RECT lr;
7535 IDirect3D9 *d3d;
7536 unsigned int i;
7537 ULONG refcount;
7538 HWND window;
7539 HRESULT hr;
7541 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7542 0, 0, 640, 480, 0, 0, 0, 0);
7543 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7544 ok(!!d3d, "Failed to create a D3D object.\n");
7545 if (!(device = create_device(d3d, window, NULL)))
7547 skip("Failed to create a D3D device, skipping tests.\n");
7548 IDirect3D9_Release(d3d);
7549 DestroyWindow(window);
7550 return;
7553 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
7555 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7556 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
7557 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
7559 hr = IDirect3DSurface9_UnlockRect(surface);
7560 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
7561 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7562 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
7563 hr = IDirect3DSurface9_UnlockRect(surface);
7564 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
7565 hr = IDirect3DSurface9_UnlockRect(surface);
7566 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
7568 IDirect3DSurface9_Release(surface);
7571 refcount = IDirect3DDevice9_Release(device);
7572 ok(!refcount, "Device has %u references left.\n", refcount);
7573 IDirect3D9_Release(d3d);
7574 DestroyWindow(window);
7577 static void test_surface_blocks(void)
7579 static const struct
7581 D3DFORMAT fmt;
7582 const char *name;
7583 unsigned int block_width;
7584 unsigned int block_height;
7585 BOOL broken;
7586 BOOL create_size_checked, core_fmt;
7588 formats[] =
7590 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
7591 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
7592 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
7593 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
7594 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
7595 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
7596 * which doesn't match the format spec. On newer Nvidia cards
7597 * they have the correct 4x4 block size */
7598 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
7599 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
7600 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
7601 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
7603 static const struct
7605 D3DPOOL pool;
7606 const char *name;
7607 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
7608 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
7609 BOOL success;
7611 pools[] =
7613 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
7614 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
7615 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
7616 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
7618 static struct
7620 D3DRESOURCETYPE rtype;
7621 const char *type_name;
7622 D3DPOOL pool;
7623 const char *pool_name;
7624 BOOL need_driver_support, need_runtime_support;
7626 create_tests[] =
7628 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7629 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
7630 /* Managed offscreen plain surfaces are not supported */
7631 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7633 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7634 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
7635 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
7636 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7638 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7639 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
7640 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
7641 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7643 IDirect3DTexture9 *texture;
7644 IDirect3DCubeTexture9 *cube_texture;
7645 IDirect3DSurface9 *surface;
7646 D3DLOCKED_RECT locked_rect;
7647 IDirect3DDevice9 *device;
7648 unsigned int i, j, w, h;
7649 BOOL surface_only;
7650 IDirect3D9 *d3d;
7651 ULONG refcount;
7652 HWND window;
7653 HRESULT hr;
7654 RECT rect;
7655 BOOL tex_pow2, cube_pow2;
7656 D3DCAPS9 caps;
7658 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7659 0, 0, 640, 480, 0, 0, 0, 0);
7660 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7661 ok(!!d3d, "Failed to create a D3D object.\n");
7662 if (!(device = create_device(d3d, window, NULL)))
7664 skip("Failed to create a D3D device, skipping tests.\n");
7665 IDirect3D9_Release(d3d);
7666 DestroyWindow(window);
7667 return;
7670 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7671 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7672 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
7673 if (tex_pow2)
7674 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
7675 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
7677 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
7679 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
7681 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7682 0, D3DRTYPE_TEXTURE, formats[i].fmt);
7683 tex_support = SUCCEEDED(hr);
7684 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7685 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
7686 cube_support = SUCCEEDED(hr);
7687 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7688 0, D3DRTYPE_SURFACE, formats[i].fmt);
7689 surface_support = SUCCEEDED(hr);
7691 /* Scratch pool in general allows texture creation even if the driver does
7692 * not support the format. If the format is an extension format that is not
7693 * known to the runtime, like ATI2N, some driver support is required for
7694 * this to work.
7696 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
7697 * about ATI2N. I cannot check this because all my Vista+ machines support
7698 * ATI2N in hardware, but none of my WinXP machines do. */
7699 format_known = tex_support || cube_support || surface_support;
7701 for (w = 1; w <= 8; w++)
7703 for (h = 1; h <= 8; h++)
7705 BOOL block_aligned = TRUE;
7706 BOOL size_is_pow2;
7708 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
7709 block_aligned = FALSE;
7711 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
7713 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
7715 BOOL support, pow2;
7716 HRESULT expect_hr;
7717 BOOL may_succeed = FALSE;
7718 IUnknown **check_null;
7720 if (!formats[i].core_fmt)
7722 /* AMD warns against creating ATI2N textures smaller than
7723 * the block size because the runtime cannot calculate the
7724 * correct texture size. Generalize this for all extension
7725 * formats. */
7726 if (w < formats[i].block_width || h < formats[i].block_height)
7727 continue;
7730 texture = (IDirect3DTexture9 *)0xdeadbeef;
7731 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
7732 surface = (IDirect3DSurface9 *)0xdeadbeef;
7734 switch (create_tests[j].rtype)
7736 case D3DRTYPE_TEXTURE:
7737 check_null = (IUnknown **)&texture;
7738 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
7739 formats[i].fmt, create_tests[j].pool, &texture, NULL);
7740 support = tex_support;
7741 pow2 = tex_pow2;
7742 break;
7744 case D3DRTYPE_CUBETEXTURE:
7745 if (w != h)
7746 continue;
7747 check_null = (IUnknown **)&cube_texture;
7748 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
7749 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
7750 support = cube_support;
7751 pow2 = cube_pow2;
7752 break;
7754 case D3DRTYPE_SURFACE:
7755 check_null = (IUnknown **)&surface;
7756 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
7757 formats[i].fmt, create_tests[j].pool, &surface, NULL);
7758 support = surface_support;
7759 pow2 = FALSE;
7760 break;
7762 default:
7763 check_null = NULL;
7764 pow2 = FALSE;
7765 support = FALSE;
7766 break;
7769 if (create_tests[j].need_driver_support && !support)
7770 expect_hr = D3DERR_INVALIDCALL;
7771 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
7772 expect_hr = D3DERR_INVALIDCALL;
7773 else if (formats[i].create_size_checked && !block_aligned)
7774 expect_hr = D3DERR_INVALIDCALL;
7775 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
7776 expect_hr = D3DERR_INVALIDCALL;
7777 else
7778 expect_hr = D3D_OK;
7780 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
7781 * does not support it. Accept scratch creation of extension formats on
7782 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
7783 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
7784 * support it. */
7785 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
7786 may_succeed = TRUE;
7788 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
7789 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
7790 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
7791 if (FAILED(hr))
7792 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
7793 else
7794 IUnknown_Release(*check_null);
7799 surface_only = FALSE;
7800 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7801 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
7802 dynamic_tex_support = SUCCEEDED(hr);
7803 if (!dynamic_tex_support)
7805 if (!surface_support)
7807 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
7808 continue;
7810 surface_only = TRUE;
7813 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
7815 switch (pools[j].pool)
7817 case D3DPOOL_SYSTEMMEM:
7818 case D3DPOOL_MANAGED:
7819 if (surface_only)
7820 continue;
7821 /* Fall through */
7822 case D3DPOOL_DEFAULT:
7823 if (surface_only)
7825 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7826 formats[i].fmt, pools[j].pool, &surface, NULL);
7827 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7829 else
7831 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
7832 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
7833 formats[i].fmt, pools[j].pool, &texture, NULL);
7834 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7835 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7836 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7837 IDirect3DTexture9_Release(texture);
7839 break;
7841 case D3DPOOL_SCRATCH:
7842 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7843 formats[i].fmt, pools[j].pool, &surface, NULL);
7844 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7845 break;
7847 default:
7848 break;
7851 if (formats[i].block_width > 1)
7853 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
7854 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7855 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
7856 "Partial block lock %s, expected %s, format %s, pool %s.\n",
7857 SUCCEEDED(hr) ? "succeeded" : "failed",
7858 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
7859 if (SUCCEEDED(hr))
7861 hr = IDirect3DSurface9_UnlockRect(surface);
7862 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7865 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
7866 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7867 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
7868 "Partial block lock %s, expected %s, format %s, pool %s.\n",
7869 SUCCEEDED(hr) ? "succeeded" : "failed",
7870 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
7871 if (SUCCEEDED(hr))
7873 hr = IDirect3DSurface9_UnlockRect(surface);
7874 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7878 if (formats[i].block_height > 1)
7880 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
7881 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7882 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
7883 "Partial block lock %s, expected %s, format %s, pool %s.\n",
7884 SUCCEEDED(hr) ? "succeeded" : "failed",
7885 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
7886 if (SUCCEEDED(hr))
7888 hr = IDirect3DSurface9_UnlockRect(surface);
7889 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7892 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
7893 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7894 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
7895 "Partial block lock %s, expected %s, format %s, pool %s.\n",
7896 SUCCEEDED(hr) ? "succeeded" : "failed",
7897 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
7898 if (SUCCEEDED(hr))
7900 hr = IDirect3DSurface9_UnlockRect(surface);
7901 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7905 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
7906 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7907 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
7908 hr = IDirect3DSurface9_UnlockRect(surface);
7909 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7911 IDirect3DSurface9_Release(surface);
7914 if (!dynamic_tex_support)
7916 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
7917 continue;
7920 if (formats[i].block_width == 1 && formats[i].block_height == 1)
7921 continue;
7922 if (!formats[i].core_fmt)
7923 continue;
7925 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
7926 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
7927 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
7929 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
7930 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
7931 hr = IDirect3DTexture9_UnlockRect(texture, 1);
7932 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
7934 rect.left = 0;
7935 rect.top = 0;
7936 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
7937 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
7938 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
7939 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
7940 hr = IDirect3DTexture9_UnlockRect(texture, 1);
7941 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
7943 rect.right = formats[i].block_width;
7944 rect.bottom = formats[i].block_height;
7945 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
7946 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7947 if (SUCCEEDED(hr))
7948 IDirect3DTexture9_UnlockRect(texture, 1);
7950 IDirect3DTexture9_Release(texture);
7953 refcount = IDirect3DDevice9_Release(device);
7954 ok(!refcount, "Device has %u references left.\n", refcount);
7955 IDirect3D9_Release(d3d);
7956 DestroyWindow(window);
7959 static void test_set_palette(void)
7961 IDirect3DDevice9 *device;
7962 IDirect3D9 *d3d9;
7963 UINT refcount;
7964 HWND window;
7965 HRESULT hr;
7966 PALETTEENTRY pal[256];
7967 unsigned int i;
7968 D3DCAPS9 caps;
7970 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
7971 0, 0, 640, 480, 0, 0, 0, 0);
7972 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
7973 ok(!!d3d9, "Failed to create a D3D object.\n");
7974 if (!(device = create_device(d3d9, window, NULL)))
7976 skip("Failed to create a D3D device, skipping tests.\n");
7977 DestroyWindow(window);
7978 return;
7981 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
7983 pal[i].peRed = i;
7984 pal[i].peGreen = i;
7985 pal[i].peBlue = i;
7986 pal[i].peFlags = 0xff;
7988 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
7989 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
7991 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7992 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7993 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
7995 pal[i].peRed = i;
7996 pal[i].peGreen = i;
7997 pal[i].peBlue = i;
7998 pal[i].peFlags = i;
8000 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
8002 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8003 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8005 else
8007 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8008 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
8011 refcount = IDirect3DDevice9_Release(device);
8012 ok(!refcount, "Device has %u references left.\n", refcount);
8013 IDirect3D9_Release(d3d9);
8014 DestroyWindow(window);
8017 static void test_swvp_buffer(void)
8019 IDirect3DDevice9 *device;
8020 IDirect3D9 *d3d9;
8021 UINT refcount;
8022 HWND window;
8023 HRESULT hr;
8024 unsigned int i;
8025 IDirect3DVertexBuffer9 *buffer;
8026 static const unsigned int bufsize = 1024;
8027 D3DVERTEXBUFFER_DESC desc;
8028 struct device_desc device_desc;
8029 struct
8031 float x, y, z;
8032 } *ptr, *ptr2;
8034 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8035 0, 0, 640, 480, 0, 0, 0, 0);
8036 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8037 ok(!!d3d9, "Failed to create a D3D object.\n");
8039 device_desc.device_window = window;
8040 device_desc.width = 640;
8041 device_desc.height = 480;
8042 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
8043 if (!(device = create_device(d3d9, window, &device_desc)))
8045 skip("Failed to create a D3D device, skipping tests.\n");
8046 DestroyWindow(window);
8047 IDirect3D9_Release(d3d9);
8048 return;
8051 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
8052 D3DPOOL_DEFAULT, &buffer, NULL);
8053 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8054 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8055 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8056 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
8057 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
8058 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
8060 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8061 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8062 for (i = 0; i < bufsize; i++)
8064 ptr[i].x = i * 1.0f;
8065 ptr[i].y = i * 2.0f;
8066 ptr[i].z = i * 3.0f;
8068 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8069 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8071 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8072 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8073 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8074 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8075 hr = IDirect3DDevice9_BeginScene(device);
8076 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8077 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8078 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8079 hr = IDirect3DDevice9_EndScene(device);
8080 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8082 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8083 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8084 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
8085 for (i = 0; i < bufsize; i++)
8087 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8089 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
8090 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8091 break;
8094 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8095 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8097 IDirect3DVertexBuffer9_Release(buffer);
8098 refcount = IDirect3DDevice9_Release(device);
8099 ok(!refcount, "Device has %u references left.\n", refcount);
8100 IDirect3D9_Release(d3d9);
8101 DestroyWindow(window);
8104 static void test_npot_textures(void)
8106 IDirect3DDevice9 *device = NULL;
8107 IDirect3D9 *d3d9;
8108 ULONG refcount;
8109 HWND window = NULL;
8110 HRESULT hr;
8111 D3DCAPS9 caps;
8112 IDirect3DTexture9 *texture;
8113 IDirect3DCubeTexture9 *cube_texture;
8114 IDirect3DVolumeTexture9 *volume_texture;
8115 struct
8117 D3DPOOL pool;
8118 const char *pool_name;
8119 HRESULT hr;
8121 pools[] =
8123 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
8124 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
8125 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
8126 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
8128 unsigned int i, levels;
8129 BOOL tex_pow2, cube_pow2, vol_pow2;
8131 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8132 0, 0, 640, 480, 0, 0, 0, 0);
8133 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8134 ok(!!d3d9, "Failed to create a D3D object.\n");
8135 if (!(device = create_device(d3d9, window, NULL)))
8137 skip("Failed to create a D3D device, skipping tests.\n");
8138 goto done;
8141 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8142 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8143 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8144 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8145 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8146 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
8147 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
8149 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
8151 for (levels = 0; levels <= 2; levels++)
8153 HRESULT expected;
8155 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
8156 pools[i].pool, &texture, NULL);
8157 if (!tex_pow2)
8159 expected = D3D_OK;
8161 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
8163 if (levels == 1)
8164 expected = D3D_OK;
8165 else
8166 expected = pools[i].hr;
8168 else
8170 expected = pools[i].hr;
8172 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
8173 pools[i].pool_name, levels, hr, expected);
8175 if (SUCCEEDED(hr))
8176 IDirect3DTexture9_Release(texture);
8179 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8180 &cube_texture, NULL);
8181 if (tex_pow2)
8183 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8184 pools[i].pool_name, hr, pools[i].hr);
8186 else
8188 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8189 pools[i].pool_name, hr, D3D_OK);
8192 if (SUCCEEDED(hr))
8193 IDirect3DCubeTexture9_Release(cube_texture);
8195 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8196 &volume_texture, NULL);
8197 if (tex_pow2)
8199 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8200 pools[i].pool_name, hr, pools[i].hr);
8202 else
8204 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8205 pools[i].pool_name, hr, D3D_OK);
8208 if (SUCCEEDED(hr))
8209 IDirect3DVolumeTexture9_Release(volume_texture);
8212 done:
8213 if (device)
8215 refcount = IDirect3DDevice9_Release(device);
8216 ok(!refcount, "Device has %u references left.\n", refcount);
8218 IDirect3D9_Release(d3d9);
8219 DestroyWindow(window);
8223 static void test_vidmem_accounting(void)
8225 IDirect3DDevice9 *device;
8226 IDirect3D9 *d3d9;
8227 ULONG refcount;
8228 HWND window;
8229 HRESULT hr = D3D_OK;
8230 IDirect3DTexture9 *textures[20];
8231 unsigned int i;
8232 UINT vidmem_start, vidmem_end, diff;
8234 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8235 0, 0, 640, 480, 0, 0, 0, 0);
8236 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8237 ok(!!d3d9, "Failed to create a D3D object.\n");
8238 if (!(device = create_device(d3d9, window, NULL)))
8240 skip("Failed to create a D3D device, skipping tests.\n");
8241 IDirect3D9_Release(d3d9);
8242 DestroyWindow(window);
8243 return;
8246 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
8247 memset(textures, 0, sizeof(textures));
8248 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
8250 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
8251 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
8252 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
8253 * E_FAIL is returned on address space or system memory exhaustion */
8254 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
8255 "Failed to create texture, hr %#x.\n", hr);
8257 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
8259 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
8260 diff = vidmem_start - vidmem_end;
8261 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
8262 2 * i, diff / 1024 / 1024);
8264 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
8266 if (textures[i])
8267 IDirect3DTexture9_Release(textures[i]);
8270 refcount = IDirect3DDevice9_Release(device);
8271 ok(!refcount, "Device has %u references left.\n", refcount);
8272 IDirect3D9_Release(d3d9);
8273 DestroyWindow(window);
8276 static void test_volume_locking(void)
8278 IDirect3DDevice9 *device;
8279 IDirect3D9 *d3d9;
8280 HWND window;
8281 HRESULT hr;
8282 IDirect3DVolumeTexture9 *texture;
8283 unsigned int i;
8284 D3DLOCKED_BOX locked_box;
8285 ULONG refcount;
8286 D3DCAPS9 caps;
8287 static const struct
8289 D3DPOOL pool;
8290 DWORD usage;
8291 HRESULT create_hr, lock_hr;
8293 tests[] =
8295 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
8296 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
8297 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
8298 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
8299 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
8300 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
8301 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
8302 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
8305 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8306 0, 0, 640, 480, 0, 0, 0, 0);
8307 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8308 ok(!!d3d9, "Failed to create a D3D object.\n");
8309 if (!(device = create_device(d3d9, window, NULL)))
8311 skip("Failed to create a D3D device, skipping tests.\n");
8312 IDirect3D9_Release(d3d9);
8313 DestroyWindow(window);
8314 return;
8317 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8318 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8319 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
8321 skip("Volume textures not supported, skipping test.\n");
8322 goto out;
8325 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8327 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
8328 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
8329 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
8330 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
8331 if (FAILED(hr))
8332 continue;
8334 locked_box.pBits = (void *)0xdeadbeef;
8335 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
8336 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
8337 if (SUCCEEDED(hr))
8339 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8340 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8342 else
8344 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
8346 IDirect3DVolumeTexture9_Release(texture);
8349 out:
8350 refcount = IDirect3DDevice9_Release(device);
8351 ok(!refcount, "Device has %u references left.\n", refcount);
8352 IDirect3D9_Release(d3d9);
8353 DestroyWindow(window);
8356 static void test_update_volumetexture(void)
8358 IDirect3DDevice9 *device;
8359 IDirect3D9 *d3d9;
8360 HWND window;
8361 HRESULT hr;
8362 IDirect3DVolumeTexture9 *src, *dst;
8363 unsigned int i;
8364 D3DLOCKED_BOX locked_box;
8365 ULONG refcount;
8366 D3DCAPS9 caps;
8367 static const struct
8369 D3DPOOL src_pool, dst_pool;
8370 HRESULT hr;
8372 tests[] =
8374 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
8375 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
8376 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
8377 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
8379 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8380 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8381 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8382 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8384 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8385 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8386 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8387 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8389 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8390 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8391 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8392 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8394 static const struct
8396 UINT src_size, dst_size;
8397 UINT src_lvl, dst_lvl;
8398 D3DFORMAT src_fmt, dst_fmt;
8400 tests2[] =
8402 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8403 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8404 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8405 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8406 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8407 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
8408 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
8409 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
8412 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8413 0, 0, 640, 480, 0, 0, 0, 0);
8414 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8415 ok(!!d3d9, "Failed to create a D3D object.\n");
8416 if (!(device = create_device(d3d9, window, NULL)))
8418 skip("Failed to create a D3D device, skipping tests.\n");
8419 IDirect3D9_Release(d3d9);
8420 DestroyWindow(window);
8421 return;
8424 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8425 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8426 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
8428 skip("Volume textures not supported, skipping test.\n");
8429 goto out;
8432 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8434 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
8435 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
8437 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
8438 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
8439 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8440 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
8441 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
8442 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8444 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
8445 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
8446 *((DWORD *)locked_box.pBits) = 0x11223344;
8447 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
8448 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8450 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
8451 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
8452 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
8454 if (SUCCEEDED(hr))
8456 DWORD content = *((DWORD *)locked_box.pBits);
8457 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
8458 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
8459 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
8460 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
8461 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8463 IDirect3DVolumeTexture9_Release(src);
8464 IDirect3DVolumeTexture9_Release(dst);
8467 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
8469 skip("Mipmapped volume maps not supported.\n");
8470 goto out;
8473 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
8475 hr = IDirect3DDevice9_CreateVolumeTexture(device,
8476 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
8477 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
8478 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
8479 hr = IDirect3DDevice9_CreateVolumeTexture(device,
8480 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
8481 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
8482 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
8484 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
8485 if (FAILED(hr))
8486 todo_wine ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
8487 else
8488 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
8490 IDirect3DVolumeTexture9_Release(src);
8491 IDirect3DVolumeTexture9_Release(dst);
8494 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
8495 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
8496 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
8497 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
8498 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
8500 * I'm not adding tests for this behavior until an application needs it. */
8502 out:
8503 refcount = IDirect3DDevice9_Release(device);
8504 ok(!refcount, "Device has %u references left.\n", refcount);
8505 IDirect3D9_Release(d3d9);
8506 DestroyWindow(window);
8509 static void test_create_rt_ds_fail(void)
8511 IDirect3DDevice9 *device;
8512 HWND window;
8513 HRESULT hr;
8514 ULONG refcount;
8515 IDirect3D9 *d3d9;
8516 IDirect3DSurface9 *surface;
8518 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8519 0, 0, 640, 480, 0, 0, 0, 0);
8520 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8521 ok(!!d3d9, "Failed to create a D3D object.\n");
8522 if (!(device = create_device(d3d9, window, NULL)))
8524 skip("Failed to create a D3D device, skipping tests.\n");
8525 IDirect3D9_Release(d3d9);
8526 DestroyWindow(window);
8527 return;
8530 /* Output pointer == NULL segfaults on Windows. */
8532 surface = (IDirect3DSurface9 *)0xdeadbeef;
8533 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
8534 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
8535 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
8536 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
8537 if (SUCCEEDED(hr))
8538 IDirect3DSurface9_Release(surface);
8540 surface = (IDirect3DSurface9 *)0xdeadbeef;
8541 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
8542 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8543 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
8544 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
8545 if (SUCCEEDED(hr))
8546 IDirect3DSurface9_Release(surface);
8548 refcount = IDirect3DDevice9_Release(device);
8549 ok(!refcount, "Device has %u references left.\n", refcount);
8550 IDirect3D9_Release(d3d9);
8551 DestroyWindow(window);
8554 static void test_volume_blocks(void)
8556 IDirect3DDevice9 *device;
8557 IDirect3D9 *d3d9;
8558 UINT refcount;
8559 HWND window;
8560 HRESULT hr;
8561 D3DCAPS9 caps;
8562 IDirect3DVolumeTexture9 *texture;
8563 unsigned int w, h, d, i, j;
8564 static const struct
8566 D3DFORMAT fmt;
8567 const char *name;
8568 unsigned int block_width;
8569 unsigned int block_height;
8570 unsigned int block_depth;
8571 unsigned int block_size;
8572 unsigned int broken;
8573 BOOL create_size_checked, core_fmt;
8575 formats[] =
8577 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
8578 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
8579 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
8580 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
8581 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
8582 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
8583 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
8584 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
8585 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
8586 * which doesn't match the format spec. On newer Nvidia cards
8587 * it has the correct 4x4 block size.
8588 * ATI1N volume textures are only supported by AMD GPUs right
8589 * now and locking offsets seem just wrong. */
8590 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
8591 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
8592 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
8593 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
8595 static const struct
8597 D3DPOOL pool;
8598 const char *name;
8599 BOOL need_driver_support, need_runtime_support;
8601 create_tests[] =
8603 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8604 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8605 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
8606 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8608 static const struct
8610 unsigned int x, y, z, x2, y2, z2;
8612 offset_tests[] =
8614 {0, 0, 0, 8, 8, 8},
8615 {0, 0, 3, 8, 8, 8},
8616 {0, 4, 0, 8, 8, 8},
8617 {0, 4, 3, 8, 8, 8},
8618 {4, 0, 0, 8, 8, 8},
8619 {4, 0, 3, 8, 8, 8},
8620 {4, 4, 0, 8, 8, 8},
8621 {4, 4, 3, 8, 8, 8},
8623 D3DBOX box;
8624 D3DLOCKED_BOX locked_box;
8625 BYTE *base;
8626 INT expected_row_pitch, expected_slice_pitch;
8627 BOOL support;
8628 BOOL pow2;
8629 unsigned int offset, expected_offset;
8631 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8632 0, 0, 640, 480, 0, 0, 0, 0);
8633 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8634 ok(!!d3d9, "Failed to create a D3D object.\n");
8635 if (!(device = create_device(d3d9, window, NULL)))
8637 skip("Failed to create a D3D device, skipping tests.\n");
8638 IDirect3D9_Release(d3d9);
8639 DestroyWindow(window);
8640 return;
8642 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8643 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8644 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8646 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
8648 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8649 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
8650 support = SUCCEEDED(hr);
8652 /* Test creation restrictions */
8653 for (w = 1; w <= 8; w++)
8655 for (h = 1; h <= 8; h++)
8657 for (d = 1; d <= 8; d++)
8659 HRESULT expect_hr;
8660 BOOL size_is_pow2;
8661 BOOL block_aligned = TRUE;
8663 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8664 block_aligned = FALSE;
8666 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
8668 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
8670 BOOL may_succeed = FALSE;
8672 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
8673 expect_hr = D3DERR_INVALIDCALL;
8674 else if (formats[i].create_size_checked && !block_aligned)
8675 expect_hr = D3DERR_INVALIDCALL;
8676 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8677 expect_hr = D3DERR_INVALIDCALL;
8678 else if (create_tests[j].need_driver_support && !support)
8679 expect_hr = D3DERR_INVALIDCALL;
8680 else
8681 expect_hr = D3D_OK;
8683 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
8684 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
8685 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8687 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8688 * does not support it. Accept scratch creation of extension formats on
8689 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8690 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8691 * support it. */
8692 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
8693 may_succeed = TRUE;
8695 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8696 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
8697 hr, formats[i].name, create_tests[j].name, w, h, d);
8699 if (FAILED(hr))
8700 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
8701 else
8702 IDirect3DVolumeTexture9_Release(texture);
8708 if (!support && !formats[i].core_fmt)
8709 continue;
8711 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
8712 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
8713 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8715 /* Test lockrect offset */
8716 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
8718 unsigned int bytes_per_pixel;
8719 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
8721 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
8722 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8724 base = locked_box.pBits;
8725 if (formats[i].broken == 1)
8727 expected_row_pitch = bytes_per_pixel * 24;
8729 else if (formats[i].broken == 2)
8731 expected_row_pitch = 24;
8733 else
8735 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
8736 * formats[i].block_size;
8738 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
8739 locked_box.RowPitch, formats[i].name, expected_row_pitch);
8741 if (formats[i].broken)
8743 expected_slice_pitch = expected_row_pitch * 8;
8745 else
8747 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
8748 * expected_row_pitch;
8750 ok(locked_box.SlicePitch == expected_slice_pitch,
8751 "Got unexpected slice pitch %d for format %s, expected %d.\n",
8752 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
8754 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8755 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
8757 box.Left = offset_tests[j].x;
8758 box.Top = offset_tests[j].y;
8759 box.Front = offset_tests[j].z;
8760 box.Right = offset_tests[j].x2;
8761 box.Bottom = offset_tests[j].y2;
8762 box.Back = offset_tests[j].z2;
8763 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
8764 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
8766 offset = (BYTE *)locked_box.pBits - base;
8767 if (formats[i].broken == 1)
8769 expected_offset = box.Front * expected_slice_pitch
8770 + box.Top * expected_row_pitch
8771 + box.Left * bytes_per_pixel;
8773 else if (formats[i].broken == 2)
8775 expected_offset = box.Front * expected_slice_pitch
8776 + box.Top * expected_row_pitch
8777 + box.Left;
8779 else
8781 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
8782 + (box.Top / formats[i].block_height) * expected_row_pitch
8783 + (box.Left / formats[i].block_width) * formats[i].block_size;
8785 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
8786 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
8788 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8789 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8792 /* Test partial block locks */
8793 box.Front = 0;
8794 box.Back = 1;
8795 if (formats[i].block_width > 1)
8797 box.Left = formats[i].block_width >> 1;
8798 box.Top = 0;
8799 box.Right = formats[i].block_width;
8800 box.Bottom = formats[i].block_height;
8801 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
8802 ok(FAILED(hr) || broken(formats[i].broken),
8803 "Partial block lock succeeded, expected failure, format %s.\n",
8804 formats[i].name);
8805 if (SUCCEEDED(hr))
8807 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8808 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8811 box.Left = 0;
8812 box.Top = 0;
8813 box.Right = formats[i].block_width >> 1;
8814 box.Bottom = formats[i].block_height;
8815 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
8816 ok(FAILED(hr) || broken(formats[i].broken),
8817 "Partial block lock succeeded, expected failure, format %s.\n",
8818 formats[i].name);
8819 if (SUCCEEDED(hr))
8821 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8822 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8826 if (formats[i].block_height > 1)
8828 box.Left = 0;
8829 box.Top = formats[i].block_height >> 1;
8830 box.Right = formats[i].block_width;
8831 box.Bottom = formats[i].block_height;
8832 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
8833 ok(FAILED(hr) || broken(formats[i].broken),
8834 "Partial block lock succeeded, expected failure, format %s.\n",
8835 formats[i].name);
8836 if (SUCCEEDED(hr))
8838 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8839 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8842 box.Left = 0;
8843 box.Top = 0;
8844 box.Right = formats[i].block_width;
8845 box.Bottom = formats[i].block_height >> 1;
8846 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
8847 ok(FAILED(hr) || broken(formats[i].broken),
8848 "Partial block lock succeeded, expected failure, format %s.\n",
8849 formats[i].name);
8850 if (SUCCEEDED(hr))
8852 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8853 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8857 /* Test full block lock */
8858 box.Left = 0;
8859 box.Top = 0;
8860 box.Right = formats[i].block_width;
8861 box.Bottom = formats[i].block_height;
8862 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
8863 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
8864 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8865 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8867 IDirect3DVolumeTexture9_Release(texture);
8869 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
8870 * does not allocate surfaces smaller than the blocksize properly. */
8871 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
8873 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
8874 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
8875 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8877 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
8878 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
8879 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
8880 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8882 box.Left = box.Top = box.Front = 0;
8883 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
8884 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
8885 box.Back = 1;
8886 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
8887 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
8888 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
8889 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8891 box.Right = formats[i].block_width;
8892 box.Bottom = formats[i].block_height;
8893 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
8894 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8895 if (SUCCEEDED(hr))
8896 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
8898 IDirect3DVolumeTexture9_Release(texture);
8902 refcount = IDirect3DDevice9_Release(device);
8903 ok(!refcount, "Device has %u references left.\n", refcount);
8904 IDirect3D9_Release(d3d9);
8905 DestroyWindow(window);
8908 static void test_lockbox_invalid(void)
8910 static const struct
8912 D3DBOX box;
8913 HRESULT result;
8915 test_data[] =
8917 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
8918 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
8919 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
8920 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
8921 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
8922 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
8923 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
8924 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
8925 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
8926 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
8927 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
8928 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
8929 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
8930 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
8932 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
8933 IDirect3DVolumeTexture9 *texture = NULL;
8934 D3DLOCKED_BOX locked_box;
8935 IDirect3DDevice9 *device;
8936 IDirect3D9 *d3d;
8937 unsigned int i;
8938 ULONG refcount;
8939 HWND window;
8940 BYTE *base;
8941 HRESULT hr;
8943 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8944 0, 0, 640, 480, 0, 0, 0, 0);
8945 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8946 ok(!!d3d, "Failed to create a D3D object.\n");
8947 if (!(device = create_device(d3d, window, NULL)))
8949 skip("Failed to create a D3D device, skipping tests.\n");
8950 IDirect3D9_Release(d3d);
8951 DestroyWindow(window);
8952 return;
8955 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
8956 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
8957 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8958 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
8959 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
8960 base = locked_box.pBits;
8961 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8962 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8964 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
8966 unsigned int offset, expected_offset;
8967 const D3DBOX *box = &test_data[i].box;
8969 locked_box.pBits = (BYTE *)0xdeadbeef;
8970 locked_box.RowPitch = 0xdeadbeef;
8971 locked_box.SlicePitch = 0xdeadbeef;
8973 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
8974 /* Unlike surfaces, volumes properly check the box even in Windows XP */
8975 ok(hr == test_data[i].result,
8976 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
8977 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
8978 test_data[i].result);
8979 if (FAILED(hr))
8980 continue;
8982 offset = (BYTE *)locked_box.pBits - base;
8983 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
8984 ok(offset == expected_offset,
8985 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
8986 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
8988 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8989 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8992 /* locked_box = NULL throws an exception on Windows */
8993 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
8994 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
8995 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
8996 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8997 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8998 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8999 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9000 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9002 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9003 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9004 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9005 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9006 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9007 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9008 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9009 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9010 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
9011 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9012 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
9013 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
9014 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9015 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9017 IDirect3DVolumeTexture9_Release(texture);
9018 refcount = IDirect3DDevice9_Release(device);
9019 ok(!refcount, "Device has %u references left.\n", refcount);
9020 IDirect3D9_Release(d3d);
9021 DestroyWindow(window);
9024 static void test_shared_handle(void)
9026 IDirect3DDevice9 *device;
9027 IDirect3D9 *d3d;
9028 ULONG refcount;
9029 HWND window;
9030 HRESULT hr;
9031 /* Native d3d9ex refuses to create a shared texture if the texture pointer
9032 * is not initialized to NULL. Make sure this doesn't cause issues here. */
9033 IDirect3DTexture9 *texture = NULL;
9034 IDirect3DSurface9 *surface = NULL;
9035 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
9036 IDirect3DIndexBuffer9 *index_buffer = NULL;
9037 HANDLE handle = NULL;
9038 void *mem;
9039 D3DCAPS9 caps;
9041 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9042 0, 0, 640, 480, 0, 0, 0, 0);
9043 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9044 ok(!!d3d, "Failed to create a D3D object.\n");
9045 if (!(device = create_device(d3d, window, NULL)))
9047 skip("Failed to create a D3D device, skipping tests.\n");
9048 IDirect3D9_Release(d3d);
9049 DestroyWindow(window);
9050 return;
9053 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9054 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9055 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
9057 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
9058 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
9059 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9060 D3DPOOL_DEFAULT, &texture, &handle);
9061 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9062 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9063 D3DPOOL_SYSTEMMEM, &texture, &mem);
9064 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9066 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9067 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
9068 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9069 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9070 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
9071 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9073 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9074 &vertex_buffer, &handle);
9075 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9076 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9077 &vertex_buffer, &mem);
9078 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
9080 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9081 &index_buffer, &handle);
9082 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9083 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9084 &index_buffer, &mem);
9085 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9087 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9089 IDirect3DCubeTexture9 *cube_texture = NULL;
9090 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9091 D3DPOOL_DEFAULT, &cube_texture, &handle);
9092 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9093 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9094 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
9095 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9098 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
9100 IDirect3DVolumeTexture9 *volume_texture = NULL;
9101 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9102 D3DPOOL_DEFAULT, &volume_texture, &handle);
9103 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9104 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9105 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
9106 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9109 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
9110 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9111 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9113 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
9114 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9115 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9117 HeapFree(GetProcessHeap(), 0, mem);
9118 refcount = IDirect3DDevice9_Release(device);
9119 ok(!refcount, "Device has %u references left.\n", refcount);
9120 IDirect3D9_Release(d3d);
9121 DestroyWindow(window);
9124 static void test_pixel_format(void)
9126 HWND hwnd, hwnd2 = NULL;
9127 HDC hdc, hdc2 = NULL;
9128 HMODULE gl = NULL;
9129 int format, test_format;
9130 PIXELFORMATDESCRIPTOR pfd;
9131 IDirect3D9 *d3d9 = NULL;
9132 IDirect3DDevice9 *device = NULL;
9133 HRESULT hr;
9134 static const float point[3] = {0.0, 0.0, 0.0};
9136 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9137 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9138 if (!hwnd)
9140 skip("Failed to create window\n");
9141 return;
9144 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9145 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9147 hdc = GetDC(hwnd);
9148 if (!hdc)
9150 skip("Failed to get DC\n");
9151 goto cleanup;
9154 if (hwnd2)
9155 hdc2 = GetDC(hwnd2);
9157 gl = LoadLibraryA("opengl32.dll");
9158 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
9160 format = GetPixelFormat(hdc);
9161 ok(format == 0, "new window has pixel format %d\n", format);
9163 ZeroMemory(&pfd, sizeof(pfd));
9164 pfd.nSize = sizeof(pfd);
9165 pfd.nVersion = 1;
9166 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
9167 pfd.iPixelType = PFD_TYPE_RGBA;
9168 pfd.iLayerType = PFD_MAIN_PLANE;
9169 format = ChoosePixelFormat(hdc, &pfd);
9170 if (format <= 0)
9172 skip("no pixel format available\n");
9173 goto cleanup;
9176 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
9178 skip("failed to set pixel format\n");
9179 goto cleanup;
9182 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
9184 skip("failed to set pixel format on second window\n");
9185 if (hdc2)
9187 ReleaseDC(hwnd2, hdc2);
9188 hdc2 = NULL;
9192 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9193 ok(!!d3d9, "Failed to create a D3D object.\n");
9195 test_format = GetPixelFormat(hdc);
9196 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9198 if (!(device = create_device(d3d9, hwnd, NULL)))
9200 skip("Failed to create device\n");
9201 goto cleanup;
9204 test_format = GetPixelFormat(hdc);
9205 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9207 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9208 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
9210 test_format = GetPixelFormat(hdc);
9211 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9213 hr = IDirect3DDevice9_BeginScene(device);
9214 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
9216 test_format = GetPixelFormat(hdc);
9217 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9219 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
9220 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9222 test_format = GetPixelFormat(hdc);
9223 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9225 hr = IDirect3DDevice9_EndScene(device);
9226 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
9228 test_format = GetPixelFormat(hdc);
9229 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9231 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9232 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9234 test_format = GetPixelFormat(hdc);
9235 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9237 if (hdc2)
9239 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
9240 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9242 test_format = GetPixelFormat(hdc);
9243 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9245 test_format = GetPixelFormat(hdc2);
9246 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
9249 cleanup:
9250 if (device)
9252 UINT refcount = IDirect3DDevice9_Release(device);
9253 ok(!refcount, "Device has %u references left.\n", refcount);
9255 if (d3d9) IDirect3D9_Release(d3d9);
9256 if (gl) FreeLibrary(gl);
9257 if (hdc) ReleaseDC(hwnd, hdc);
9258 if (hdc2) ReleaseDC(hwnd2, hdc2);
9259 if (hwnd) DestroyWindow(hwnd);
9260 if (hwnd2) DestroyWindow(hwnd2);
9263 static void test_begin_end_state_block(void)
9265 IDirect3DStateBlock9 *stateblock;
9266 IDirect3DDevice9 *device;
9267 IDirect3D9 *d3d;
9268 ULONG refcount;
9269 HWND window;
9270 HRESULT hr;
9272 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9273 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9274 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9275 ok(!!d3d, "Failed to create a D3D object.\n");
9276 if (!(device = create_device(d3d, window, NULL)))
9278 skip("Failed to create a D3D device, skipping tests.\n");
9279 IDirect3D9_Release(d3d);
9280 DestroyWindow(window);
9281 return;
9284 /* Should succeed. */
9285 hr = IDirect3DDevice9_BeginStateBlock(device);
9286 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
9288 /* Calling BeginStateBlock() while recording should return
9289 * D3DERR_INVALIDCALL. */
9290 hr = IDirect3DDevice9_BeginStateBlock(device);
9291 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9293 /* Should succeed. */
9294 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
9295 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9296 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
9297 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
9298 "Got unexpected stateblock %p.\n", stateblock);
9299 IDirect3DStateBlock9_Release(stateblock);
9301 /* Calling EndStateBlock() while not recording should return
9302 * D3DERR_INVALIDCALL. stateblock should not be touched. */
9303 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
9304 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9305 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9306 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
9307 "Got unexpected stateblock %p.\n", stateblock);
9309 refcount = IDirect3DDevice9_Release(device);
9310 ok(!refcount, "Device has %u references left.\n", refcount);
9311 IDirect3D9_Release(d3d);
9312 DestroyWindow(window);
9315 static void test_shader_constant_apply(void)
9317 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
9318 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
9319 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
9320 IDirect3DStateBlock9 *stateblock;
9321 DWORD vs_version, ps_version;
9322 IDirect3DDevice9 *device;
9323 IDirect3D9 *d3d;
9324 ULONG refcount;
9325 D3DCAPS9 caps;
9326 float ret[4];
9327 HWND window;
9328 HRESULT hr;
9330 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9331 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9332 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9333 ok(!!d3d, "Failed to create a D3D object.\n");
9334 if (!(device = create_device(d3d, window, NULL)))
9336 skip("Failed to create a D3D device, skipping tests.\n");
9337 IDirect3D9_Release(d3d);
9338 DestroyWindow(window);
9339 return;
9342 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9343 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9344 vs_version = caps.VertexShaderVersion & 0xffff;
9345 ps_version = caps.PixelShaderVersion & 0xffff;
9347 if (vs_version)
9349 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
9350 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9351 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
9352 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9354 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
9355 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9356 ok(!memcmp(ret, initial, sizeof(initial)),
9357 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9358 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9359 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
9360 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9361 ok(!memcmp(ret, initial, sizeof(initial)),
9362 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9363 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9365 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
9366 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9368 if (ps_version)
9370 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
9371 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9372 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
9373 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9375 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
9376 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9377 ok(!memcmp(ret, initial, sizeof(initial)),
9378 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9379 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9380 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
9381 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9382 ok(!memcmp(ret, initial, sizeof(initial)),
9383 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9384 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9386 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
9387 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9390 hr = IDirect3DDevice9_BeginStateBlock(device);
9391 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
9393 if (vs_version)
9395 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
9396 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9398 if (ps_version)
9400 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
9401 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9404 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9405 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
9407 if (vs_version)
9409 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
9410 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9411 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
9412 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9413 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
9414 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
9415 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9416 ok(!memcmp(ret, initial, sizeof(initial)),
9417 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9418 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9420 if (ps_version)
9422 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
9423 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9424 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
9425 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9426 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
9427 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
9428 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9429 ok(!memcmp(ret, initial, sizeof(initial)),
9430 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9431 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9434 /* Apply doesn't overwrite constants that aren't explicitly set on the
9435 * source stateblock. */
9436 hr = IDirect3DStateBlock9_Apply(stateblock);
9437 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
9439 if (vs_version)
9441 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
9442 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9443 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
9444 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9445 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
9446 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
9447 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9448 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
9449 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9450 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
9452 if (ps_version)
9454 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
9455 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9456 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
9457 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9458 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
9459 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
9460 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9461 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
9462 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9463 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
9466 IDirect3DStateBlock9_Release(stateblock);
9467 refcount = IDirect3DDevice9_Release(device);
9468 ok(!refcount, "Device has %u references left.\n", refcount);
9469 IDirect3D9_Release(d3d);
9470 DestroyWindow(window);
9473 static void test_vdecl_apply(void)
9475 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
9476 IDirect3DStateBlock9 *stateblock;
9477 IDirect3DDevice9 *device;
9478 IDirect3D9 *d3d;
9479 ULONG refcount;
9480 HWND window;
9481 HRESULT hr;
9483 static const D3DVERTEXELEMENT9 decl1[] =
9485 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9486 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9487 D3DDECL_END(),
9490 static const D3DVERTEXELEMENT9 decl2[] =
9492 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9493 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9494 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
9495 D3DDECL_END(),
9498 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9499 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9500 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9501 ok(!!d3d, "Failed to create a D3D object.\n");
9502 if (!(device = create_device(d3d, window, NULL)))
9504 skip("Failed to create a D3D device, skipping tests.\n");
9505 IDirect3D9_Release(d3d);
9506 DestroyWindow(window);
9507 return;
9510 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
9511 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
9513 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
9514 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
9516 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9517 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9518 hr = IDirect3DDevice9_BeginStateBlock(device);
9519 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
9520 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
9521 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9522 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9523 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
9524 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9525 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9526 hr = IDirect3DStateBlock9_Apply(stateblock);
9527 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9528 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9529 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9530 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
9531 declaration, declaration1);
9532 IDirect3DVertexDeclaration9_Release(declaration);
9534 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9535 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9536 hr = IDirect3DStateBlock9_Capture(stateblock);
9537 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9538 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9539 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9540 hr = IDirect3DStateBlock9_Apply(stateblock);
9541 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9542 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9543 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9544 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9545 declaration, declaration2);
9546 IDirect3DVertexDeclaration9_Release(declaration);
9548 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9549 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9550 hr = IDirect3DStateBlock9_Capture(stateblock);
9551 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9552 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9553 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9554 hr = IDirect3DStateBlock9_Apply(stateblock);
9555 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9556 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9557 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9558 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9559 declaration, declaration2);
9560 IDirect3DVertexDeclaration9_Release(declaration);
9562 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9563 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9564 hr = IDirect3DStateBlock9_Capture(stateblock);
9565 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9566 hr = IDirect3DStateBlock9_Apply(stateblock);
9567 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9568 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9569 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9570 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
9572 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9573 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9574 hr = IDirect3DStateBlock9_Capture(stateblock);
9575 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9576 hr = IDirect3DStateBlock9_Apply(stateblock);
9577 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9578 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9579 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9580 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9581 declaration, declaration2);
9582 IDirect3DVertexDeclaration9_Release(declaration);
9584 IDirect3DStateBlock9_Release(stateblock);
9585 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
9586 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9587 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
9588 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
9589 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9590 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9591 hr = IDirect3DStateBlock9_Apply(stateblock);
9592 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9593 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9594 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9595 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
9596 declaration, declaration1);
9597 IDirect3DVertexDeclaration9_Release(declaration);
9599 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9600 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9601 hr = IDirect3DStateBlock9_Capture(stateblock);
9602 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9603 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9604 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9605 hr = IDirect3DStateBlock9_Apply(stateblock);
9606 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9607 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9608 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9609 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9610 declaration, declaration2);
9611 IDirect3DVertexDeclaration9_Release(declaration);
9613 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9614 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9615 hr = IDirect3DStateBlock9_Capture(stateblock);
9616 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9617 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9618 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9619 hr = IDirect3DStateBlock9_Apply(stateblock);
9620 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9621 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9622 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9623 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9624 declaration, declaration2);
9625 IDirect3DVertexDeclaration9_Release(declaration);
9627 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9628 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9629 hr = IDirect3DStateBlock9_Capture(stateblock);
9630 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9631 hr = IDirect3DStateBlock9_Apply(stateblock);
9632 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9633 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9634 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9635 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
9637 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9638 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9639 hr = IDirect3DStateBlock9_Capture(stateblock);
9640 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9641 hr = IDirect3DStateBlock9_Apply(stateblock);
9642 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9643 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9644 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9645 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9646 declaration, declaration2);
9647 IDirect3DVertexDeclaration9_Release(declaration);
9649 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9650 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9651 IDirect3DVertexDeclaration9_Release(declaration1);
9652 IDirect3DVertexDeclaration9_Release(declaration2);
9653 IDirect3DStateBlock9_Release(stateblock);
9654 refcount = IDirect3DDevice9_Release(device);
9655 ok(!refcount, "Device has %u references left.\n", refcount);
9656 IDirect3D9_Release(d3d);
9657 DestroyWindow(window);
9660 static void test_resource_type(void)
9662 IDirect3DDevice9 *device;
9663 IDirect3DSurface9 *surface;
9664 IDirect3DTexture9 *texture;
9665 IDirect3DCubeTexture9 *cube_texture;
9666 IDirect3DVolume9 *volume;
9667 IDirect3DVolumeTexture9 *volume_texture;
9668 D3DSURFACE_DESC surface_desc;
9669 D3DVOLUME_DESC volume_desc;
9670 D3DRESOURCETYPE type;
9671 IDirect3D9 *d3d;
9672 ULONG refcount;
9673 HWND window;
9674 HRESULT hr;
9675 D3DCAPS9 caps;
9677 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9678 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9679 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9680 ok(!!d3d, "Failed to create a D3D object.\n");
9681 if (!(device = create_device(d3d, window, NULL)))
9683 skip("Failed to create a D3D device, skipping tests.\n");
9684 IDirect3D9_Release(d3d);
9685 DestroyWindow(window);
9686 return;
9689 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9690 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9692 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
9693 D3DPOOL_SYSTEMMEM, &surface, NULL);
9694 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9695 type = IDirect3DSurface9_GetType(surface);
9696 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
9697 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
9698 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
9699 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9700 surface_desc.Type);
9701 IDirect3DSurface9_Release(surface);
9703 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
9704 D3DPOOL_SYSTEMMEM, &texture, NULL);
9705 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
9706 type = IDirect3DTexture9_GetType(texture);
9707 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
9709 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
9710 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
9711 /* The following code crashes, for the sake of completeness:
9712 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
9713 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
9715 * So applications will not depend on getting the "right" resource type - whatever it
9716 * may be - from the "wrong" vtable. */
9717 type = IDirect3DSurface9_GetType(surface);
9718 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
9719 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
9720 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
9721 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9722 surface_desc.Type);
9723 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
9724 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
9725 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
9726 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
9727 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9728 surface_desc.Type);
9729 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
9730 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
9731 IDirect3DSurface9_Release(surface);
9733 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
9734 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
9735 type = IDirect3DSurface9_GetType(surface);
9736 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
9737 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
9738 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
9739 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9740 surface_desc.Type);
9741 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
9742 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
9743 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
9744 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
9745 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9746 surface_desc.Type);
9747 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
9748 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
9749 IDirect3DSurface9_Release(surface);
9750 IDirect3DTexture9_Release(texture);
9752 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9754 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
9755 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
9756 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
9757 type = IDirect3DCubeTexture9_GetType(cube_texture);
9758 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
9760 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
9761 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
9762 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
9763 type = IDirect3DSurface9_GetType(surface);
9764 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
9765 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
9766 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
9767 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9768 surface_desc.Type);
9769 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
9770 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
9771 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9772 surface_desc.Type);
9773 IDirect3DSurface9_Release(surface);
9774 IDirect3DCubeTexture9_Release(cube_texture);
9776 else
9777 skip("Cube maps not supported.\n");
9779 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
9781 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
9782 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
9783 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9784 type = IDirect3DVolumeTexture9_GetType(volume_texture);
9785 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
9787 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
9788 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
9789 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
9790 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
9791 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
9792 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
9793 volume_desc.Type);
9794 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
9795 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
9796 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
9797 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
9798 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
9799 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
9800 volume_desc.Type);
9801 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
9802 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
9803 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
9804 IDirect3DVolume9_Release(volume);
9806 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
9807 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
9808 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
9809 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
9810 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
9811 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
9812 volume_desc.Type);
9813 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
9814 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
9815 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
9816 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
9817 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
9818 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
9819 volume_desc.Type);
9820 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
9821 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
9822 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
9823 IDirect3DVolume9_Release(volume);
9824 IDirect3DVolumeTexture9_Release(volume_texture);
9826 else
9827 skip("Mipmapped volume maps not supported.\n");
9829 refcount = IDirect3DDevice9_Release(device);
9830 ok(!refcount, "Device has %u references left.\n", refcount);
9831 IDirect3D9_Release(d3d);
9832 DestroyWindow(window);
9835 static void test_mipmap_lock(void)
9837 IDirect3DDevice9 *device;
9838 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
9839 IDirect3DTexture9 *texture, *texture_dst;
9840 IDirect3D9 *d3d;
9841 ULONG refcount;
9842 HWND window;
9843 HRESULT hr;
9844 D3DLOCKED_RECT locked_rect;
9846 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9847 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9848 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9849 ok(!!d3d, "Failed to create a D3D object.\n");
9850 if (!(device = create_device(d3d, window, NULL)))
9852 skip("Failed to create a D3D device, skipping tests.\n");
9853 IDirect3D9_Release(d3d);
9854 DestroyWindow(window);
9855 return;
9858 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
9859 D3DPOOL_DEFAULT, &texture_dst, NULL);
9860 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
9861 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
9862 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
9863 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
9864 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
9866 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
9867 D3DPOOL_SYSTEMMEM, &texture, NULL);
9868 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
9869 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
9870 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
9871 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
9872 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
9874 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
9875 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9876 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
9877 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
9878 hr = IDirect3DSurface9_UnlockRect(surface);
9879 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9881 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
9882 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
9883 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
9884 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9886 /* Apparently there's no validation on the container. */
9887 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
9888 (IDirect3DBaseTexture9 *)texture_dst);
9889 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
9891 hr = IDirect3DSurface9_UnlockRect(surface2);
9892 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9894 IDirect3DSurface9_Release(surface_dst2);
9895 IDirect3DSurface9_Release(surface_dst);
9896 IDirect3DSurface9_Release(surface2);
9897 IDirect3DSurface9_Release(surface);
9898 IDirect3DTexture9_Release(texture_dst);
9899 IDirect3DTexture9_Release(texture);
9901 refcount = IDirect3DDevice9_Release(device);
9902 ok(!refcount, "Device has %u references left.\n", refcount);
9903 IDirect3D9_Release(d3d);
9904 DestroyWindow(window);
9907 static void test_writeonly_resource(void)
9909 IDirect3D9 *d3d;
9910 IDirect3DDevice9 *device;
9911 IDirect3DVertexBuffer9 *buffer;
9912 ULONG refcount;
9913 HWND window;
9914 HRESULT hr;
9915 void *ptr;
9916 static const struct
9918 struct vec3 pos;
9920 quad[] =
9922 {{-1.0f, -1.0f, 0.0f}},
9923 {{-1.0f, 1.0f, 0.0f}},
9924 {{ 1.0f, -1.0f, 0.0f}},
9925 {{ 1.0f, 1.0f, 0.0f}}
9928 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9929 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9930 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9931 ok(!!d3d, "Failed to create a D3D object.\n");
9932 if (!(device = create_device(d3d, window, NULL)))
9934 skip("Failed to create a D3D device, skipping tests.\n");
9935 IDirect3D9_Release(d3d);
9936 DestroyWindow(window);
9937 return;
9940 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
9941 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
9942 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9944 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
9945 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9946 memcpy(ptr, quad, sizeof(quad));
9947 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9948 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9949 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
9950 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9951 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9952 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
9954 hr = IDirect3DDevice9_BeginScene(device);
9955 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
9956 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
9957 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9958 hr = IDirect3DDevice9_EndScene(device);
9959 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
9961 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
9962 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9963 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9964 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9965 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9967 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
9968 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
9969 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
9970 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9971 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
9973 refcount = IDirect3DVertexBuffer9_Release(buffer);
9974 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
9975 refcount = IDirect3DDevice9_Release(device);
9976 ok(!refcount, "Device has %u references left.\n", refcount);
9977 IDirect3D9_Release(d3d);
9978 DestroyWindow(window);
9981 static void test_lost_device(void)
9983 struct device_desc device_desc;
9984 IDirect3DDevice9 *device;
9985 IDirect3D9 *d3d;
9986 ULONG refcount;
9987 HWND window;
9988 HRESULT hr;
9989 BOOL ret;
9991 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9992 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9993 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9994 ok(!!d3d, "Failed to create a D3D object.\n");
9995 device_desc.device_window = window;
9996 device_desc.width = registry_mode.dmPelsWidth;
9997 device_desc.height = registry_mode.dmPelsHeight;
9998 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
9999 if (!(device = create_device(d3d, window, &device_desc)))
10001 skip("Failed to create a D3D device, skipping tests.\n");
10002 goto done;
10005 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10006 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10007 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10008 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10010 ret = SetForegroundWindow(GetDesktopWindow());
10011 ok(ret, "Failed to set foreground window.\n");
10012 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10013 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10014 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10015 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10017 ret = ShowWindow(window, SW_RESTORE);
10018 ok(ret, "Failed to restore window.\n");
10019 ret = SetForegroundWindow(window);
10020 ok(ret, "Failed to set foreground window.\n");
10021 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10022 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
10023 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10024 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10026 hr = reset_device(device, &device_desc);
10027 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10028 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10029 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10030 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10031 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10033 device_desc.flags = 0;
10034 hr = reset_device(device, &device_desc);
10035 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10036 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10037 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10038 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10039 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10041 ret = SetForegroundWindow(GetDesktopWindow());
10042 ok(ret, "Failed to set foreground window.\n");
10043 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10044 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10045 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10046 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10048 ret = ShowWindow(window, SW_RESTORE);
10049 ok(ret, "Failed to restore window.\n");
10050 ret = SetForegroundWindow(window);
10051 ok(ret, "Failed to set foreground window.\n");
10052 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10053 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10054 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10055 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10057 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10058 hr = reset_device(device, &device_desc);
10059 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10060 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10061 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10062 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10063 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10065 ret = SetForegroundWindow(GetDesktopWindow());
10066 ok(ret, "Failed to set foreground window.\n");
10067 hr = reset_device(device, &device_desc);
10068 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10069 ret = ShowWindow(window, SW_RESTORE);
10070 ok(ret, "Failed to restore window.\n");
10071 ret = SetForegroundWindow(window);
10072 ok(ret, "Failed to set foreground window.\n");
10073 hr = reset_device(device, &device_desc);
10074 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10076 refcount = IDirect3DDevice9_Release(device);
10077 ok(!refcount, "Device has %u references left.\n", refcount);
10078 done:
10079 IDirect3D9_Release(d3d);
10080 DestroyWindow(window);
10083 static void test_resource_priority(void)
10085 IDirect3DDevice9 *device;
10086 IDirect3DSurface9 *surface;
10087 IDirect3DTexture9 *texture;
10088 IDirect3DVertexBuffer9 *buffer;
10089 IDirect3D9 *d3d;
10090 ULONG refcount;
10091 HWND window;
10092 HRESULT hr;
10093 static const struct
10095 D3DPOOL pool;
10096 const char *name;
10097 BOOL can_set_priority;
10099 test_data[] =
10101 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
10102 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
10103 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
10104 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
10106 unsigned int i;
10107 DWORD priority;
10109 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10110 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10111 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10112 ok(!!d3d, "Failed to create a D3D object.\n");
10113 if (!(device = create_device(d3d, window, NULL)))
10115 skip("Failed to create a D3D device, skipping tests.\n");
10116 IDirect3D9_Release(d3d);
10117 DestroyWindow(window);
10118 return;
10121 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
10123 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
10124 test_data[i].pool, &texture, NULL);
10125 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
10126 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10127 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10129 priority = IDirect3DTexture9_GetPriority(texture);
10130 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10131 priority = IDirect3DTexture9_SetPriority(texture, 1);
10132 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10133 priority = IDirect3DTexture9_GetPriority(texture);
10134 if (test_data[i].can_set_priority)
10136 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10137 priority = IDirect3DTexture9_SetPriority(texture, 2);
10138 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10140 else
10141 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10143 priority = IDirect3DSurface9_GetPriority(surface);
10144 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10145 priority = IDirect3DSurface9_SetPriority(surface, 1);
10146 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10147 priority = IDirect3DSurface9_GetPriority(surface);
10148 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10150 IDirect3DSurface9_Release(surface);
10151 IDirect3DTexture9_Release(texture);
10153 if (test_data[i].pool != D3DPOOL_MANAGED)
10155 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
10156 test_data[i].pool, &surface, NULL);
10157 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
10159 priority = IDirect3DSurface9_GetPriority(surface);
10160 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10161 priority = IDirect3DSurface9_SetPriority(surface, 1);
10162 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10163 priority = IDirect3DSurface9_GetPriority(surface);
10164 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10166 IDirect3DSurface9_Release(surface);
10169 if (test_data[i].pool != D3DPOOL_SCRATCH)
10171 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
10172 test_data[i].pool, &buffer, NULL);
10173 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
10175 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10176 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10177 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
10178 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10179 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10180 if (test_data[i].can_set_priority)
10182 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10183 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
10184 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10186 else
10187 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10189 IDirect3DVertexBuffer9_Release(buffer);
10193 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
10194 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
10196 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
10197 priority = IDirect3DSurface9_GetPriority(surface);
10198 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10199 priority = IDirect3DSurface9_SetPriority(surface, 1);
10200 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10201 priority = IDirect3DSurface9_GetPriority(surface);
10202 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10204 IDirect3DSurface9_Release(surface);
10206 refcount = IDirect3DDevice9_Release(device);
10207 ok(!refcount, "Device has %u references left.\n", refcount);
10208 IDirect3D9_Release(d3d);
10209 DestroyWindow(window);
10212 static void test_swapchain_parameters(void)
10214 IDirect3DDevice9 *device;
10215 IDirect3D9 *d3d;
10216 HWND window;
10217 HRESULT hr;
10218 unsigned int i;
10219 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
10220 IDirect3DSwapChain9 *swapchain;
10221 static const struct
10223 BOOL windowed;
10224 UINT backbuffer_count;
10225 D3DSWAPEFFECT swap_effect;
10226 HRESULT hr;
10228 tests[] =
10230 /* Swap effect 0 is not allowed. */
10231 {TRUE, 1, 0, D3DERR_INVALIDCALL},
10232 {FALSE, 1, 0, D3DERR_INVALIDCALL},
10234 /* All (non-ex) swap effects are allowed in
10235 * windowed and fullscreen mode. */
10236 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10237 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10238 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10239 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10240 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10242 /* Only one backbuffer in copy mode. */
10243 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
10244 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10245 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10246 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10248 /* Ok with the others, in fullscreen and windowed mode. */
10249 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
10250 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
10251 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
10252 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
10254 /* D3D9Ex swap effects. */
10255 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
10256 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
10257 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
10258 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
10259 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
10260 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
10262 /* 3 is the highest allowed backbuffer count. */
10263 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
10264 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
10265 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
10266 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
10267 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
10270 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10271 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10272 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10273 ok(!!d3d, "Failed to create a D3D object.\n");
10274 if (!(device = create_device(d3d, window, NULL)))
10276 skip("Failed to create a D3D device, skipping tests.\n");
10277 IDirect3D9_Release(d3d);
10278 DestroyWindow(window);
10279 return;
10281 IDirect3DDevice9_Release(device);
10283 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
10284 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
10285 present_parameters_windowed.hDeviceWindow = window;
10286 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
10287 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
10288 present_parameters_windowed.Windowed = TRUE;
10289 present_parameters_windowed.BackBufferCount = 1;
10291 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
10293 memset(&present_parameters, 0, sizeof(present_parameters));
10294 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
10295 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
10296 present_parameters.hDeviceWindow = window;
10297 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
10299 present_parameters.SwapEffect = tests[i].swap_effect;
10300 present_parameters.Windowed = tests[i].windowed;
10301 present_parameters.BackBufferCount = tests[i].backbuffer_count;
10303 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
10304 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
10305 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
10306 if (SUCCEEDED(hr))
10308 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
10310 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
10311 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
10313 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
10314 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
10315 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
10316 tests[i].swap_effect, present_parameters2.SwapEffect, i);
10317 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
10318 bb_count, present_parameters2.BackBufferCount, i);
10319 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
10320 tests[i].windowed, present_parameters2.Windowed, i);
10322 IDirect3DSwapChain9_Release(swapchain);
10323 IDirect3DDevice9_Release(device);
10326 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
10327 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
10328 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
10330 memset(&present_parameters, 0, sizeof(present_parameters));
10331 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
10332 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
10333 present_parameters.hDeviceWindow = window;
10334 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
10336 present_parameters.SwapEffect = tests[i].swap_effect;
10337 present_parameters.Windowed = tests[i].windowed;
10338 present_parameters.BackBufferCount = tests[i].backbuffer_count;
10340 hr = IDirect3DDevice9_Reset(device, &present_parameters);
10341 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
10343 if (FAILED(hr))
10345 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
10346 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
10348 IDirect3DDevice9_Release(device);
10351 IDirect3D9_Release(d3d);
10352 DestroyWindow(window);
10355 START_TEST(device)
10357 WNDCLASSA wc = {0};
10358 IDirect3D9 *d3d9;
10359 DEVMODEW current_mode;
10361 memset(&current_mode, 0, sizeof(current_mode));
10362 current_mode.dmSize = sizeof(current_mode);
10363 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
10364 registry_mode.dmSize = sizeof(registry_mode);
10365 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
10366 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
10367 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
10369 skip("Current mode does not match registry mode, skipping test.\n");
10370 return;
10373 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
10375 skip("could not create D3D9 object\n");
10376 return;
10378 IDirect3D9_Release(d3d9);
10380 wc.lpfnWndProc = DefWindowProcA;
10381 wc.lpszClassName = "d3d9_test_wc";
10382 RegisterClassA(&wc);
10384 test_get_set_vertex_declaration();
10385 test_get_declaration();
10386 test_fvf_decl_conversion();
10387 test_fvf_decl_management();
10388 test_vertex_declaration_alignment();
10389 test_unused_declaration_type();
10390 test_fpu_setup();
10391 test_multi_device();
10392 test_display_formats();
10393 test_display_modes();
10394 test_swapchain();
10395 test_refcount();
10396 test_mipmap_levels();
10397 test_checkdevicemultisampletype();
10398 test_cursor();
10399 test_cursor_pos();
10400 test_reset_fullscreen();
10401 test_reset();
10402 test_scene();
10403 test_limits();
10404 test_depthstenciltest();
10405 test_get_rt();
10406 test_draw_indexed();
10407 test_null_stream();
10408 test_lights();
10409 test_set_stream_source();
10410 test_scissor_size();
10411 test_wndproc();
10412 test_wndproc_windowed();
10413 test_window_style();
10414 test_mode_change();
10415 test_device_window_reset();
10416 test_reset_resources();
10417 test_set_rt_vp_scissor();
10418 test_volume_get_container();
10419 test_volume_resource();
10420 test_vb_lock_flags();
10421 test_vertex_buffer_alignment();
10422 test_query_support();
10423 test_occlusion_query_states();
10424 test_timestamp_query();
10425 test_get_set_vertex_shader();
10426 test_vertex_shader_constant();
10427 test_get_set_pixel_shader();
10428 test_pixel_shader_constant();
10429 test_unsupported_shaders();
10430 test_texture_stage_states();
10431 test_cube_textures();
10432 test_mipmap_gen();
10433 test_filter();
10434 test_get_set_texture();
10435 test_lod();
10436 test_surface_get_container();
10437 test_surface_alignment();
10438 test_lockrect_offset();
10439 test_lockrect_invalid();
10440 test_private_data();
10441 test_getdc();
10442 test_surface_dimensions();
10443 test_surface_format_null();
10444 test_surface_double_unlock();
10445 test_surface_blocks();
10446 test_set_palette();
10447 test_swvp_buffer();
10448 test_npot_textures();
10449 test_vidmem_accounting();
10450 test_volume_locking();
10451 test_update_volumetexture();
10452 test_create_rt_ds_fail();
10453 test_volume_blocks();
10454 test_lockbox_invalid();
10455 test_shared_handle();
10456 test_pixel_format();
10457 test_begin_end_state_block();
10458 test_shader_constant_apply();
10459 test_vdecl_apply();
10460 test_resource_type();
10461 test_mipmap_lock();
10462 test_writeonly_resource();
10463 test_lost_device();
10464 test_resource_priority();
10465 test_swapchain_parameters();
10467 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));