d3d9/tests: Test invalid locks with textures.
[wine.git] / dlls / d3d9 / tests / device.c
blobed5f7310b49b84cb58da43880853afcb54271a99
1 /*
2 * Copyright (C) 2006 Ivan Gyurdiev
3 * Copyright (C) 2006 Vitaliy Margolen
4 * Copyright (C) 2006 Chris Robinson
5 * Copyright 2006-2008, 2010-2011, 2013 Stefan Dösinger for CodeWeavers
6 * Copyright 2005, 2006, 2007 Henri Verbeet
7 * Copyright 2013-2014 Henri Verbeet for CodeWeavers
8 * Copyright (C) 2008 Rico Schüller
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WINVER 0x0602 /* for CURSOR_SUPPRESSED */
26 #define COBJMACROS
27 #include <d3d9.h>
28 #include "wine/test.h"
30 struct vec3
32 float x, y, z;
35 #define CREATE_DEVICE_FULLSCREEN 0x01
36 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
37 #define CREATE_DEVICE_FPU_PRESERVE 0x04
38 #define CREATE_DEVICE_SWVP_ONLY 0x08
40 struct device_desc
42 HWND device_window;
43 unsigned int width;
44 unsigned int height;
45 DWORD flags;
48 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
49 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
51 static DEVMODEW registry_mode;
53 static const DWORD simple_vs[] =
55 0xfffe0101, /* vs_1_1 */
56 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
57 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
58 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
59 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
60 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
61 0x0000ffff, /* end */
64 static const DWORD simple_ps[] =
66 0xffff0101, /* ps_1_1 */
67 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
68 0x00000042, 0xb00f0000, /* tex t0 */
69 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
70 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
71 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
72 0x0000ffff, /* end */
75 static int get_refcount(IUnknown *object)
77 IUnknown_AddRef( object );
78 return IUnknown_Release( object );
81 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
83 unsigned int element_count, i;
84 D3DVERTEXELEMENT9 *elements;
85 BOOL equal = TRUE;
86 HRESULT hr;
88 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
89 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
90 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
91 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
92 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
94 for (i = 0; i < element_count; ++i)
96 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
98 equal = FALSE;
99 break;
103 if (!equal)
105 for (i = 0; i < element_count; ++i)
107 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
108 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
109 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
113 HeapFree(GetProcessHeap(), 0, elements);
114 return equal;
117 /* try to make sure pending X events have been processed before continuing */
118 static void flush_events(void)
120 MSG msg;
121 int diff = 200;
122 int min_timeout = 100;
123 DWORD time = GetTickCount() + diff;
125 while (diff > 0)
127 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
128 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
129 diff = time - GetTickCount();
133 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
135 D3DPRESENT_PARAMETERS present_parameters = {0};
136 IDirect3DDevice9 *device;
137 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
139 present_parameters.BackBufferWidth = 640;
140 present_parameters.BackBufferHeight = 480;
141 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
142 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
143 present_parameters.hDeviceWindow = focus_window;
144 present_parameters.Windowed = TRUE;
145 present_parameters.EnableAutoDepthStencil = TRUE;
146 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
148 if (desc)
150 present_parameters.BackBufferWidth = desc->width;
151 present_parameters.BackBufferHeight = desc->height;
152 present_parameters.hDeviceWindow = desc->device_window;
153 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
154 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
155 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
156 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
157 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
158 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
159 behavior_flags |= D3DCREATE_FPU_PRESERVE;
162 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
163 behavior_flags, &present_parameters, &device)))
164 return device;
166 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
167 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
168 behavior_flags, &present_parameters, &device)))
169 return device;
171 if (desc && desc->flags & CREATE_DEVICE_SWVP_ONLY)
172 return NULL;
173 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
175 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
176 behavior_flags, &present_parameters, &device)))
177 return device;
179 return NULL;
182 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
184 D3DPRESENT_PARAMETERS present_parameters = {0};
186 present_parameters.BackBufferWidth = 640;
187 present_parameters.BackBufferHeight = 480;
188 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
189 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
190 present_parameters.hDeviceWindow = NULL;
191 present_parameters.Windowed = TRUE;
192 present_parameters.EnableAutoDepthStencil = TRUE;
193 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
195 if (desc)
197 present_parameters.BackBufferWidth = desc->width;
198 present_parameters.BackBufferHeight = desc->height;
199 present_parameters.hDeviceWindow = desc->device_window;
200 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
203 return IDirect3DDevice9_Reset(device, &present_parameters);
206 #define CHECK_CALL(r,c,d,rc) \
207 if (SUCCEEDED(r)) {\
208 int tmp1 = get_refcount( (IUnknown *)d ); \
209 int rc_new = rc; \
210 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
211 } else {\
212 trace("%s failed: %08x\n", c, r); \
215 #define CHECK_RELEASE(obj,d,rc) \
216 if (obj) { \
217 int tmp1, rc_new = rc; \
218 IUnknown_Release( (IUnknown*)obj ); \
219 tmp1 = get_refcount( (IUnknown *)d ); \
220 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
223 #define CHECK_REFCOUNT(obj,rc) \
225 int rc_new = rc; \
226 int count = get_refcount( (IUnknown *)obj ); \
227 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
230 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
232 int rc_new = rc; \
233 int count = IUnknown_Release( (IUnknown *)obj ); \
234 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
237 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
239 int rc_new = rc; \
240 int count = IUnknown_AddRef( (IUnknown *)obj ); \
241 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
244 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
246 void *container_ptr = (void *)0x1337c0d3; \
247 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
248 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
249 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
250 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
253 static void test_get_set_vertex_declaration(void)
255 IDirect3DVertexDeclaration9 *declaration, *tmp;
256 ULONG refcount, expected_refcount;
257 IDirect3DDevice9 *device;
258 IDirect3D9 *d3d;
259 HWND window;
260 HRESULT hr;
262 static const D3DVERTEXELEMENT9 simple_decl[] =
264 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
265 D3DDECL_END()
268 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
269 0, 0, 640, 480, NULL, NULL, NULL, NULL);
270 d3d = Direct3DCreate9(D3D_SDK_VERSION);
271 ok(!!d3d, "Failed to create a D3D object.\n");
272 if (!(device = create_device(d3d, window, NULL)))
274 skip("Failed to create a D3D device, skipping tests.\n");
275 goto done;
278 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
279 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
281 /* SetVertexDeclaration() should not touch the declaration's refcount. */
282 expected_refcount = get_refcount((IUnknown *)declaration);
283 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
284 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
285 refcount = get_refcount((IUnknown *)declaration);
286 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
288 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
289 tmp = NULL;
290 expected_refcount = refcount + 1;
291 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
292 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
293 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
294 refcount = get_refcount((IUnknown *)declaration);
295 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
296 IDirect3DVertexDeclaration9_Release(tmp);
298 IDirect3DVertexDeclaration9_Release(declaration);
299 refcount = IDirect3DDevice9_Release(device);
300 ok(!refcount, "Device has %u references left.\n", refcount);
301 done:
302 IDirect3D9_Release(d3d);
303 DestroyWindow(window);
306 static void test_get_declaration(void)
308 unsigned int element_count, expected_element_count;
309 IDirect3DVertexDeclaration9 *declaration;
310 D3DVERTEXELEMENT9 *elements;
311 IDirect3DDevice9 *device;
312 IDirect3D9 *d3d;
313 ULONG refcount;
314 HWND window;
315 HRESULT hr;
317 static const D3DVERTEXELEMENT9 simple_decl[] =
319 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
320 D3DDECL_END()
323 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
324 0, 0, 640, 480, NULL, NULL, NULL, NULL);
325 d3d = Direct3DCreate9(D3D_SDK_VERSION);
326 ok(!!d3d, "Failed to create a D3D object.\n");
327 if (!(device = create_device(d3d, window, NULL)))
329 skip("Failed to create a D3D device, skipping tests.\n");
330 goto done;
333 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
334 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
336 /* First test only getting the number of elements. */
337 element_count = 0x1337c0de;
338 expected_element_count = sizeof(simple_decl) / sizeof(*simple_decl);
339 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
340 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
341 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
342 element_count, expected_element_count);
344 element_count = 0;
345 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
346 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
347 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
348 element_count, expected_element_count);
350 /* Also test the returned data. */
351 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
353 element_count = 0x1337c0de;
354 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
355 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
356 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
357 element_count, expected_element_count);
358 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
359 "Original and returned vertexdeclarations are not the same.\n");
361 memset(elements, 0, sizeof(simple_decl));
363 element_count = 0;
364 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
365 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
366 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
367 element_count, expected_element_count);
368 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
369 "Original and returned vertexdeclarations are not the same.\n");
371 HeapFree(GetProcessHeap(), 0, elements);
372 IDirect3DVertexDeclaration9_Release(declaration);
373 refcount = IDirect3DDevice9_Release(device);
374 ok(!refcount, "Device has %u references left.\n", refcount);
375 done:
376 IDirect3D9_Release(d3d);
377 DestroyWindow(window);
380 static void test_fvf_decl_conversion(void)
382 IDirect3DVertexDeclaration9 *default_decl;
383 IDirect3DVertexDeclaration9 *declaration;
384 IDirect3DDevice9 *device;
385 IDirect3D9 *d3d;
386 ULONG refcount;
387 unsigned int i;
388 HWND window;
389 HRESULT hr;
391 static const D3DVERTEXELEMENT9 default_elements[] =
393 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
394 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
395 D3DDECL_END()
397 /* Test conversions from vertex declaration to an FVF. For some reason
398 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
399 * forced to 0 - maybe this is configuration specific. */
400 static const struct
402 D3DVERTEXELEMENT9 elements[7];
403 DWORD fvf;
404 BOOL todo;
406 decl_to_fvf_tests[] =
408 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
409 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
410 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
411 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
412 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
413 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
414 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
415 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
416 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
417 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
418 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
419 /* No FVF mapping available. */
420 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
421 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
422 /* Try empty declaration. */
423 {{ D3DDECL_END()}, 0, FALSE},
424 /* Make sure textures of different sizes work. */
425 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
426 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
427 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
428 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
429 /* Make sure the TEXCOORD index works correctly - try several textures. */
432 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
433 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
434 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
435 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
436 D3DDECL_END(),
437 }, 0, FALSE,
439 /* Now try a combination test. */
442 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
443 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
444 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
445 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
446 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
447 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
448 D3DDECL_END(),
449 }, 0, FALSE,
452 /* Test conversions from FVF to a vertex declaration. These seem to always
453 * occur internally. A new declaration object is created if necessary. */
454 static const struct
456 DWORD fvf;
457 D3DVERTEXELEMENT9 elements[7];
459 fvf_to_decl_tests[] =
461 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
462 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
463 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
465 D3DFVF_XYZB5,
467 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
468 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
469 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
470 D3DDECL_END(),
474 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
476 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
477 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
478 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
479 D3DDECL_END(),
483 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
485 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
486 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
487 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
488 D3DDECL_END(),
492 D3DFVF_XYZB1,
494 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
495 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
496 D3DDECL_END(),
500 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
502 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
503 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
504 D3DDECL_END(),
508 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
510 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
511 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
512 D3DDECL_END(),
516 D3DFVF_XYZB2,
518 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
519 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
520 D3DDECL_END(),
524 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
526 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
527 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
528 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
529 D3DDECL_END(),
533 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
535 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
536 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
537 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
538 D3DDECL_END(),
542 D3DFVF_XYZB3,
544 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
545 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
546 D3DDECL_END(),
550 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
552 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
553 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
554 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
555 D3DDECL_END(),
559 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
561 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
562 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
563 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
564 D3DDECL_END(),
568 D3DFVF_XYZB4,
570 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
571 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
572 D3DDECL_END(),
576 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
578 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
579 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
580 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
581 D3DDECL_END(),
585 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
587 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
588 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
589 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
590 D3DDECL_END(),
593 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
594 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
595 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
596 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
597 /* Make sure textures of different sizes work. */
599 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
600 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
603 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
604 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
607 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
608 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
611 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
612 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
614 /* Make sure the TEXCOORD index works correctly - try several textures. */
616 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
617 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
619 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
620 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
621 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
622 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
623 D3DDECL_END(),
626 /* Now try a combination test. */
628 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
629 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
631 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
632 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
633 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
634 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
635 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
636 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
637 D3DDECL_END(),
642 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
643 0, 0, 640, 480, NULL, NULL, NULL, NULL);
644 d3d = Direct3DCreate9(D3D_SDK_VERSION);
645 ok(!!d3d, "Failed to create a D3D object.\n");
646 if (!(device = create_device(d3d, window, NULL)))
648 skip("Failed to create a D3D device, skipping tests.\n");
649 goto done;
652 for (i = 0; i < sizeof(decl_to_fvf_tests) / sizeof(*decl_to_fvf_tests); ++i)
654 DWORD fvf = 0xdeadbeef;
655 HRESULT hr;
657 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
658 * back to 0. */
659 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
660 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
662 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
663 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
664 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
665 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
667 /* Check the FVF. */
668 hr = IDirect3DDevice9_GetFVF(device, &fvf);
669 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
671 if (decl_to_fvf_tests[i].todo)
672 todo_wine ok(fvf == decl_to_fvf_tests[i].fvf,
673 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
674 i, fvf, decl_to_fvf_tests[i].fvf);
675 else
676 ok(fvf == decl_to_fvf_tests[i].fvf,
677 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
678 i, fvf, decl_to_fvf_tests[i].fvf);
680 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
681 IDirect3DVertexDeclaration9_Release(declaration);
684 /* Create a default declaration and FVF that does not match any of the
685 * tests. */
686 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
687 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
689 for (i = 0; i < sizeof(fvf_to_decl_tests) / sizeof(*fvf_to_decl_tests); ++i)
691 /* Set a default declaration to make sure it is changed. */
692 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
693 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
695 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
696 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
698 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
699 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
700 ok(!!declaration && declaration != default_decl,
701 "Test %u: Got unexpected declaration %p.\n", i, declaration);
702 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
703 "Test %u: Declaration does not match.\n", i);
704 IDirect3DVertexDeclaration9_Release(declaration);
707 /* Setting the FVF to 0 should result in no change to the default decl. */
708 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
709 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
710 hr = IDirect3DDevice9_SetFVF(device, 0);
711 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
712 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
713 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
714 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
715 IDirect3DVertexDeclaration9_Release(declaration);
717 IDirect3DVertexDeclaration9_Release(default_decl);
718 refcount = IDirect3DDevice9_Release(device);
719 ok(!refcount, "Device has %u references left.\n", refcount);
720 done:
721 IDirect3D9_Release(d3d);
722 DestroyWindow(window);
725 /* Check whether a declaration converted from FVF is shared.
726 * Check whether refcounts behave as expected. */
727 static void test_fvf_decl_management(void)
729 IDirect3DVertexDeclaration9 *declaration1;
730 IDirect3DVertexDeclaration9 *declaration2;
731 IDirect3DVertexDeclaration9 *declaration3;
732 IDirect3DVertexDeclaration9 *declaration4;
733 IDirect3DDevice9 *device;
734 IDirect3D9 *d3d;
735 ULONG refcount;
736 HWND window;
737 HRESULT hr;
739 static const D3DVERTEXELEMENT9 test_elements1[] =
740 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
741 static const D3DVERTEXELEMENT9 test_elements2[] =
742 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
744 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
745 0, 0, 640, 480, NULL, NULL, NULL, NULL);
746 d3d = Direct3DCreate9(D3D_SDK_VERSION);
747 ok(!!d3d, "Failed to create a D3D object.\n");
748 if (!(device = create_device(d3d, window, NULL)))
750 skip("Failed to create a D3D device, skipping tests.\n");
751 goto done;
754 /* Clear down any current vertex declaration. */
755 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
756 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
757 /* Conversion. */
758 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
759 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
760 /* Get converted decl (#1). */
761 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
762 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
763 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
764 /* Get converted decl again (#2). */
765 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
766 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
767 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
769 /* Conversion. */
770 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
771 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
772 /* Get converted decl (#3). */
773 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
774 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
775 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
776 /* The contents should correspond to the second conversion. */
777 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
778 /* Re-Check if the first decl was overwritten by the new Get(). */
779 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
781 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
782 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
783 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
784 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
785 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
787 refcount = get_refcount((IUnknown*)declaration1);
788 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
789 refcount = get_refcount((IUnknown*)declaration2);
790 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
791 refcount = get_refcount((IUnknown*)declaration3);
792 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
793 refcount = get_refcount((IUnknown*)declaration4);
794 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
796 IDirect3DVertexDeclaration9_Release(declaration4);
797 IDirect3DVertexDeclaration9_Release(declaration3);
798 IDirect3DVertexDeclaration9_Release(declaration2);
799 IDirect3DVertexDeclaration9_Release(declaration1);
801 refcount = IDirect3DDevice9_Release(device);
802 ok(!refcount, "Device has %u references left.\n", refcount);
803 done:
804 IDirect3D9_Release(d3d);
805 DestroyWindow(window);
808 static void test_vertex_declaration_alignment(void)
810 IDirect3DVertexDeclaration9 *declaration;
811 IDirect3DDevice9 *device;
812 IDirect3D9 *d3d;
813 unsigned int i;
814 ULONG refcount;
815 HWND window;
816 HRESULT hr;
818 static const struct
820 D3DVERTEXELEMENT9 elements[3];
821 HRESULT hr;
823 test_data[] =
827 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
828 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
829 D3DDECL_END(),
830 }, D3D_OK,
834 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
835 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
836 D3DDECL_END(),
837 }, E_FAIL,
841 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
842 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
843 D3DDECL_END(),
844 }, E_FAIL,
848 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
849 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
850 D3DDECL_END(),
851 }, E_FAIL,
855 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
856 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
857 D3DDECL_END(),
858 }, D3D_OK,
862 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
863 0, 0, 640, 480, NULL, NULL, NULL, NULL);
864 d3d = Direct3DCreate9(D3D_SDK_VERSION);
865 ok(!!d3d, "Failed to create a D3D object.\n");
866 if (!(device = create_device(d3d, window, NULL)))
868 skip("Failed to create a D3D device, skipping tests.\n");
869 goto done;
872 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
874 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
875 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
876 if (SUCCEEDED(hr))
877 IDirect3DVertexDeclaration9_Release(declaration);
880 refcount = IDirect3DDevice9_Release(device);
881 ok(!refcount, "Device has %u references left.\n", refcount);
882 done:
883 IDirect3D9_Release(d3d);
884 DestroyWindow(window);
887 static void test_unused_declaration_type(void)
889 IDirect3DVertexDeclaration9 *declaration;
890 IDirect3DDevice9 *device;
891 IDirect3D9 *d3d;
892 unsigned int i;
893 ULONG refcount;
894 HWND window;
895 HRESULT hr;
897 static const D3DVERTEXELEMENT9 test_elements[][3] =
900 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
901 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
902 D3DDECL_END(),
905 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
906 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
907 D3DDECL_END(),
910 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
911 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
912 D3DDECL_END(),
915 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
916 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
917 D3DDECL_END(),
920 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
921 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
922 D3DDECL_END(),
925 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
926 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
927 D3DDECL_END(),
930 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
931 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
932 D3DDECL_END(),
936 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
937 0, 0, 640, 480, NULL, NULL, NULL, NULL);
938 d3d = Direct3DCreate9(D3D_SDK_VERSION);
939 ok(!!d3d, "Failed to create a D3D object.\n");
940 if (!(device = create_device(d3d, window, NULL)))
942 skip("Failed to create a D3D device, skipping tests.\n");
943 goto done;
946 for (i = 0; i < sizeof(test_elements) / sizeof(*test_elements); ++i)
948 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
949 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
952 refcount = IDirect3DDevice9_Release(device);
953 ok(!refcount, "Device has %u references left.\n", refcount);
954 done:
955 IDirect3D9_Release(d3d);
956 DestroyWindow(window);
959 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
961 IDirect3DBaseTexture9* texture = NULL;
962 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
963 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
965 if (SUCCEEDED(hr)) {
966 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
967 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
968 } else
969 trace("CreateTexture failed: %08x\n", hr);
971 if (texture) IDirect3DBaseTexture9_Release( texture );
974 static void test_mipmap_levels(void)
976 IDirect3DDevice9 *device;
977 IDirect3D9 *d3d;
978 ULONG refcount;
979 HWND window;
981 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
982 0, 0, 640, 480, NULL, NULL, NULL, NULL);
983 ok(!!window, "Failed to create a window.\n");
984 d3d = Direct3DCreate9(D3D_SDK_VERSION);
985 ok(!!d3d, "Failed to create a D3D object.\n");
986 if (!(device = create_device(d3d, window, NULL)))
988 skip("Failed to create a 3D device, skipping test.\n");
989 goto cleanup;
992 check_mipmap_levels(device, 32, 32, 6);
993 check_mipmap_levels(device, 256, 1, 9);
994 check_mipmap_levels(device, 1, 256, 9);
995 check_mipmap_levels(device, 1, 1, 1);
997 refcount = IDirect3DDevice9_Release(device);
998 ok(!refcount, "Device has %u references left.\n", refcount);
999 cleanup:
1000 IDirect3D9_Release(d3d);
1001 DestroyWindow(window);
1004 static void test_checkdevicemultisampletype(void)
1006 IDirect3DDevice9 *device;
1007 DWORD quality_levels;
1008 IDirect3D9 *d3d;
1009 ULONG refcount;
1010 HWND window;
1011 HRESULT hr;
1013 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1014 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1015 ok(!!window, "Failed to create a window.\n");
1016 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1017 ok(!!d3d, "Failed to create a D3D object.\n");
1018 if (!(device = create_device(d3d, window, NULL)))
1020 skip("Failed to create a 3D device, skipping test.\n");
1021 goto cleanup;
1024 quality_levels = 0;
1025 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1026 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1027 ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE, "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
1028 if (hr == D3DERR_NOTAVAILABLE)
1030 skip("IDirect3D9_CheckDeviceMultiSampleType not available\n");
1031 goto cleanup;
1033 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1035 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1036 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1037 ok(SUCCEEDED(hr), "CheckDeviceMultiSampleType failed with (%08x)\n", hr);
1038 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1040 cleanup:
1041 if (device)
1043 refcount = IDirect3DDevice9_Release(device);
1044 ok(!refcount, "Device has %u references left.\n", refcount);
1046 IDirect3D9_Release(d3d);
1047 DestroyWindow(window);
1050 static void test_swapchain(void)
1052 IDirect3DSwapChain9 *swapchain0;
1053 IDirect3DSwapChain9 *swapchain1;
1054 IDirect3DSwapChain9 *swapchain2;
1055 IDirect3DSwapChain9 *swapchain3;
1056 IDirect3DSwapChain9 *swapchainX;
1057 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1058 D3DPRESENT_PARAMETERS d3dpp;
1059 IDirect3DDevice9 *device;
1060 IDirect3D9 *d3d;
1061 ULONG refcount;
1062 HWND window, window2;
1063 HRESULT hr;
1064 struct device_desc device_desc;
1066 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1067 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1068 ok(!!window, "Failed to create a window.\n");
1069 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1070 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1071 ok(!!window2, "Failed to create a window.\n");
1072 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1073 ok(!!d3d, "Failed to create a D3D object.\n");
1074 if (!(device = create_device(d3d, window, NULL)))
1076 skip("Failed to create a 3D device, skipping test.\n");
1077 goto cleanup;
1080 /* Get the implicit swapchain */
1081 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1082 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1083 /* Check if the back buffer count was modified */
1084 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1085 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1086 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1087 IDirect3DSwapChain9_Release(swapchain0);
1089 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1090 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1091 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1092 backbuffer = (void *)0xdeadbeef;
1093 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1094 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1095 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1096 backbuffer = (void *)0xdeadbeef;
1097 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1098 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1099 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1101 /* Check if there is a back buffer */
1102 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1103 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1104 ok(backbuffer != NULL, "The back buffer is NULL\n");
1105 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1107 /* The back buffer type value is ignored. */
1108 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1109 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1110 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1111 IDirect3DSurface9_Release(stereo_buffer);
1112 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1113 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1114 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1115 IDirect3DSurface9_Release(stereo_buffer);
1116 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1117 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1118 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1119 IDirect3DSurface9_Release(stereo_buffer);
1121 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1122 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1123 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1124 IDirect3DSurface9_Release(stereo_buffer);
1125 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1126 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1127 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1128 IDirect3DSurface9_Release(stereo_buffer);
1129 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1130 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1131 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1132 IDirect3DSurface9_Release(stereo_buffer);
1134 /* Try to get a nonexistent swapchain */
1135 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1136 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1137 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1138 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1140 /* Create a bunch of swapchains */
1141 d3dpp.BackBufferCount = 0;
1142 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1143 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1144 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1146 d3dpp.BackBufferCount = 1;
1147 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1148 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1150 d3dpp.BackBufferCount = 2;
1151 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1152 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1153 if(SUCCEEDED(hr)) {
1154 /* Swapchain 3, created with backbuffercount 2 */
1155 backbuffer = (void *) 0xdeadbeef;
1156 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1157 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1158 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1159 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1161 backbuffer = (void *) 0xdeadbeef;
1162 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1163 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1164 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1165 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1167 backbuffer = (void *) 0xdeadbeef;
1168 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1169 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1170 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1171 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1173 backbuffer = (void *) 0xdeadbeef;
1174 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1175 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1176 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1177 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1180 /* Check the back buffers of the swapchains */
1181 /* Swapchain 1, created with backbuffercount 0 */
1182 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1183 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1184 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1185 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1187 backbuffer = (void *) 0xdeadbeef;
1188 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1189 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1190 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1191 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1193 /* Swapchain 2 - created with backbuffercount 1 */
1194 backbuffer = (void *) 0xdeadbeef;
1195 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1196 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1197 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1198 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1200 backbuffer = (void *) 0xdeadbeef;
1201 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1202 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1203 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1204 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1206 backbuffer = (void *) 0xdeadbeef;
1207 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1208 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1209 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1210 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1212 /* Try getSwapChain on a manually created swapchain
1213 * it should fail, apparently GetSwapChain only returns implicit swapchains
1215 swapchainX = (void *) 0xdeadbeef;
1216 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1217 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1218 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1219 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1221 IDirect3DSwapChain9_Release(swapchain3);
1222 IDirect3DSwapChain9_Release(swapchain2);
1223 IDirect3DSwapChain9_Release(swapchain1);
1225 d3dpp.Windowed = FALSE;
1226 d3dpp.hDeviceWindow = window;
1227 d3dpp.BackBufferCount = 1;
1228 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1229 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1230 d3dpp.hDeviceWindow = window2;
1231 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1232 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1234 device_desc.width = registry_mode.dmPelsWidth;
1235 device_desc.height = registry_mode.dmPelsHeight;
1236 device_desc.device_window = window;
1237 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1238 hr = reset_device(device, &device_desc);
1239 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1241 d3dpp.hDeviceWindow = window;
1242 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1243 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1244 d3dpp.hDeviceWindow = window2;
1245 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1246 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1247 d3dpp.Windowed = TRUE;
1248 d3dpp.hDeviceWindow = window;
1249 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1250 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1251 d3dpp.hDeviceWindow = window2;
1252 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1253 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1255 refcount = IDirect3DDevice9_Release(device);
1256 ok(!refcount, "Device has %u references left.\n", refcount);
1257 cleanup:
1258 IDirect3D9_Release(d3d);
1259 DestroyWindow(window2);
1260 DestroyWindow(window);
1263 static void test_refcount(void)
1265 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1266 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1267 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1268 IDirect3DVertexShader9 *pVertexShader = NULL;
1269 IDirect3DPixelShader9 *pPixelShader = NULL;
1270 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1271 IDirect3DTexture9 *pTexture = NULL;
1272 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1273 IDirect3DVolume9 *pVolumeLevel = NULL;
1274 IDirect3DSurface9 *pStencilSurface = NULL;
1275 IDirect3DSurface9 *pOffscreenSurface = NULL;
1276 IDirect3DSurface9 *pRenderTarget = NULL;
1277 IDirect3DSurface9 *pRenderTarget2 = NULL;
1278 IDirect3DSurface9 *pRenderTarget3 = NULL;
1279 IDirect3DSurface9 *pTextureLevel = NULL;
1280 IDirect3DSurface9 *pBackBuffer = NULL;
1281 IDirect3DStateBlock9 *pStateBlock = NULL;
1282 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1283 IDirect3DSwapChain9 *pSwapChain = NULL;
1284 IDirect3DQuery9 *pQuery = NULL;
1285 D3DPRESENT_PARAMETERS d3dpp;
1286 IDirect3DDevice9 *device;
1287 ULONG refcount = 0, tmp;
1288 IDirect3D9 *d3d, *d3d2;
1289 HWND window;
1290 HRESULT hr;
1292 D3DVERTEXELEMENT9 decl[] =
1294 D3DDECL_END()
1297 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1298 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1299 ok(!!window, "Failed to create a window.\n");
1300 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1301 ok(!!d3d, "Failed to create a D3D object.\n");
1303 CHECK_REFCOUNT(d3d, 1);
1305 if (!(device = create_device(d3d, window, NULL)))
1307 skip("Failed to create a 3D device, skipping test.\n");
1308 goto cleanup;
1311 refcount = get_refcount((IUnknown *)device);
1312 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1314 CHECK_REFCOUNT(d3d, 2);
1316 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1317 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1319 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1320 CHECK_REFCOUNT(d3d, 3);
1321 CHECK_RELEASE_REFCOUNT(d3d, 2);
1324 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1325 * - the container is the device OR swapchain
1326 * - they hold a reference to the device
1327 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1328 * - they are not freed if refcount reaches 0.
1329 * - the refcount is not forwarded to the container.
1331 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1332 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1333 if (pSwapChain)
1335 CHECK_REFCOUNT( pSwapChain, 1);
1337 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1338 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1339 CHECK_REFCOUNT( pSwapChain, 1);
1340 if(pRenderTarget)
1342 CHECK_SURFACE_CONTAINER( pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1343 CHECK_REFCOUNT( pRenderTarget, 1);
1345 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1346 CHECK_REFCOUNT(device, refcount);
1347 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1348 CHECK_REFCOUNT(device, refcount);
1350 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1351 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1352 CHECK_REFCOUNT( pRenderTarget, 2);
1353 CHECK_RELEASE_REFCOUNT( pRenderTarget, 1);
1354 CHECK_RELEASE_REFCOUNT( pRenderTarget, 0);
1355 CHECK_REFCOUNT(device, --refcount);
1357 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1358 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1359 CHECK_REFCOUNT(device, ++refcount);
1360 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1361 CHECK_REFCOUNT(device, --refcount);
1364 /* Render target and back buffer are identical. */
1365 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1366 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1367 if(pBackBuffer)
1369 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1370 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1371 pRenderTarget, pBackBuffer);
1372 pBackBuffer = NULL;
1374 CHECK_REFCOUNT(device, --refcount);
1376 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1377 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1378 CHECK_REFCOUNT( pSwapChain, 1);
1379 if(pStencilSurface)
1381 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1382 CHECK_REFCOUNT( pStencilSurface, 1);
1384 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1385 CHECK_REFCOUNT(device, refcount);
1386 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1387 CHECK_REFCOUNT(device, refcount);
1389 CHECK_RELEASE_REFCOUNT( pStencilSurface, 0);
1390 CHECK_REFCOUNT(device, --refcount);
1392 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1393 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1394 CHECK_REFCOUNT(device, ++refcount);
1395 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1396 CHECK_REFCOUNT(device, --refcount);
1397 pStencilSurface = NULL;
1400 CHECK_RELEASE_REFCOUNT( pSwapChain, 0);
1401 CHECK_REFCOUNT(device, --refcount);
1403 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1404 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1405 CHECK_REFCOUNT(device, ++refcount);
1406 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1407 CHECK_REFCOUNT(device, --refcount);
1408 pSwapChain = NULL;
1411 /* Buffers */
1412 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1413 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1414 if(pIndexBuffer)
1416 tmp = get_refcount( (IUnknown *)pIndexBuffer );
1418 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1419 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1420 hr = IDirect3DDevice9_SetIndices(device, NULL);
1421 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1424 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1425 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1426 if(pVertexBuffer)
1428 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1429 UINT offset = ~0;
1430 UINT stride = ~0;
1432 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1434 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1435 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1436 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1437 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1439 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1440 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1441 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1442 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1443 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1445 /* Shaders */
1446 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1447 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1448 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1449 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1450 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1451 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1452 /* Textures */
1453 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1454 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1455 if (pTexture)
1457 tmp = get_refcount( (IUnknown *)pTexture );
1459 /* SetTexture should not increase refcounts */
1460 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1461 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1462 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1463 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1465 /* This should not increment device refcount */
1466 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1467 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1468 /* But should increment texture's refcount */
1469 CHECK_REFCOUNT( pTexture, tmp+1 );
1470 /* Because the texture and surface refcount are identical */
1471 if (pTextureLevel)
1473 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1474 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1475 CHECK_REFCOUNT ( pTexture , tmp+2 );
1476 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1477 CHECK_REFCOUNT ( pTexture , tmp+1 );
1478 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1479 CHECK_REFCOUNT ( pTextureLevel, tmp );
1482 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1483 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1484 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1485 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1486 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1487 if (pVolumeTexture)
1489 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1491 /* This should not increment device refcount */
1492 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1493 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1494 /* But should increment volume texture's refcount */
1495 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1496 /* Because the volume texture and volume refcount are identical */
1497 if (pVolumeLevel)
1499 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1500 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1501 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1502 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1503 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1504 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1505 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1508 /* Surfaces */
1509 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1510 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1511 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1512 CHECK_REFCOUNT( pStencilSurface, 1 );
1513 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1514 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1515 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1516 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1517 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1518 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1519 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1520 CHECK_REFCOUNT( pRenderTarget3, 1 );
1521 /* Misc */
1522 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1523 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1525 memset(&d3dpp, 0, sizeof(d3dpp));
1526 d3dpp.Windowed = TRUE;
1527 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1528 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1529 d3dpp.EnableAutoDepthStencil = TRUE;
1530 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1531 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1532 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1533 if(pSwapChain)
1535 /* check implicit back buffer */
1536 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1537 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1538 CHECK_REFCOUNT( pSwapChain, 1);
1539 if(pBackBuffer)
1541 CHECK_SURFACE_CONTAINER( pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1542 CHECK_REFCOUNT( pBackBuffer, 1);
1543 CHECK_RELEASE_REFCOUNT( pBackBuffer, 0);
1544 CHECK_REFCOUNT(device, --refcount);
1546 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1547 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1548 CHECK_REFCOUNT(device, ++refcount);
1549 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1550 CHECK_REFCOUNT(device, --refcount);
1551 pBackBuffer = NULL;
1553 CHECK_REFCOUNT( pSwapChain, 1);
1555 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1556 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1558 hr = IDirect3DDevice9_BeginStateBlock(device);
1559 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1560 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1561 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1563 /* The implicit render target is not freed if refcount reaches 0.
1564 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1565 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1566 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1567 if(pRenderTarget2)
1569 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1570 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1571 pRenderTarget, pRenderTarget2);
1572 CHECK_REFCOUNT(device, --refcount);
1573 pRenderTarget2 = NULL;
1575 pRenderTarget = NULL;
1577 cleanup:
1578 CHECK_RELEASE(device, device, --refcount);
1580 /* Buffers */
1581 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1582 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1583 /* Shaders */
1584 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1585 CHECK_RELEASE(pVertexShader, device, --refcount);
1586 CHECK_RELEASE(pPixelShader, device, --refcount);
1587 /* Textures */
1588 CHECK_RELEASE(pTextureLevel, device, --refcount);
1589 CHECK_RELEASE(pCubeTexture, device, --refcount);
1590 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1591 /* Surfaces */
1592 CHECK_RELEASE(pStencilSurface, device, --refcount);
1593 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1594 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1595 /* Misc */
1596 CHECK_RELEASE(pStateBlock, device, --refcount);
1597 CHECK_RELEASE(pSwapChain, device, --refcount);
1598 CHECK_RELEASE(pQuery, device, --refcount);
1599 /* This will destroy device - cannot check the refcount here */
1600 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1601 CHECK_RELEASE_REFCOUNT(d3d, 0);
1602 DestroyWindow(window);
1605 static void test_cursor(void)
1607 IDirect3DSurface9 *cursor = NULL;
1608 IDirect3DDevice9 *device;
1609 CURSORINFO info;
1610 IDirect3D9 *d3d;
1611 ULONG refcount;
1612 HCURSOR cur;
1613 HWND window;
1614 HRESULT hr;
1615 BOOL ret;
1617 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1618 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1619 ok(!!window, "Failed to create a window.\n");
1621 ret = SetCursorPos(50, 50);
1622 ok(ret, "Failed to set cursor position.\n");
1623 flush_events();
1624 memset(&info, 0, sizeof(info));
1625 info.cbSize = sizeof(info);
1626 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1627 cur = info.hCursor;
1629 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1630 ok(!!d3d, "Failed to create a D3D object.\n");
1631 if (!(device = create_device(d3d, window, NULL)))
1633 skip("Failed to create a 3D device, skipping test.\n");
1634 goto cleanup;
1637 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1638 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1639 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1641 /* Initially hidden */
1642 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1643 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1645 /* Not enabled without a surface*/
1646 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1647 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1649 /* Fails */
1650 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1651 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1653 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1654 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1656 IDirect3DSurface9_Release(cursor);
1658 memset(&info, 0, sizeof(info));
1659 info.cbSize = sizeof(info);
1660 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1661 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1662 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1664 /* Still hidden */
1665 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1666 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1668 /* Enabled now*/
1669 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1670 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1672 memset(&info, 0, sizeof(info));
1673 info.cbSize = sizeof(info);
1674 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1675 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1676 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1678 refcount = IDirect3DDevice9_Release(device);
1679 ok(!refcount, "Device has %u references left.\n", refcount);
1680 cleanup:
1681 IDirect3D9_Release(d3d);
1682 DestroyWindow(window);
1685 static void test_reset(void)
1687 HRESULT hr;
1688 RECT winrect;
1689 D3DPRESENT_PARAMETERS d3dpp;
1690 D3DDISPLAYMODE d3ddm, d3ddm2;
1691 D3DVIEWPORT9 vp;
1692 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1693 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1694 IDirect3DSurface9 *surface;
1695 IDirect3DTexture9 *texture;
1696 IDirect3DVertexShader9 *shader;
1697 UINT i, adapter_mode_count;
1698 D3DLOCKED_RECT lockrect;
1699 IDirect3DDevice9 *device1 = NULL;
1700 IDirect3DDevice9 *device2 = NULL;
1701 IDirect3DSwapChain9 *swapchain;
1702 struct device_desc device_desc;
1703 IDirect3D9 *d3d;
1704 D3DCAPS9 caps;
1705 DWORD value;
1706 HWND hwnd;
1707 struct
1709 UINT w;
1710 UINT h;
1711 } *modes = NULL;
1712 UINT mode_count = 0;
1714 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1715 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1716 ok(!!hwnd, "Failed to create a window.\n");
1717 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1718 ok(!!d3d, "Failed to create a D3D object.\n");
1720 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1721 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1722 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1723 for(i = 0; i < adapter_mode_count; ++i)
1725 UINT j;
1726 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1727 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1728 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1730 for (j = 0; j < mode_count; ++j)
1732 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1733 break;
1735 if (j == mode_count)
1737 modes[j].w = d3ddm2.Width;
1738 modes[j].h = d3ddm2.Height;
1739 ++mode_count;
1742 /* We use them as invalid modes */
1743 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1744 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1745 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1746 d3ddm2.Width, d3ddm2.Height);
1747 goto cleanup;
1751 if (mode_count < 2)
1753 skip("Less than 2 modes supported, skipping mode tests\n");
1754 goto cleanup;
1757 i = 0;
1758 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1760 device_desc.width = modes[i].w;
1761 device_desc.height = modes[i].h;
1762 device_desc.device_window = hwnd;
1763 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1764 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1766 skip("Failed to create a D3D device, skipping tests.\n");
1767 goto cleanup;
1769 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1770 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1772 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1773 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1775 width = GetSystemMetrics(SM_CXSCREEN);
1776 height = GetSystemMetrics(SM_CYSCREEN);
1777 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1778 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1780 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1781 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1782 if(SUCCEEDED(hr))
1784 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1785 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1786 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1787 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1788 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1789 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1792 i = 1;
1793 vp.X = 10;
1794 vp.Y = 20;
1795 vp.MinZ = 2;
1796 vp.MaxZ = 3;
1797 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1798 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1800 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1801 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1802 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1803 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1804 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1806 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1807 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1808 d3dpp.Windowed = FALSE;
1809 d3dpp.BackBufferWidth = modes[i].w;
1810 d3dpp.BackBufferHeight = modes[i].h;
1811 d3dpp.BackBufferFormat = d3ddm.Format;
1812 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1813 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1814 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1815 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1817 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1818 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1819 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1821 ZeroMemory(&vp, sizeof(vp));
1822 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1823 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1824 if(SUCCEEDED(hr))
1826 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1827 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1828 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1829 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1830 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1831 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1834 width = GetSystemMetrics(SM_CXSCREEN);
1835 height = GetSystemMetrics(SM_CYSCREEN);
1836 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1837 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1839 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1840 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1841 memset(&d3dpp, 0, sizeof(d3dpp));
1842 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1843 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1844 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1845 d3dpp.BackBufferWidth, modes[i].w);
1846 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1847 d3dpp.BackBufferHeight, modes[i].h);
1848 IDirect3DSwapChain9_Release(swapchain);
1850 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1851 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1852 d3dpp.Windowed = TRUE;
1853 d3dpp.BackBufferWidth = 400;
1854 d3dpp.BackBufferHeight = 300;
1855 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1856 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1857 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1858 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1859 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1861 width = GetSystemMetrics(SM_CXSCREEN);
1862 height = GetSystemMetrics(SM_CYSCREEN);
1863 ok(width == orig_width, "Screen width is %d\n", width);
1864 ok(height == orig_height, "Screen height is %d\n", height);
1866 ZeroMemory(&vp, sizeof(vp));
1867 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1868 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1869 if(SUCCEEDED(hr))
1871 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1872 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1873 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
1874 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
1875 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1876 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1879 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1880 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1881 memset(&d3dpp, 0, sizeof(d3dpp));
1882 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1883 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1884 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1885 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1886 IDirect3DSwapChain9_Release(swapchain);
1888 winrect.left = 0;
1889 winrect.top = 0;
1890 winrect.right = 200;
1891 winrect.bottom = 150;
1892 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
1893 ok(SetWindowPos(hwnd, NULL, 0, 0,
1894 winrect.right-winrect.left,
1895 winrect.bottom-winrect.top,
1896 SWP_NOMOVE|SWP_NOZORDER),
1897 "SetWindowPos failed\n");
1899 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1900 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1901 d3dpp.Windowed = TRUE;
1902 d3dpp.BackBufferWidth = 0;
1903 d3dpp.BackBufferHeight = 0;
1904 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
1905 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1906 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1907 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1908 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1910 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1911 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1912 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1913 d3dpp.BackBufferFormat, d3ddm.Format);
1914 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1915 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1916 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1917 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1918 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1919 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1920 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1921 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1922 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1923 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1924 d3dpp.FullScreen_RefreshRateInHz);
1925 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1927 ZeroMemory(&vp, sizeof(vp));
1928 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1929 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1930 if(SUCCEEDED(hr))
1932 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1933 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1934 ok(vp.Width == 200, "D3DVIEWPORT->Width = %d\n", vp.Width);
1935 ok(vp.Height == 150, "D3DVIEWPORT->Height = %d\n", vp.Height);
1936 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1937 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1940 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1941 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1942 memset(&d3dpp, 0, sizeof(d3dpp));
1943 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1944 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1945 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1946 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1947 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1948 d3dpp.BackBufferFormat, d3ddm.Format);
1949 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1950 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1951 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1952 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1953 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
1954 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1955 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1956 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1957 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1958 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1959 d3dpp.FullScreen_RefreshRateInHz);
1960 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1961 IDirect3DSwapChain9_Release(swapchain);
1963 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1964 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1965 d3dpp.Windowed = TRUE;
1966 d3dpp.BackBufferWidth = 400;
1967 d3dpp.BackBufferHeight = 300;
1969 /* _Reset fails if there is a resource in the default pool */
1970 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1971 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
1972 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1973 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1974 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1975 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
1976 IDirect3DSurface9_Release(surface);
1977 /* Reset again to get the device out of the lost state */
1978 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1979 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1980 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1981 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1983 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1985 IDirect3DVolumeTexture9 *volume_texture;
1987 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
1988 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1989 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
1990 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1991 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
1992 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1993 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
1994 hr, D3DERR_DEVICENOTRESET);
1995 IDirect3DVolumeTexture9_Release(volume_texture);
1996 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1997 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
1998 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1999 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2001 else
2003 skip("Volume textures not supported.\n");
2006 /* Scratch, sysmem and managed pools are fine */
2007 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2008 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2009 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2010 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2011 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2012 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2013 IDirect3DSurface9_Release(surface);
2015 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2016 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2017 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2018 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2019 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2020 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2021 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2022 IDirect3DSurface9_Release(surface);
2024 /* The depth stencil should get reset to the auto depth stencil when present. */
2025 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2026 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2028 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2029 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2030 ok(surface == NULL, "Depth stencil should be NULL\n");
2032 d3dpp.EnableAutoDepthStencil = TRUE;
2033 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2034 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2035 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2037 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2038 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2039 ok(surface != NULL, "Depth stencil should not be NULL\n");
2040 if (surface) IDirect3DSurface9_Release(surface);
2042 d3dpp.EnableAutoDepthStencil = FALSE;
2043 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2044 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2046 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2047 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2048 ok(surface == NULL, "Depth stencil should be NULL\n");
2050 /* Will a sysmem or scratch survive while locked */
2051 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2052 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2053 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2054 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2055 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2056 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2057 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2058 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2059 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2060 IDirect3DSurface9_UnlockRect(surface);
2061 IDirect3DSurface9_Release(surface);
2063 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2064 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2065 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2066 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2067 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2068 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2069 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2070 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2071 IDirect3DSurface9_UnlockRect(surface);
2072 IDirect3DSurface9_Release(surface);
2074 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2075 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2076 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2077 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2078 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2079 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2080 IDirect3DTexture9_Release(texture);
2082 /* A reference held to an implicit surface causes failures as well */
2083 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2084 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2085 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2086 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2087 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2088 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2089 IDirect3DSurface9_Release(surface);
2090 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2091 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2092 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2093 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2095 /* Shaders are fine as well */
2096 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2097 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2098 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2099 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2100 IDirect3DVertexShader9_Release(shader);
2102 /* Try setting invalid modes */
2103 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2104 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2105 d3dpp.Windowed = FALSE;
2106 d3dpp.BackBufferWidth = 32;
2107 d3dpp.BackBufferHeight = 32;
2108 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2109 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2110 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2111 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2113 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2114 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2115 d3dpp.Windowed = FALSE;
2116 d3dpp.BackBufferWidth = 801;
2117 d3dpp.BackBufferHeight = 600;
2118 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2119 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2120 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2121 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2123 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2124 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2125 d3dpp.Windowed = FALSE;
2126 d3dpp.BackBufferWidth = 0;
2127 d3dpp.BackBufferHeight = 0;
2128 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2129 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2130 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2131 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2133 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2135 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2136 d3dpp.Windowed = TRUE;
2137 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2138 d3dpp.BackBufferFormat = d3ddm.Format;
2139 d3dpp.EnableAutoDepthStencil = FALSE;
2140 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2142 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2143 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2145 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2146 goto cleanup;
2149 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2150 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2152 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2153 d3dpp.Windowed = TRUE;
2154 d3dpp.BackBufferWidth = 400;
2155 d3dpp.BackBufferHeight = 300;
2156 d3dpp.EnableAutoDepthStencil = TRUE;
2157 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2159 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2160 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2162 if (FAILED(hr)) goto cleanup;
2164 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2165 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2166 ok(surface != NULL, "Depth stencil should not be NULL\n");
2167 if (surface) IDirect3DSurface9_Release(surface);
2169 cleanup:
2170 HeapFree(GetProcessHeap(), 0, modes);
2171 if (device2)
2173 UINT refcount = IDirect3DDevice9_Release(device2);
2174 ok(!refcount, "Device has %u references left.\n", refcount);
2176 if (device1)
2178 UINT refcount = IDirect3DDevice9_Release(device1);
2179 ok(!refcount, "Device has %u references left.\n", refcount);
2181 IDirect3D9_Release(d3d);
2182 DestroyWindow(hwnd);
2185 /* Test adapter display modes */
2186 static void test_display_modes(void)
2188 D3DDISPLAYMODE dmode;
2189 IDirect3D9 *d3d;
2191 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2192 ok(!!d3d, "Failed to create a D3D object.\n");
2194 #define TEST_FMT(x,r) do { \
2195 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2196 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2197 } while(0)
2199 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2200 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2201 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2202 /* D3DFMT_R5G6B5 */
2203 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2204 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2205 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2206 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2207 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2208 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2209 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2210 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2211 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2212 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2213 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2214 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2216 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2217 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2219 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2220 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2221 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2223 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2224 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2225 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2226 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2227 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2228 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2230 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2231 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2232 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2233 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2234 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2235 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2236 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2237 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2238 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2239 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2241 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2242 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2243 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2244 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2245 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2246 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2247 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2248 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2249 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2250 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2252 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2253 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2254 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2255 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2256 /* Floating point formats */
2257 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2258 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2259 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2261 /* IEEE formats */
2262 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2263 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2264 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2266 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2268 TEST_FMT(0, D3DERR_INVALIDCALL);
2270 IDirect3D9_Release(d3d);
2273 static void test_scene(void)
2275 IDirect3DSurface9 *surface1, *surface2, *surface3;
2276 IDirect3DSurface9 *backBuffer, *rt, *ds;
2277 RECT rect = {0, 0, 128, 128};
2278 IDirect3DDevice9 *device;
2279 IDirect3D9 *d3d;
2280 ULONG refcount;
2281 D3DCAPS9 caps;
2282 HWND window;
2283 HRESULT hr;
2285 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2286 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2287 ok(!!window, "Failed to create a window.\n");
2288 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2289 ok(!!d3d, "Failed to create a D3D object.\n");
2290 if (!(device = create_device(d3d, window, NULL)))
2292 skip("Failed to create a 3D device, skipping test.\n");
2293 goto cleanup;
2296 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2297 memset(&caps, 0, sizeof(caps));
2298 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2299 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2301 /* Test an EndScene without BeginScene. Should return an error */
2302 hr = IDirect3DDevice9_EndScene(device);
2303 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2305 /* Test a normal BeginScene / EndScene pair, this should work */
2306 hr = IDirect3DDevice9_BeginScene(device);
2307 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2308 hr = IDirect3DDevice9_EndScene(device);
2309 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2311 /* Test another EndScene without having begun a new scene. Should return an error */
2312 hr = IDirect3DDevice9_EndScene(device);
2313 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2315 /* Two nested BeginScene and EndScene calls */
2316 hr = IDirect3DDevice9_BeginScene(device);
2317 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2318 hr = IDirect3DDevice9_BeginScene(device);
2319 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2320 hr = IDirect3DDevice9_EndScene(device);
2321 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2322 hr = IDirect3DDevice9_EndScene(device);
2323 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2325 /* Create some surfaces to test stretchrect between the scenes */
2326 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2327 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2328 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2329 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2330 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2331 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2332 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2333 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2334 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2335 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2336 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2337 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2339 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2340 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2341 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2342 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2344 /* First make sure a simple StretchRect call works */
2345 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2346 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2347 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2348 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2349 if (0) /* Disabled for now because it crashes in wine */
2351 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2352 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2353 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2356 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2357 * BeginScene - Endscene pair with normal surfaces and render targets, but
2358 * not depth stencil surfaces. */
2359 hr = IDirect3DDevice9_BeginScene(device);
2360 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2362 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2363 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2364 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2365 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2366 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2367 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2368 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2370 hr = IDirect3DDevice9_EndScene(device);
2371 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2373 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2374 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2375 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2377 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2378 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2379 hr = IDirect3DDevice9_BeginScene(device);
2380 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2381 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2382 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2383 hr = IDirect3DDevice9_EndScene(device);
2384 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2386 IDirect3DSurface9_Release(rt);
2387 IDirect3DSurface9_Release(ds);
2388 IDirect3DSurface9_Release(backBuffer);
2389 IDirect3DSurface9_Release(surface1);
2390 IDirect3DSurface9_Release(surface2);
2391 IDirect3DSurface9_Release(surface3);
2392 refcount = IDirect3DDevice9_Release(device);
2393 ok(!refcount, "Device has %u references left.\n", refcount);
2394 cleanup:
2395 IDirect3D9_Release(d3d);
2396 DestroyWindow(window);
2399 static void test_limits(void)
2401 IDirect3DTexture9 *texture;
2402 IDirect3DDevice9 *device;
2403 IDirect3D9 *d3d;
2404 unsigned int i;
2405 ULONG refcount;
2406 HWND window;
2407 HRESULT hr;
2409 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2410 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2411 ok(!!window, "Failed to create a window.\n");
2412 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2413 ok(!!d3d, "Failed to create a D3D object.\n");
2414 if (!(device = create_device(d3d, window, NULL)))
2416 skip("Failed to create a 3D device, skipping test.\n");
2417 goto cleanup;
2420 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2421 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2423 /* There are 16 pixel samplers. We should be able to access all of them */
2424 for (i = 0; i < 16; ++i)
2426 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2427 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2428 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2429 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2430 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2431 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2434 /* Now test all 8 textures stage states */
2435 for (i = 0; i < 8; ++i)
2437 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2438 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2441 /* Investigations show that accessing higher samplers / textures stage
2442 * states does not return an error either. Writing to too high samplers
2443 * (approximately sampler 40) causes memory corruption in Windows, so
2444 * there is no bounds checking. */
2445 IDirect3DTexture9_Release(texture);
2446 refcount = IDirect3D9_Release(device);
2447 ok(!refcount, "Device has %u references left.\n", refcount);
2448 cleanup:
2449 IDirect3D9_Release(d3d);
2450 DestroyWindow(window);
2453 static void test_depthstenciltest(void)
2455 HRESULT hr;
2456 IDirect3DDevice9 *pDevice = NULL;
2457 D3DPRESENT_PARAMETERS d3dpp;
2458 D3DDISPLAYMODE d3ddm;
2459 IDirect3DSurface9 *pDepthStencil = NULL;
2460 IDirect3DSurface9 *pDepthStencil2 = NULL;
2461 IDirect3D9 *d3d;
2462 DWORD state;
2463 HWND hwnd;
2465 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2466 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2467 ok(!!hwnd, "Failed to create a window.\n");
2468 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2469 ok(!!d3d, "Failed to create a D3D object.\n");
2471 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2472 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2473 d3dpp.Windowed = TRUE;
2474 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2475 d3dpp.BackBufferWidth = 800;
2476 d3dpp.BackBufferHeight = 600;
2477 d3dpp.BackBufferFormat = d3ddm.Format;
2478 d3dpp.EnableAutoDepthStencil = TRUE;
2479 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2481 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2482 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2483 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2484 if(!pDevice)
2486 skip("Failed to create a d3d device\n");
2487 goto cleanup;
2490 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2491 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2493 /* Try to clear */
2494 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2495 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2497 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2498 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2500 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2501 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2502 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2503 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2505 /* This left the render states untouched! */
2506 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2507 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2508 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2509 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2510 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2511 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2512 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2513 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2514 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2515 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2516 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2517 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2519 /* This is supposed to fail now */
2520 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2521 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2523 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2524 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2526 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2527 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2529 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2530 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2531 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2533 /* Now it works again */
2534 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2535 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2537 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2538 if(pDevice) IDirect3D9_Release(pDevice);
2540 /* Now see if autodepthstencil disable is honored. First, without a format set */
2541 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2542 d3dpp.Windowed = TRUE;
2543 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2544 d3dpp.BackBufferWidth = 800;
2545 d3dpp.BackBufferHeight = 600;
2546 d3dpp.BackBufferFormat = d3ddm.Format;
2547 d3dpp.EnableAutoDepthStencil = FALSE;
2548 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2550 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2551 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2552 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2553 if(!pDevice)
2555 skip("Failed to create a d3d device\n");
2556 goto cleanup;
2559 pDepthStencil = NULL;
2560 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2561 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2562 if(pDepthStencil) {
2563 IDirect3DSurface9_Release(pDepthStencil);
2564 pDepthStencil = NULL;
2567 /* Check the depth test state */
2568 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2569 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2570 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2572 if(pDevice) IDirect3D9_Release(pDevice);
2574 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2575 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2576 d3dpp.Windowed = TRUE;
2577 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2578 d3dpp.BackBufferWidth = 800;
2579 d3dpp.BackBufferHeight = 600;
2580 d3dpp.BackBufferFormat = d3ddm.Format;
2581 d3dpp.EnableAutoDepthStencil = FALSE;
2582 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2584 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2585 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2586 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2587 if(!pDevice)
2589 skip("Failed to create a d3d device\n");
2590 goto cleanup;
2593 pDepthStencil = NULL;
2594 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2595 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2596 if(pDepthStencil) {
2597 IDirect3DSurface9_Release(pDepthStencil);
2598 pDepthStencil = NULL;
2601 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2602 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2603 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2605 cleanup:
2606 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2607 if (pDevice)
2609 UINT refcount = IDirect3D9_Release(pDevice);
2610 ok(!refcount, "Device has %u references left.\n", refcount);
2612 IDirect3D9_Release(d3d);
2613 DestroyWindow(hwnd);
2616 static void test_get_rt(void)
2618 IDirect3DSurface9 *backbuffer, *rt;
2619 IDirect3DDevice9 *device;
2620 IDirect3D9 *d3d9;
2621 D3DCAPS9 caps;
2622 HWND window;
2623 HRESULT hr;
2624 ULONG ref;
2625 UINT i;
2627 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2628 0, 0, 128, 128, 0, 0, 0, 0);
2629 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2630 ok(!!d3d9, "Failed to create a D3D object.\n");
2631 device = create_device(d3d9, window, NULL);
2632 if (!device)
2634 skip("Failed to create a D3D device, skipping tests.\n");
2635 goto done;
2638 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2639 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2640 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2642 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2643 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2645 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2647 rt = backbuffer;
2648 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2649 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2650 ok(!rt, "Got rt %p.\n", rt);
2653 IDirect3DSurface9_Release(backbuffer);
2655 ref = IDirect3DDevice9_Release(device);
2656 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2657 done:
2658 IDirect3D9_Release(d3d9);
2659 DestroyWindow(window);
2662 /* Test what happens when IDirect3DDevice9_DrawIndexedPrimitive is called without a valid index buffer set. */
2663 static void test_draw_indexed(void)
2665 static const struct {
2666 float position[3];
2667 DWORD color;
2668 } quad[] = {
2669 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2670 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2671 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2672 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2674 WORD indices[] = {0, 1, 2, 3, 0, 2};
2676 static const D3DVERTEXELEMENT9 decl_elements[] = {
2677 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2678 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2679 D3DDECL_END()
2682 IDirect3DVertexDeclaration9 *vertex_declaration;
2683 IDirect3DVertexBuffer9 *vertex_buffer;
2684 IDirect3DIndexBuffer9 *index_buffer;
2685 IDirect3DDevice9 *device;
2686 IDirect3D9 *d3d9;
2687 ULONG refcount;
2688 HWND window;
2689 HRESULT hr;
2690 void *ptr;
2692 window = CreateWindowA("d3d9_test_wc", "d3d9_test", 0,
2693 0, 0, 640, 480, 0, 0, 0, 0);
2694 ok(!!window, "Failed to create a window.\n");
2695 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2696 ok(!!d3d9, "Failed to create a D3D object.\n");
2697 if (!(device = create_device(d3d9, window, NULL)))
2699 skip("Failed to create a 3D device, skipping test.\n");
2700 goto cleanup;
2703 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2704 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
2705 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2706 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2708 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2709 ok(SUCCEEDED(hr), "CreateVertexBuffer failed (0x%08x)\n", hr);
2710 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2711 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
2712 memcpy(ptr, quad, sizeof(quad));
2713 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2714 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2715 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2716 ok(SUCCEEDED(hr), "SetStreamSource failed (0x%08x)\n", hr);
2718 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &index_buffer, NULL);
2719 ok(SUCCEEDED(hr), "CreateIndexBuffer failed (0x%08x)\n", hr);
2720 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2721 ok(SUCCEEDED(hr), "Lock failed (0x%08x)\n", hr);
2722 memcpy(ptr, indices, sizeof(indices));
2723 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2724 ok(SUCCEEDED(hr), "Unlock failed (0x%08x)\n", hr);
2725 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2726 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed (0x%08x)\n", hr);
2727 hr = IDirect3DDevice9_BeginScene(device);
2728 ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
2730 /* NULL index buffer. Should fail */
2731 hr = IDirect3DDevice9_SetIndices(device, NULL);
2732 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
2733 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2734 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2735 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
2736 hr, D3DERR_INVALIDCALL);
2738 /* Valid index buffer, NULL vertex declaration. Should fail */
2739 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2740 ok(SUCCEEDED(hr), "SetIndices failed (0x%08x)\n", hr);
2741 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2742 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2743 ok(hr == D3DERR_INVALIDCALL, "DrawIndexedPrimitive returned 0x%08x, expected D3DERR_INVALIDCALL (0x%08x)\n",
2744 hr, D3DERR_INVALIDCALL);
2746 /* Valid index buffer and vertex declaration. Should succeed */
2747 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2748 ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2749 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */, 0 /* MinIndex */,
2750 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2751 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed (0x%08x)\n", hr);
2753 hr = IDirect3DDevice9_EndScene(device);
2754 ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2756 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2757 ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2759 IDirect3DVertexBuffer9_Release(vertex_buffer);
2760 IDirect3DIndexBuffer9_Release(index_buffer);
2761 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2762 refcount = IDirect3DDevice9_Release(device);
2763 ok(!refcount, "Device has %u references left.\n", refcount);
2764 cleanup:
2765 IDirect3D9_Release(d3d9);
2766 DestroyWindow(window);
2769 static void test_null_stream(void)
2771 IDirect3DVertexBuffer9 *buffer = NULL;
2772 IDirect3DDevice9 *device;
2773 IDirect3D9 *d3d9;
2774 ULONG refcount;
2775 HWND window;
2776 HRESULT hr;
2777 IDirect3DVertexShader9 *shader = NULL;
2778 IDirect3DVertexDeclaration9 *decl = NULL;
2779 static const DWORD shader_code[] =
2781 0xfffe0101, /* vs_1_1 */
2782 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2783 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2784 0x0000ffff /* end */
2786 static const D3DVERTEXELEMENT9 decl_elements[] = {
2787 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2788 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2789 D3DDECL_END()
2792 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2793 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2794 ok(!!window, "Failed to create a window.\n");
2795 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2796 ok(!!d3d9, "Failed to create a D3D object.\n");
2797 if (!(device = create_device(d3d9, window, NULL)))
2799 skip("Failed to create a 3D device, skipping test.\n");
2800 goto cleanup;
2803 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2804 if(FAILED(hr)) {
2805 skip("No vertex shader support\n");
2806 goto cleanup;
2808 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2809 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
2810 if (FAILED(hr)) {
2811 skip("Vertex declaration handling not possible.\n");
2812 goto cleanup;
2814 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
2815 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
2816 if (FAILED(hr)) {
2817 skip("Vertex buffer handling not possible.\n");
2818 goto cleanup;
2821 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
2822 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2823 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
2824 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
2825 hr = IDirect3DDevice9_SetVertexShader(device, shader);
2826 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
2827 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2828 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
2830 hr = IDirect3DDevice9_BeginScene(device);
2831 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
2832 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
2833 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
2834 hr = IDirect3DDevice9_EndScene(device);
2835 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
2837 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2838 IDirect3DDevice9_SetVertexShader(device, NULL);
2839 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2841 cleanup:
2842 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
2843 if (decl) IDirect3DVertexDeclaration9_Release(decl);
2844 if (shader) IDirect3DVertexShader9_Release(shader);
2845 if (device)
2847 refcount = IDirect3DDevice9_Release(device);
2848 ok(!refcount, "Device has %u references left.\n", refcount);
2850 IDirect3D9_Release(d3d9);
2851 DestroyWindow(window);
2854 static void test_lights(void)
2856 IDirect3DDevice9 *device;
2857 IDirect3D9 *d3d9;
2858 ULONG refcount;
2859 HWND window;
2860 HRESULT hr;
2861 unsigned int i;
2862 BOOL enabled;
2863 D3DCAPS9 caps;
2865 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2866 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2867 ok(!!window, "Failed to create a window.\n");
2868 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2869 ok(!!d3d9, "Failed to create a D3D object.\n");
2870 if (!(device = create_device(d3d9, window, NULL)))
2872 skip("Failed to create a 3D device, skipping test.\n");
2873 goto cleanup;
2876 memset(&caps, 0, sizeof(caps));
2877 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2878 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
2880 for(i = 1; i <= caps.MaxActiveLights; i++) {
2881 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
2882 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
2883 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
2884 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
2885 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
2888 /* TODO: Test the rendering results in this situation */
2889 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
2890 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
2891 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
2892 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
2893 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
2894 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
2895 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
2897 for(i = 1; i <= caps.MaxActiveLights; i++) {
2898 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
2899 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
2902 refcount = IDirect3DDevice9_Release(device);
2903 ok(!refcount, "Device has %u references left.\n", refcount);
2904 cleanup:
2905 IDirect3D9_Release(d3d9);
2906 DestroyWindow(window);
2909 static void test_set_stream_source(void)
2911 IDirect3DVertexBuffer9 *vb;
2912 IDirect3DDevice9 *device;
2913 IDirect3D9 *d3d9;
2914 ULONG refcount;
2915 HWND window;
2916 HRESULT hr;
2918 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2919 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2920 ok(!!window, "Failed to create a window.\n");
2921 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2922 ok(!!d3d9, "Failed to create a D3D object.\n");
2923 if (!(device = create_device(d3d9, window, NULL)))
2925 skip("Failed to create a 3D device, skipping test.\n");
2926 goto cleanup;
2929 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
2930 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
2932 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
2933 * (Radeon 9000 verified) reject them, so accept both results. Wine
2934 * currently rejects this to be able to optimize the vbo conversion, but
2935 * writes a WARN. */
2936 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
2937 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2938 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
2939 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2940 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
2941 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2942 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
2943 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2944 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
2945 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2947 /* Try to set the NULL buffer with an offset and stride 0 */
2948 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2949 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2950 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
2951 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2952 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
2953 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2954 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
2955 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2956 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
2957 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2959 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2960 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
2962 IDirect3DVertexBuffer9_Release(vb);
2963 refcount = IDirect3DDevice9_Release(device);
2964 ok(!refcount, "Device has %u references left.\n", refcount);
2965 cleanup:
2966 IDirect3D9_Release(d3d9);
2967 DestroyWindow(window);
2970 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
2971 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
2972 * a fixed number of combinations are possible in fullscreen mode. In windowed
2973 * mode more combinations are allowed due to format conversion and this is
2974 * likely driver dependent. */
2975 static void test_display_formats(void)
2977 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
2978 unsigned int backbuffer, display;
2979 unsigned int windowed;
2980 IDirect3D9 *d3d9;
2981 BOOL should_pass;
2982 BOOL has_modes;
2983 HRESULT hr;
2985 static const struct
2987 const char *name;
2988 D3DFORMAT format;
2989 D3DFORMAT alpha_format;
2990 BOOL display;
2991 BOOL windowed;
2993 formats[] =
2995 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
2996 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
2997 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
2998 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
2999 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3000 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3001 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3004 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3005 ok(!!d3d9, "Failed to create a D3D object.\n");
3007 for (display = 0; display < sizeof(formats) / sizeof(*formats); ++display)
3009 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3011 for (windowed = 0; windowed <= 1; ++windowed)
3013 for (backbuffer = 0; backbuffer < sizeof(formats) / sizeof(*formats); ++backbuffer)
3015 should_pass = FALSE;
3017 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3019 D3DFORMAT backbuffer_format;
3021 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3022 backbuffer_format = formats[display].format;
3023 else
3024 backbuffer_format = formats[backbuffer].format;
3026 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3027 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3028 if (hr == D3D_OK)
3030 if (windowed)
3032 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3033 backbuffer_format, formats[display].format);
3034 should_pass = (hr == D3D_OK);
3036 else
3037 should_pass = (formats[display].format == formats[backbuffer].format
3038 || (formats[display].alpha_format
3039 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3043 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3044 formats[display].format, formats[backbuffer].format, windowed);
3045 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3046 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3047 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3052 IDirect3D9_Release(d3d9);
3055 static void test_scissor_size(void)
3057 struct device_desc device_desc;
3058 IDirect3D9 *d3d9_ptr;
3059 unsigned int i;
3060 static struct {
3061 int winx; int winy; int backx; int backy; DWORD flags;
3062 } scts[] = { /* scissor tests */
3063 {800, 600, 640, 480, 0},
3064 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3065 {640, 480, 800, 600, 0},
3066 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3069 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3070 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3072 for(i=0; i<sizeof(scts)/sizeof(scts[0]); i++) {
3073 IDirect3DDevice9 *device_ptr = 0;
3074 HRESULT hr;
3075 HWND hwnd = 0;
3076 RECT scissorrect;
3078 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3079 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3081 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3083 scts[i].backx = registry_mode.dmPelsWidth;
3084 scts[i].backy = registry_mode.dmPelsHeight;
3087 device_desc.device_window = hwnd;
3088 device_desc.width = scts[i].backx;
3089 device_desc.height = scts[i].backy;
3090 device_desc.flags = scts[i].flags;
3091 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3093 skip("Failed to create a 3D device, skipping test.\n");
3094 DestroyWindow(hwnd);
3095 goto err_out;
3098 /* Check for the default scissor rect size */
3099 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3100 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3101 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3102 && scissorrect.top == 0 && scissorrect.left == 0,
3103 "Scissorrect missmatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3104 scts[i].backx, scts[i].backy);
3106 /* check the scissorrect values after a reset */
3107 device_desc.width = registry_mode.dmPelsWidth;
3108 device_desc.height = registry_mode.dmPelsHeight;
3109 device_desc.flags = scts[i].flags;
3110 hr = reset_device(device_ptr, &device_desc);
3111 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3112 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3113 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3115 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3116 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3117 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3118 && scissorrect.top == 0 && scissorrect.left == 0,
3119 "Scissorrect missmatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3120 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3122 if(device_ptr) {
3123 ULONG ref;
3125 ref = IDirect3DDevice9_Release(device_ptr);
3126 DestroyWindow(hwnd);
3127 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3131 err_out:
3132 IDirect3D9_Release(d3d9_ptr);
3135 static void test_multi_device(void)
3137 IDirect3DDevice9 *device1, *device2;
3138 HWND window1, window2;
3139 IDirect3D9 *d3d9;
3140 ULONG refcount;
3142 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3143 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3144 ok(!!window1, "Failed to create a window.\n");
3145 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3146 ok(!!d3d9, "Failed to create a D3D object.\n");
3147 if (!(device1 = create_device(d3d9, window1, NULL)))
3149 skip("Failed to create a 3D device, skipping test.\n");
3150 IDirect3D9_Release(d3d9);
3151 DestroyWindow(window1);
3152 return;
3154 IDirect3D9_Release(d3d9);
3156 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3157 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3158 ok(!!window2, "Failed to create a window.\n");
3159 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3160 ok(!!d3d9, "Failed to create a D3D object.\n");
3161 device2 = create_device(d3d9, window2, NULL);
3162 IDirect3D9_Release(d3d9);
3164 refcount = IDirect3DDevice9_Release(device2);
3165 ok(!refcount, "Device has %u references left.\n", refcount);
3166 refcount = IDirect3DDevice9_Release(device1);
3167 ok(!refcount, "Device has %u references left.\n", refcount);
3168 DestroyWindow(window2);
3169 DestroyWindow(window1);
3172 static HWND filter_messages;
3174 enum message_window
3176 DEVICE_WINDOW,
3177 FOCUS_WINDOW,
3180 struct message
3182 UINT message;
3183 enum message_window window;
3184 BOOL check_wparam;
3185 WPARAM expect_wparam;
3188 static const struct message *expect_messages;
3189 static HWND device_window, focus_window;
3190 static LONG windowposchanged_received, syscommand_received;
3192 struct wndproc_thread_param
3194 HWND dummy_window;
3195 HANDLE window_created;
3196 HANDLE test_finished;
3197 BOOL running_in_foreground;
3200 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3202 if (filter_messages && filter_messages == hwnd)
3204 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3205 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3208 if (expect_messages)
3210 HWND w;
3212 switch (expect_messages->window)
3214 case DEVICE_WINDOW:
3215 w = device_window;
3216 break;
3218 case FOCUS_WINDOW:
3219 w = focus_window;
3220 break;
3222 default:
3223 w = NULL;
3224 break;
3227 if (hwnd == w && expect_messages->message == message)
3229 if (expect_messages->check_wparam)
3230 ok(wparam == expect_messages->expect_wparam,
3231 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3232 wparam, message, expect_messages->expect_wparam);
3234 ++expect_messages;
3238 /* KDE randomly does something with the hidden window during the
3239 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3240 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3241 * just flag WM_WINDOWPOSCHANGED as bad. */
3242 if (message == WM_WINDOWPOSCHANGED)
3243 InterlockedIncrement(&windowposchanged_received);
3244 else if (message == WM_SYSCOMMAND)
3245 InterlockedIncrement(&syscommand_received);
3247 return DefWindowProcA(hwnd, message, wparam, lparam);
3250 static DWORD WINAPI wndproc_thread(void *param)
3252 struct wndproc_thread_param *p = param;
3253 DWORD res;
3254 BOOL ret;
3256 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3257 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3258 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3259 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3261 ret = SetEvent(p->window_created);
3262 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3264 for (;;)
3266 MSG msg;
3268 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3269 res = WaitForSingleObject(p->test_finished, 100);
3270 if (res == WAIT_OBJECT_0) break;
3271 if (res != WAIT_TIMEOUT)
3273 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3274 break;
3278 DestroyWindow(p->dummy_window);
3280 return 0;
3283 static void test_wndproc(void)
3285 struct wndproc_thread_param thread_params;
3286 struct device_desc device_desc;
3287 IDirect3DDevice9 *device;
3288 WNDCLASSA wc = {0};
3289 IDirect3D9 *d3d9;
3290 HANDLE thread;
3291 LONG_PTR proc;
3292 ULONG ref;
3293 DWORD res, tid;
3294 HWND tmp;
3295 UINT i, adapter_mode_count;
3296 HRESULT hr;
3297 D3DDISPLAYMODE d3ddm;
3298 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3299 DEVMODEW devmode;
3300 LONG change_ret;
3301 BOOL ret;
3303 static const struct message create_messages[] =
3305 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3306 /* Do not test wparam here. If device creation succeeds,
3307 * wparam is WA_ACTIVE. If device creation fails (testbot)
3308 * wparam is set to WA_INACTIVE on some Windows versions. */
3309 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3310 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3311 {0, 0, FALSE, 0},
3313 static const struct message focus_loss_messages[] =
3315 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3316 * not reliable on X11 WMs. When the window focus follows the
3317 * mouse pointer the message is not sent.
3318 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3319 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3320 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3321 * not deterministic. */
3322 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3323 /* Windows sends WM_ACTIVATE to the device window, indicating that
3324 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3325 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3326 * leaves the device window active, breaking re-activation in the
3327 * lost device test.
3328 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3329 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3330 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3331 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3332 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3333 * not deterministic. It may be sent after the focus window handling
3334 * or before. */
3335 {0, 0, FALSE, 0},
3337 static const struct message focus_loss_messages_nowc[] =
3339 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3340 * not reliable on X11 WMs. When the window focus follows the
3341 * mouse pointer the message is not sent.
3342 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3343 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3344 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3345 {0, 0, FALSE, 0},
3347 static const struct message reactivate_messages[] =
3349 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3350 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3351 /* optional WM_MOVE here if size changed */
3352 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3353 {0, 0, FALSE, 0},
3355 static const struct message reactivate_messages_nowc[] =
3357 /* We're activating the device window before activating the
3358 * focus window, so no ACTIVATEAPP message is sent. */
3359 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3360 {0, 0, FALSE, 0},
3362 static const struct message focus_loss_messages_hidden[] =
3364 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3365 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3366 {0, 0, FALSE, 0},
3368 static const struct message focus_loss_messages_filtered[] =
3370 /* WM_ACTIVATE is delivered to the window proc because it is
3371 * generated by SetForegroundWindow before the d3d routine
3372 * starts it work. Don't check for it due to focus-follows-mouse
3373 * WMs though. */
3374 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3375 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3376 {0, 0, FALSE, 0},
3378 static const struct message reactivate_messages_filtered[] =
3380 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3381 {0, 0, FALSE, 0},
3383 static const struct message sc_restore_messages[] =
3385 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3386 * processed it. Our wndproc has no way to prevent d3d from
3387 * handling the message. The second DefWindowProc call done by
3388 * our wndproc doesn't do any changes to the window because it
3389 * is already restored due to d3d's handling. */
3390 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3391 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3392 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3393 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3394 {0, 0, FALSE, 0},
3396 static const struct message sc_minimize_messages[] =
3398 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3399 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3400 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3401 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3402 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3403 {0, 0, FALSE, 0},
3405 static const struct message sc_maximize_messages[] =
3407 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3408 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3409 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3410 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3411 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3412 {0, 0, FALSE, 0},
3414 static const struct
3416 DWORD create_flags;
3417 const struct message *focus_loss_messages, *reactivate_messages;
3418 BOOL iconic;
3420 tests[] =
3422 {0, focus_loss_messages, reactivate_messages, TRUE},
3423 {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, reactivate_messages_nowc, FALSE},
3426 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3427 ok(!!d3d9, "Failed to create a D3D object.\n");
3429 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3430 for (i = 0; i < adapter_mode_count; ++i)
3432 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3433 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3435 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3436 continue;
3437 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3438 * refuses to create a device at these sizes. */
3439 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3440 continue;
3442 if (!user32_width)
3444 user32_width = d3ddm.Width;
3445 user32_height = d3ddm.Height;
3446 continue;
3449 /* Make sure the d3d mode is smaller in width or height and at most
3450 * equal in the other dimension than the mode passed to
3451 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3452 * the ChangeDisplaySettings parameters + 12. */
3453 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3454 continue;
3455 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3457 d3d_width = d3ddm.Width;
3458 d3d_height = d3ddm.Height;
3459 break;
3461 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3463 d3d_width = user32_width;
3464 d3d_height = user32_height;
3465 user32_width = d3ddm.Width;
3466 user32_height = d3ddm.Height;
3467 break;
3471 if (!d3d_width)
3473 skip("Could not find adequate modes, skipping mode tests.\n");
3474 IDirect3D9_Release(d3d9);
3475 return;
3478 wc.lpfnWndProc = test_proc;
3479 wc.lpszClassName = "d3d9_test_wndproc_wc";
3480 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3482 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3483 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3484 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3485 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3487 memset(&devmode, 0, sizeof(devmode));
3488 devmode.dmSize = sizeof(devmode);
3489 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
3491 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3492 devmode.dmPelsWidth = user32_width;
3493 devmode.dmPelsHeight = user32_height;
3494 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3495 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3497 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3498 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3499 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3500 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3501 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3502 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3504 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3505 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3507 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3508 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3509 (LONG_PTR)test_proc, proc);
3510 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3511 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3512 (LONG_PTR)test_proc, proc);
3514 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3515 device_window, focus_window, thread_params.dummy_window);
3517 tmp = GetFocus();
3518 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3519 if (thread_params.running_in_foreground)
3521 tmp = GetForegroundWindow();
3522 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3523 thread_params.dummy_window, tmp);
3525 else
3526 skip("Not running in foreground, skip foreground window test\n");
3528 flush_events();
3530 expect_messages = create_messages;
3532 device_desc.device_window = device_window;
3533 device_desc.width = d3d_width;
3534 device_desc.height = d3d_height;
3535 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
3536 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3538 skip("Failed to create a D3D device, skipping tests.\n");
3539 goto done;
3542 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3543 expect_messages->message, expect_messages->window, i);
3544 expect_messages = NULL;
3546 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3548 tmp = GetFocus();
3549 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3550 tmp = GetForegroundWindow();
3551 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3553 SetForegroundWindow(focus_window);
3554 flush_events();
3556 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3557 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3558 (LONG_PTR)test_proc, proc, i);
3560 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3561 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3562 (LONG_PTR)test_proc, i);
3564 /* Change the mode while the device is in use and then drop focus. */
3565 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3566 devmode.dmPelsWidth = user32_width;
3567 devmode.dmPelsHeight = user32_height;
3568 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3569 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3571 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3572 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3573 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3574 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3575 if (hr == D3DERR_DEVICENOTRESET)
3576 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3577 else
3578 todo_wine ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3580 expect_messages = tests[i].focus_loss_messages;
3581 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3582 * manually changing the focus. It generates the same messages, but the task
3583 * bar still shows the previous foreground window as active, and the window has
3584 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3585 * the device is difficult, see below. */
3586 SetForegroundWindow(GetDesktopWindow());
3587 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3588 expect_messages->message, expect_messages->window, i);
3589 expect_messages = NULL;
3590 tmp = GetFocus();
3591 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3592 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3594 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3595 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3597 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3598 ok(ret, "Failed to get display mode.\n");
3599 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3600 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3601 devmode.dmPelsWidth, devmode.dmPelsHeight);
3603 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3604 * done before the focus window is restored. This makes sense to some extent
3605 * because minimizing the window on focus loss is the application's job if this
3606 * flag is set. */
3607 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3609 ShowWindow(device_window, SW_MINIMIZE);
3610 ShowWindow(device_window, SW_RESTORE);
3612 flush_events();
3614 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3615 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3616 * restore is triggered by the user. */
3617 expect_messages = tests[i].reactivate_messages;
3618 ShowWindow(focus_window, SW_MINIMIZE);
3619 ShowWindow(focus_window, SW_RESTORE);
3620 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3621 SetForegroundWindow(focus_window);
3622 flush_events();
3623 SetForegroundWindow(focus_window);
3624 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3625 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3626 expect_messages->message, expect_messages->window, i);
3627 expect_messages = NULL;
3629 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3630 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3632 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3633 ok(ret, "Failed to get display mode.\n");
3634 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3635 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3636 devmode.dmPelsWidth, devmode.dmPelsHeight);
3638 hr = reset_device(device, &device_desc);
3639 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3641 ShowWindow(device_window, SW_HIDE);
3642 flush_events();
3644 expect_messages = focus_loss_messages_hidden;
3645 windowposchanged_received = 0;
3646 SetForegroundWindow(GetDesktopWindow());
3647 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3648 expect_messages->message, expect_messages->window, i);
3649 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3650 expect_messages = NULL;
3651 flush_events();
3653 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3654 ok(ret, "Failed to get display mode.\n");
3655 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3656 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3658 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3659 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3660 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3661 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3662 flush_events();
3664 syscommand_received = 0;
3665 expect_messages = sc_restore_messages;
3666 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3667 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3668 expect_messages->message, expect_messages->window, i);
3669 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3670 expect_messages = NULL;
3671 flush_events();
3673 expect_messages = sc_minimize_messages;
3674 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3675 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3676 expect_messages->message, expect_messages->window, i);
3677 expect_messages = NULL;
3678 flush_events();
3680 expect_messages = sc_maximize_messages;
3681 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3682 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3683 expect_messages->message, expect_messages->window, i);
3684 expect_messages = NULL;
3685 flush_events();
3687 SetForegroundWindow(GetDesktopWindow());
3688 ShowWindow(device_window, SW_MINIMIZE);
3689 ShowWindow(device_window, SW_RESTORE);
3690 ShowWindow(focus_window, SW_MINIMIZE);
3691 ShowWindow(focus_window, SW_RESTORE);
3692 SetForegroundWindow(focus_window);
3693 flush_events();
3695 /* Releasing a device in lost state breaks follow-up tests on native. */
3696 hr = reset_device(device, &device_desc);
3697 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3699 filter_messages = focus_window;
3701 ref = IDirect3DDevice9_Release(device);
3702 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3704 /* Fix up the mode until Wine's device release behavior is fixed. */
3705 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3706 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3708 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3709 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3710 (LONG_PTR)test_proc, proc, i);
3712 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3713 * on native in the test below. It isn't needed anyways. Creating the third
3714 * device will show it again. */
3715 filter_messages = NULL;
3716 ShowWindow(device_window, SW_HIDE);
3717 /* Remove the maximized state from the SYSCOMMAND test while we're not
3718 * interfering with a device. */
3719 ShowWindow(focus_window, SW_SHOWNORMAL);
3720 filter_messages = focus_window;
3722 device_desc.device_window = focus_window;
3723 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3725 skip("Failed to create a D3D device, skipping tests.\n");
3726 goto done;
3728 filter_messages = NULL;
3729 SetForegroundWindow(focus_window); /* For KDE. */
3730 flush_events();
3732 expect_messages = focus_loss_messages_filtered;
3733 windowposchanged_received = 0;
3734 SetForegroundWindow(GetDesktopWindow());
3735 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3736 expect_messages->message, expect_messages->window, i);
3737 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3738 expect_messages = NULL;
3740 /* The window is iconic even though no message was sent. */
3741 ok(!IsIconic(focus_window) == !tests[i].iconic,
3742 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
3744 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3745 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3747 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3748 ShowWindow(focus_window, SW_MINIMIZE);
3750 syscommand_received = 0;
3751 expect_messages = sc_restore_messages;
3752 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3753 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3754 expect_messages->message, expect_messages->window, i);
3755 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3756 expect_messages = NULL;
3757 flush_events();
3759 /* For FVWM. */
3760 ShowWindow(focus_window, SW_RESTORE);
3761 flush_events();
3763 expect_messages = sc_minimize_messages;
3764 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3765 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3766 expect_messages->message, expect_messages->window, i);
3767 expect_messages = NULL;
3768 flush_events();
3770 expect_messages = sc_maximize_messages;
3771 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3772 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3773 expect_messages->message, expect_messages->window, i);
3774 expect_messages = NULL;
3775 flush_events();
3777 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
3778 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
3779 SetForegroundWindow(GetDesktopWindow());
3780 flush_events();
3781 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
3782 flush_events();
3784 expect_messages = reactivate_messages_filtered;
3785 windowposchanged_received = 0;
3786 SetForegroundWindow(focus_window);
3787 flush_events();
3788 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3789 expect_messages->message, expect_messages->window, i);
3790 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
3791 ok(!windowposchanged_received || broken(1),
3792 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
3793 expect_messages = NULL;
3795 filter_messages = focus_window;
3796 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3797 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3799 hr = reset_device(device, &device_desc);
3800 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3802 ref = IDirect3DDevice9_Release(device);
3803 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3805 device_desc.device_window = device_window;
3806 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3808 skip("Failed to create a D3D device, skipping tests.\n");
3809 goto done;
3812 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3813 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3814 (LONG_PTR)test_proc, i);
3816 ref = IDirect3DDevice9_Release(device);
3817 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3819 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3820 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3821 (LONG_PTR)DefWindowProcA, proc, i);
3823 done:
3824 filter_messages = NULL;
3825 DestroyWindow(device_window);
3826 DestroyWindow(focus_window);
3827 SetEvent(thread_params.test_finished);
3828 WaitForSingleObject(thread, INFINITE);
3829 CloseHandle(thread);
3832 IDirect3D9_Release(d3d9);
3833 CloseHandle(thread_params.test_finished);
3834 CloseHandle(thread_params.window_created);
3835 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3838 static void test_wndproc_windowed(void)
3840 struct wndproc_thread_param thread_params;
3841 struct device_desc device_desc;
3842 IDirect3DDevice9 *device;
3843 WNDCLASSA wc = {0};
3844 IDirect3D9 *d3d9;
3845 HANDLE thread;
3846 LONG_PTR proc;
3847 HRESULT hr;
3848 ULONG ref;
3849 DWORD res, tid;
3850 HWND tmp;
3852 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3853 ok(!!d3d9, "Failed to create a D3D object.\n");
3855 wc.lpfnWndProc = test_proc;
3856 wc.lpszClassName = "d3d9_test_wndproc_wc";
3857 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3859 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3860 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3861 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3862 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3864 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3865 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3866 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3867 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3868 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3869 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3870 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3871 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3873 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3874 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3876 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3877 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3878 (LONG_PTR)test_proc, proc);
3879 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3880 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3881 (LONG_PTR)test_proc, proc);
3883 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3884 device_window, focus_window, thread_params.dummy_window);
3886 tmp = GetFocus();
3887 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3888 if (thread_params.running_in_foreground)
3890 tmp = GetForegroundWindow();
3891 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3892 thread_params.dummy_window, tmp);
3894 else
3895 skip("Not running in foreground, skip foreground window test\n");
3897 filter_messages = focus_window;
3899 device_desc.device_window = device_window;
3900 device_desc.width = 640;
3901 device_desc.height = 480;
3902 device_desc.flags = 0;
3903 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3905 skip("Failed to create a D3D device, skipping tests.\n");
3906 goto done;
3909 tmp = GetFocus();
3910 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3911 tmp = GetForegroundWindow();
3912 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3913 thread_params.dummy_window, tmp);
3915 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3916 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3917 (LONG_PTR)test_proc, proc);
3919 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3920 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3921 (LONG_PTR)test_proc, proc);
3923 filter_messages = NULL;
3925 device_desc.width = registry_mode.dmPelsWidth;
3926 device_desc.height = registry_mode.dmPelsHeight;
3927 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3928 hr = reset_device(device, &device_desc);
3929 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3931 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3932 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3933 (LONG_PTR)test_proc, proc);
3935 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3936 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3938 device_desc.flags = 0;
3939 hr = reset_device(device, &device_desc);
3940 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3942 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3943 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3944 (LONG_PTR)test_proc, proc);
3946 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3947 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3948 (LONG_PTR)test_proc, proc);
3950 filter_messages = focus_window;
3952 ref = IDirect3DDevice9_Release(device);
3953 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3955 filter_messages = device_window;
3957 device_desc.device_window = focus_window;
3958 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3960 skip("Failed to create a D3D device, skipping tests.\n");
3961 goto done;
3964 filter_messages = NULL;
3966 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3967 hr = reset_device(device, &device_desc);
3968 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3970 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3971 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3972 (LONG_PTR)test_proc, proc);
3974 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3975 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3977 device_desc.flags = 0;
3978 hr = reset_device(device, &device_desc);
3979 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3981 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3982 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3983 (LONG_PTR)test_proc, proc);
3985 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3986 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3987 (LONG_PTR)test_proc, proc);
3989 filter_messages = device_window;
3991 ref = IDirect3DDevice9_Release(device);
3992 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3994 device_desc.device_window = device_window;
3995 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3997 skip("Failed to create a D3D device, skipping tests.\n");
3998 goto done;
4001 filter_messages = NULL;
4003 device_desc.device_window = device_window;
4004 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4005 hr = reset_device(device, &device_desc);
4006 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4008 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4009 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4010 (LONG_PTR)test_proc, proc);
4012 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4013 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4015 device_desc.flags = 0;
4016 hr = reset_device(device, &device_desc);
4017 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4019 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4020 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4021 (LONG_PTR)test_proc, proc);
4023 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4024 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4025 (LONG_PTR)test_proc, proc);
4027 filter_messages = device_window;
4029 ref = IDirect3DDevice9_Release(device);
4030 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4032 done:
4033 filter_messages = NULL;
4034 IDirect3D9_Release(d3d9);
4036 SetEvent(thread_params.test_finished);
4037 WaitForSingleObject(thread, INFINITE);
4038 CloseHandle(thread_params.test_finished);
4039 CloseHandle(thread_params.window_created);
4040 CloseHandle(thread);
4042 DestroyWindow(device_window);
4043 DestroyWindow(focus_window);
4044 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4047 static void test_reset_fullscreen(void)
4049 WNDCLASSEXA wc = {0};
4050 IDirect3DDevice9 *device = NULL;
4051 IDirect3D9 *d3d;
4052 ATOM atom;
4053 struct device_desc device_desc;
4054 static const struct message messages[] =
4056 /* Windows usually sends wparam = TRUE, except on the testbot,
4057 * where it randomly sends FALSE. Ignore it. */
4058 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4059 {0, 0, FALSE, 0},
4062 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4063 ok(!!d3d, "Failed to create a D3D object.\n");
4064 expect_messages = messages;
4066 wc.cbSize = sizeof(wc);
4067 wc.lpfnWndProc = test_proc;
4068 wc.lpszClassName = "test_reset_fullscreen";
4070 atom = RegisterClassExA(&wc);
4071 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4073 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4074 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4075 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4078 * Create a device in windowed mode.
4079 * Since the device is windowed and we haven't called any methods that
4080 * could show the window (such as ShowWindow or SetWindowPos) yet,
4081 * WM_ACTIVATEAPP will not have been sent.
4083 if (!(device = create_device(d3d, device_window, NULL)))
4085 skip("Unable to create device. Skipping test.\n");
4086 goto cleanup;
4090 * Switch to fullscreen mode.
4091 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4092 * message to be sent.
4094 device_desc.width = registry_mode.dmPelsWidth;
4095 device_desc.height = registry_mode.dmPelsHeight;
4096 device_desc.device_window = device_window;
4097 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4098 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4100 flush_events();
4101 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4102 expect_messages = NULL;
4104 cleanup:
4105 if (device) IDirect3DDevice9_Release(device);
4106 IDirect3D9_Release(d3d);
4107 DestroyWindow(device_window);
4108 device_window = focus_window = NULL;
4109 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4113 static inline void set_fpu_cw(WORD cw)
4115 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4116 #define D3D9_TEST_SET_FPU_CW 1
4117 __asm__ volatile ("fnclex");
4118 __asm__ volatile ("fldcw %0" : : "m" (cw));
4119 #elif defined(__i386__) && defined(_MSC_VER)
4120 #define D3D9_TEST_SET_FPU_CW 1
4121 __asm fnclex;
4122 __asm fldcw cw;
4123 #endif
4126 static inline WORD get_fpu_cw(void)
4128 WORD cw = 0;
4129 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4130 #define D3D9_TEST_GET_FPU_CW 1
4131 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4132 #elif defined(__i386__) && defined(_MSC_VER)
4133 #define D3D9_TEST_GET_FPU_CW 1
4134 __asm fnstcw cw;
4135 #endif
4136 return cw;
4139 static WORD callback_cw, callback_set_cw;
4140 static DWORD callback_tid;
4142 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4144 *out = NULL;
4145 return E_NOINTERFACE;
4148 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4150 callback_cw = get_fpu_cw();
4151 set_fpu_cw(callback_set_cw);
4152 callback_tid = GetCurrentThreadId();
4153 return 2;
4156 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4158 callback_cw = get_fpu_cw();
4159 set_fpu_cw(callback_set_cw);
4160 callback_tid = GetCurrentThreadId();
4161 return 1;
4164 static const IUnknownVtbl dummy_object_vtbl =
4166 dummy_object_QueryInterface,
4167 dummy_object_AddRef,
4168 dummy_object_Release,
4171 static const GUID d3d9_private_data_test_guid =
4173 0xfdb37466,
4174 0x428f,
4175 0x4edf,
4176 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4179 static void test_fpu_setup(void)
4181 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4182 struct device_desc device_desc;
4183 IDirect3DDevice9 *device;
4184 HWND window = NULL;
4185 IDirect3D9 *d3d9;
4186 WORD cw;
4187 IDirect3DSurface9 *surface;
4188 HRESULT hr;
4189 IUnknown dummy_object = {&dummy_object_vtbl};
4191 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4192 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4193 ok(!!window, "Failed to create a window.\n");
4194 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4195 ok(!!d3d9, "Failed to create a D3D object.\n");
4197 device_desc.device_window = window;
4198 device_desc.width = 640;
4199 device_desc.height = 480;
4200 device_desc.flags = 0;
4202 set_fpu_cw(0xf60);
4203 cw = get_fpu_cw();
4204 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4206 if (!(device = create_device(d3d9, window, &device_desc)))
4208 skip("Failed to create a 3D device, skipping test.\n");
4209 set_fpu_cw(0x37f);
4210 goto done;
4213 cw = get_fpu_cw();
4214 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4216 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4217 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4219 callback_set_cw = 0xf60;
4220 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4221 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4222 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4223 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4224 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4225 cw = get_fpu_cw();
4226 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4228 callback_cw = 0;
4229 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4230 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4231 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4232 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4233 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4235 callback_set_cw = 0x7f;
4236 set_fpu_cw(0x7f);
4238 IDirect3DSurface9_Release(surface);
4240 callback_cw = 0;
4241 IDirect3DDevice9_Release(device);
4242 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4243 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4245 cw = get_fpu_cw();
4246 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4247 set_fpu_cw(0xf60);
4248 cw = get_fpu_cw();
4249 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4251 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4252 device = create_device(d3d9, window, &device_desc);
4253 ok(device != NULL, "CreateDevice failed.\n");
4255 cw = get_fpu_cw();
4256 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4258 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4259 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4261 callback_cw = 0;
4262 callback_set_cw = 0x37f;
4263 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4264 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4265 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4266 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4267 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4268 cw = get_fpu_cw();
4269 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4271 IDirect3DSurface9_Release(surface);
4273 callback_cw = 0;
4274 IDirect3DDevice9_Release(device);
4275 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4276 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4278 done:
4279 IDirect3D9_Release(d3d9);
4280 DestroyWindow(window);
4281 #endif
4284 static void test_window_style(void)
4286 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4287 LONG device_style, device_exstyle;
4288 LONG focus_style, focus_exstyle;
4289 struct device_desc device_desc;
4290 LONG style, expected_style;
4291 IDirect3DDevice9 *device;
4292 IDirect3D9 *d3d9;
4293 HRESULT hr;
4294 ULONG ref;
4295 BOOL ret;
4296 static const struct
4298 DWORD device_flags;
4299 LONG style, focus_loss_style, exstyle;
4301 tests[] =
4303 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4304 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4306 unsigned int i;
4308 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4309 ok(!!d3d9, "Failed to create a D3D object.\n");
4310 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4312 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
4314 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4315 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4316 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4317 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4319 device_style = GetWindowLongA(device_window, GWL_STYLE);
4320 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4321 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4322 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4324 GetWindowRect(focus_window, &focus_rect);
4325 GetWindowRect(device_window, &device_rect);
4327 device_desc.device_window = device_window;
4328 device_desc.width = registry_mode.dmPelsWidth;
4329 device_desc.height = registry_mode.dmPelsHeight;
4330 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4331 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4333 skip("Failed to create a D3D device, skipping tests.\n");
4334 DestroyWindow(device_window);
4335 DestroyWindow(focus_window);
4336 break;
4339 style = GetWindowLongA(device_window, GWL_STYLE);
4340 expected_style = device_style | tests[i].style;
4341 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4342 expected_style, style, i);
4343 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4344 expected_style = device_exstyle | tests[i].exstyle;
4345 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4346 expected_style, style, i);
4348 style = GetWindowLongA(focus_window, GWL_STYLE);
4349 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4350 focus_style, style, i);
4351 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4352 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4353 focus_exstyle, style, i);
4355 GetWindowRect(device_window, &r);
4356 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4357 todo_wine ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}, i=%u.\n",
4358 device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
4359 r.left, r.top, r.right, r.bottom, i);
4360 else
4361 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}, i=%u.\n",
4362 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4363 r.left, r.top, r.right, r.bottom, i);
4364 GetClientRect(device_window, &r2);
4365 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4366 GetWindowRect(focus_window, &r);
4367 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}, i=%u.\n",
4368 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
4369 r.left, r.top, r.right, r.bottom, i);
4371 device_desc.flags = 0;
4372 hr = reset_device(device, &device_desc);
4373 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4375 style = GetWindowLongA(device_window, GWL_STYLE);
4376 expected_style = device_style | tests[i].style;
4377 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4378 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4379 expected_style, style, i);
4380 else
4381 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4382 expected_style, style, i);
4383 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4384 expected_style = device_exstyle | tests[i].exstyle;
4385 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4386 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4387 expected_style, style, i);
4388 else
4389 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4390 expected_style, style, i);
4392 style = GetWindowLongA(focus_window, GWL_STYLE);
4393 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4394 focus_style, style, i);
4395 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4396 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4397 focus_exstyle, style, i);
4399 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4400 hr = reset_device(device, &device_desc);
4401 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4402 ret = SetForegroundWindow(GetDesktopWindow());
4403 ok(ret, "Failed to set foreground window.\n");
4405 style = GetWindowLongA(device_window, GWL_STYLE);
4406 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4407 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4408 expected_style, style);
4409 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4410 expected_style = device_exstyle | tests[i].exstyle;
4411 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4412 expected_style, style);
4414 style = GetWindowLongA(focus_window, GWL_STYLE);
4415 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4416 focus_style, style);
4417 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4418 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4419 focus_exstyle, style);
4421 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4422 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4423 * like a good idea to reset it first. */
4424 ShowWindow(focus_window, SW_MINIMIZE);
4425 ShowWindow(focus_window, SW_RESTORE);
4426 ret = SetForegroundWindow(focus_window);
4427 ok(ret, "Failed to set foreground window.\n");
4428 flush_events();
4429 hr = reset_device(device, &device_desc);
4430 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4432 ref = IDirect3DDevice9_Release(device);
4433 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4435 DestroyWindow(device_window);
4436 DestroyWindow(focus_window);
4438 IDirect3D9_Release(d3d9);
4441 static const POINT *expect_pos;
4443 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4445 if (message == WM_MOUSEMOVE)
4447 if (expect_pos && expect_pos->x && expect_pos->y)
4449 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4451 ClientToScreen(window, &p);
4452 if (expect_pos->x == p.x && expect_pos->y == p.y)
4453 ++expect_pos;
4457 return DefWindowProcA(window, message, wparam, lparam);
4460 static void test_cursor_pos(void)
4462 IDirect3DSurface9 *cursor;
4463 IDirect3DDevice9 *device;
4464 WNDCLASSA wc = {0};
4465 IDirect3D9 *d3d9;
4466 UINT refcount;
4467 HWND window;
4468 HRESULT hr;
4469 BOOL ret;
4471 /* Note that we don't check for movement we're not supposed to receive.
4472 * That's because it's hard to distinguish from the user accidentally
4473 * moving the mouse. */
4474 static const POINT points[] =
4476 {50, 50},
4477 {75, 75},
4478 {100, 100},
4479 {125, 125},
4480 {150, 150},
4481 {125, 125},
4482 {150, 150},
4483 {150, 150},
4484 {0, 0},
4487 wc.lpfnWndProc = test_cursor_proc;
4488 wc.lpszClassName = "d3d9_test_cursor_wc";
4489 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4490 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4491 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4492 ShowWindow(window, SW_SHOW);
4493 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4494 ok(!!d3d9, "Failed to create a D3D object.\n");
4496 device = create_device(d3d9, window, NULL);
4497 if (!device)
4499 skip("Failed to create a D3D device, skipping tests.\n");
4500 goto done;
4503 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4504 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4505 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4506 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4507 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4508 IDirect3DSurface9_Release(cursor);
4509 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4510 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4512 flush_events();
4513 expect_pos = points;
4515 ret = SetCursorPos(50, 50);
4516 ok(ret, "Failed to set cursor position.\n");
4517 flush_events();
4519 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4520 flush_events();
4521 /* SetCursorPosition() eats duplicates. */
4522 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4523 flush_events();
4525 ret = SetCursorPos(100, 100);
4526 ok(ret, "Failed to set cursor position.\n");
4527 flush_events();
4528 /* Even if the position was set with SetCursorPos(). */
4529 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4530 flush_events();
4532 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4533 flush_events();
4534 ret = SetCursorPos(150, 150);
4535 ok(ret, "Failed to set cursor position.\n");
4536 flush_events();
4537 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4538 flush_events();
4540 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4541 flush_events();
4542 /* SetCursorPos() doesn't. */
4543 ret = SetCursorPos(150, 150);
4544 ok(ret, "Failed to set cursor position.\n");
4545 flush_events();
4547 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4548 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4550 refcount = IDirect3DDevice9_Release(device);
4551 ok(!refcount, "Device has %u references left.\n", refcount);
4552 done:
4553 DestroyWindow(window);
4554 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4555 IDirect3D9_Release(d3d9);
4558 static void test_mode_change(void)
4560 RECT d3d_rect, focus_rect, r;
4561 struct device_desc device_desc;
4562 IDirect3DSurface9 *backbuffer;
4563 IDirect3DDevice9 *device;
4564 D3DSURFACE_DESC desc;
4565 IDirect3D9 *d3d9;
4566 DEVMODEW devmode;
4567 ULONG refcount;
4568 UINT adapter_mode_count, i;
4569 HRESULT hr;
4570 DWORD ret;
4571 LONG change_ret;
4572 D3DDISPLAYMODE d3ddm;
4573 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4575 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4576 ok(!!d3d9, "Failed to create a D3D object.\n");
4578 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4579 for (i = 0; i < adapter_mode_count; ++i)
4581 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4582 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4584 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4585 continue;
4586 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4587 * refuses to create a device at these sizes. */
4588 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4589 continue;
4591 if (!user32_width)
4593 user32_width = d3ddm.Width;
4594 user32_height = d3ddm.Height;
4595 continue;
4598 /* Make sure the d3d mode is smaller in width or height and at most
4599 * equal in the other dimension than the mode passed to
4600 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4601 * the ChangeDisplaySettings parameters + 12. */
4602 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4603 continue;
4604 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4606 d3d_width = d3ddm.Width;
4607 d3d_height = d3ddm.Height;
4608 break;
4610 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4612 d3d_width = user32_width;
4613 d3d_height = user32_height;
4614 user32_width = d3ddm.Width;
4615 user32_height = d3ddm.Height;
4616 break;
4620 if (!d3d_width)
4622 skip("Could not find adequate modes, skipping mode tests.\n");
4623 IDirect3D9_Release(d3d9);
4624 return;
4627 memset(&devmode, 0, sizeof(devmode));
4628 devmode.dmSize = sizeof(devmode);
4629 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4630 devmode.dmPelsWidth = user32_width;
4631 devmode.dmPelsHeight = user32_height;
4632 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4633 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4635 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4636 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4637 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4638 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4640 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4641 GetWindowRect(focus_window, &focus_rect);
4643 device_desc.device_window = device_window;
4644 device_desc.width = d3d_width;
4645 device_desc.height = d3d_height;
4646 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4647 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4649 skip("Failed to create a D3D device, skipping tests.\n");
4650 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4651 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4652 goto done;
4655 devmode.dmPelsWidth = user32_width;
4656 devmode.dmPelsHeight = user32_height;
4657 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4658 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4660 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4661 ok(ret, "Failed to get display mode.\n");
4662 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
4663 "Expected resolution %ux%u, got %ux%u.\n",
4664 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
4666 GetWindowRect(device_window, &r);
4667 ok(EqualRect(&r, &d3d_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4668 d3d_rect.left, d3d_rect.top, d3d_rect.right, d3d_rect.bottom,
4669 r.left, r.top, r.right, r.bottom);
4670 GetWindowRect(focus_window, &r);
4671 ok(EqualRect(&r, &focus_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4672 focus_rect.left, focus_rect.top, focus_rect.right, focus_rect.bottom,
4673 r.left, r.top, r.right, r.bottom);
4675 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
4676 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
4677 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
4678 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
4679 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
4680 desc.Width, d3d_width);
4681 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
4682 desc.Height, d3d_height);
4683 IDirect3DSurface9_Release(backbuffer);
4685 refcount = IDirect3DDevice9_Release(device);
4686 ok(!refcount, "Device has %u references left.\n", refcount);
4688 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4689 ok(ret, "Failed to get display mode.\n");
4690 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4691 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4692 "Expected resolution %ux%u, got %ux%u.\n",
4693 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4695 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
4696 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4698 /* The mode restore also happens when the device was created at the original screen size. */
4700 device_desc.device_window = device_window;
4701 device_desc.width = registry_mode.dmPelsWidth;
4702 device_desc.height = registry_mode.dmPelsHeight;
4703 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4704 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
4706 devmode.dmPelsWidth = user32_width;
4707 devmode.dmPelsHeight = user32_height;
4708 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4709 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4711 refcount = IDirect3DDevice9_Release(device);
4712 ok(!refcount, "Device has %u references left.\n", refcount);
4714 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
4715 ok(ret, "Failed to get display mode.\n");
4716 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
4717 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
4718 "Expected resolution %ux%u, got %ux%u.\n",
4719 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
4721 done:
4722 DestroyWindow(device_window);
4723 DestroyWindow(focus_window);
4724 IDirect3D9_Release(d3d9);
4727 static void test_device_window_reset(void)
4729 RECT fullscreen_rect, device_rect, r;
4730 struct device_desc device_desc;
4731 IDirect3DDevice9 *device;
4732 WNDCLASSA wc = {0};
4733 IDirect3D9 *d3d9;
4734 LONG_PTR proc;
4735 HRESULT hr;
4736 ULONG ref;
4738 wc.lpfnWndProc = test_proc;
4739 wc.lpszClassName = "d3d9_test_wndproc_wc";
4740 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4742 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4743 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4744 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4745 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4746 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4747 ok(!!d3d9, "Failed to create a D3D object.\n");
4749 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4750 GetWindowRect(device_window, &device_rect);
4752 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4753 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4754 (LONG_PTR)test_proc, proc);
4755 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4756 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4757 (LONG_PTR)test_proc, proc);
4759 device_desc.device_window = NULL;
4760 device_desc.width = registry_mode.dmPelsWidth;
4761 device_desc.height = registry_mode.dmPelsHeight;
4762 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4763 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4765 skip("Failed to create a D3D device, skipping tests.\n");
4766 goto done;
4769 GetWindowRect(focus_window, &r);
4770 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4771 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4772 r.left, r.top, r.right, r.bottom);
4773 GetWindowRect(device_window, &r);
4774 ok(EqualRect(&r, &device_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4775 device_rect.left, device_rect.top, device_rect.right, device_rect.bottom,
4776 r.left, r.top, r.right, r.bottom);
4778 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4779 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4780 (LONG_PTR)test_proc, proc);
4781 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4782 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4784 device_desc.device_window = device_window;
4785 hr = reset_device(device, &device_desc);
4786 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4788 GetWindowRect(focus_window, &r);
4789 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4790 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4791 r.left, r.top, r.right, r.bottom);
4792 GetWindowRect(device_window, &r);
4793 ok(EqualRect(&r, &fullscreen_rect), "Expected {%d, %d, %d, %d}, got {%d, %d, %d, %d}.\n",
4794 fullscreen_rect.left, fullscreen_rect.top, fullscreen_rect.right, fullscreen_rect.bottom,
4795 r.left, r.top, r.right, r.bottom);
4797 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4798 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4799 (LONG_PTR)test_proc, proc);
4800 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4801 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4803 ref = IDirect3DDevice9_Release(device);
4804 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4806 done:
4807 IDirect3D9_Release(d3d9);
4808 DestroyWindow(device_window);
4809 DestroyWindow(focus_window);
4810 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4813 static void test_reset_resources(void)
4815 IDirect3DSurface9 *surface, *rt;
4816 IDirect3DTexture9 *texture;
4817 IDirect3DDevice9 *device;
4818 IDirect3D9 *d3d9;
4819 unsigned int i;
4820 D3DCAPS9 caps;
4821 HWND window;
4822 HRESULT hr;
4823 ULONG ref;
4825 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
4826 0, 0, 640, 480, 0, 0, 0, 0);
4827 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4828 ok(!!d3d9, "Failed to create a D3D object.\n");
4830 if (!(device = create_device(d3d9, window, NULL)))
4832 skip("Failed to create a D3D device, skipping tests.\n");
4833 goto done;
4836 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
4837 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
4839 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
4840 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
4841 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
4842 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
4843 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
4844 IDirect3DSurface9_Release(surface);
4846 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
4848 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
4849 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
4850 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
4851 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4852 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
4853 IDirect3DTexture9_Release(texture);
4854 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
4855 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
4856 IDirect3DSurface9_Release(surface);
4859 hr = reset_device(device, NULL);
4860 ok(SUCCEEDED(hr), "Failed to reset device.\n");
4862 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
4863 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
4864 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4865 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4866 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
4867 IDirect3DSurface9_Release(surface);
4868 IDirect3DSurface9_Release(rt);
4870 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
4872 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
4873 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
4876 ref = IDirect3DDevice9_Release(device);
4877 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4879 done:
4880 IDirect3D9_Release(d3d9);
4881 DestroyWindow(window);
4884 static void test_set_rt_vp_scissor(void)
4886 IDirect3DStateBlock9 *stateblock;
4887 IDirect3DDevice9 *device;
4888 IDirect3DSurface9 *rt;
4889 IDirect3D9 *d3d9;
4890 D3DVIEWPORT9 vp;
4891 UINT refcount;
4892 HWND window;
4893 HRESULT hr;
4894 RECT rect;
4896 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
4897 0, 0, 640, 480, 0, 0, 0, 0);
4898 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4899 ok(!!d3d9, "Failed to create a D3D object.\n");
4900 if (!(device = create_device(d3d9, window, NULL)))
4902 skip("Failed to create a D3D device, skipping tests.\n");
4903 DestroyWindow(window);
4904 return;
4907 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
4908 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
4909 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
4911 hr = IDirect3DDevice9_GetViewport(device, &vp);
4912 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4913 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4914 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4915 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
4916 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
4917 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4918 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4920 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4921 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4922 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
4923 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4924 rect.left, rect.top, rect.right, rect.bottom);
4926 hr = IDirect3DDevice9_BeginStateBlock(device);
4927 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
4929 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4930 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4932 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
4933 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
4934 IDirect3DStateBlock9_Release(stateblock);
4936 hr = IDirect3DDevice9_GetViewport(device, &vp);
4937 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4938 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4939 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4940 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4941 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4942 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4943 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4945 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4946 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4947 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
4948 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4949 rect.left, rect.top, rect.right, rect.bottom);
4951 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4952 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4954 vp.X = 10;
4955 vp.Y = 20;
4956 vp.Width = 30;
4957 vp.Height = 40;
4958 vp.MinZ = 0.25f;
4959 vp.MaxZ = 0.75f;
4960 hr = IDirect3DDevice9_SetViewport(device, &vp);
4961 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
4963 SetRect(&rect, 50, 60, 70, 80);
4964 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
4965 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
4967 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
4968 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
4970 hr = IDirect3DDevice9_GetViewport(device, &vp);
4971 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
4972 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
4973 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
4974 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
4975 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
4976 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
4977 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
4979 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
4980 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
4981 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
4982 "Got unexpected scissor rect {%d, %d, %d, %d}.\n",
4983 rect.left, rect.top, rect.right, rect.bottom);
4985 IDirect3DSurface9_Release(rt);
4986 refcount = IDirect3DDevice9_Release(device);
4987 ok(!refcount, "Device has %u references left.\n", refcount);
4988 IDirect3D9_Release(d3d9);
4989 DestroyWindow(window);
4992 static void test_volume_get_container(void)
4994 IDirect3DVolumeTexture9 *texture = NULL;
4995 IDirect3DVolume9 *volume = NULL;
4996 IDirect3DDevice9 *device;
4997 IUnknown *container;
4998 IDirect3D9 *d3d9;
4999 ULONG refcount;
5000 D3DCAPS9 caps;
5001 HWND window;
5002 HRESULT hr;
5004 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5005 0, 0, 640, 480, 0, 0, 0, 0);
5006 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5007 ok(!!d3d9, "Failed to create a D3D object.\n");
5008 if (!(device = create_device(d3d9, window, NULL)))
5010 skip("Failed to create a D3D device, skipping tests.\n");
5011 IDirect3D9_Release(d3d9);
5012 DestroyWindow(window);
5013 return;
5016 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5017 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5018 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5020 skip("No volume texture support, skipping tests.\n");
5021 IDirect3DDevice9_Release(device);
5022 IDirect3D9_Release(d3d9);
5023 DestroyWindow(window);
5024 return;
5027 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5028 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5029 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5030 ok(!!texture, "Got unexpected texture %p.\n", texture);
5032 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5033 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5034 ok(!!volume, "Got unexpected volume %p.\n", volume);
5036 /* These should work... */
5037 container = NULL;
5038 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5039 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5040 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5041 IUnknown_Release(container);
5043 container = NULL;
5044 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5045 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5046 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5047 IUnknown_Release(container);
5049 container = NULL;
5050 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5051 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5052 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5053 IUnknown_Release(container);
5055 container = NULL;
5056 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5057 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5058 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5059 IUnknown_Release(container);
5061 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5062 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5063 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5064 ok(!container, "Got unexpected container %p.\n", container);
5066 IDirect3DVolume9_Release(volume);
5067 IDirect3DVolumeTexture9_Release(texture);
5068 refcount = IDirect3DDevice9_Release(device);
5069 ok(!refcount, "Device has %u references left.\n", refcount);
5070 IDirect3D9_Release(d3d9);
5071 DestroyWindow(window);
5074 static void test_volume_resource(void)
5076 IDirect3DVolumeTexture9 *texture;
5077 IDirect3DResource9 *resource;
5078 IDirect3DVolume9 *volume;
5079 IDirect3DDevice9 *device;
5080 IDirect3D9 *d3d9;
5081 ULONG refcount;
5082 D3DCAPS9 caps;
5083 HWND window;
5084 HRESULT hr;
5086 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5087 0, 0, 640, 480, 0, 0, 0, 0);
5088 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5089 ok(!!d3d9, "Failed to create a D3D object.\n");
5090 if (!(device = create_device(d3d9, window, NULL)))
5092 skip("Failed to create a D3D device, skipping tests.\n");
5093 IDirect3D9_Release(d3d9);
5094 DestroyWindow(window);
5095 return;
5098 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5099 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5100 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5102 skip("No volume texture support, skipping tests.\n");
5103 IDirect3DDevice9_Release(device);
5104 IDirect3D9_Release(d3d9);
5105 DestroyWindow(window);
5106 return;
5109 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5110 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5111 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5112 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5113 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5114 IDirect3DVolumeTexture9_Release(texture);
5116 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5117 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5119 IDirect3DVolume9_Release(volume);
5120 refcount = IDirect3DDevice9_Release(device);
5121 ok(!refcount, "Device has %u references left.\n", refcount);
5122 IDirect3D9_Release(d3d9);
5123 DestroyWindow(window);
5126 static void test_vb_lock_flags(void)
5128 static const struct
5130 DWORD flags;
5131 const char *debug_string;
5132 HRESULT win7_result;
5134 test_data[] =
5136 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5137 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5138 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5139 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5140 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5141 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5142 /* Completely bogus flags aren't an error. */
5143 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5145 IDirect3DVertexBuffer9 *buffer;
5146 IDirect3DDevice9 *device;
5147 IDirect3D9 *d3d9;
5148 unsigned int i;
5149 ULONG refcount;
5150 HWND window;
5151 HRESULT hr;
5152 void *data;
5154 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5155 0, 0, 640, 480, 0, 0, 0, 0);
5156 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5157 ok(!!d3d9, "Failed to create a D3D object.\n");
5158 if (!(device = create_device(d3d9, window, NULL)))
5160 skip("Failed to create a D3D device, skipping tests.\n");
5161 IDirect3D9_Release(d3d9);
5162 DestroyWindow(window);
5163 return;
5166 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5167 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5169 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
5171 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5172 /* Windows XP always returns D3D_OK even with flags that don't make
5173 * sense. Windows 7 returns an error. At least one game (Shaiya)
5174 * depends on the Windows XP result, so mark the Windows 7 behavior as
5175 * broken. */
5176 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5177 hr, test_data[i].debug_string);
5178 if (SUCCEEDED(hr))
5180 ok(!!data, "Got unexpected data %p.\n", data);
5181 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5182 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5186 IDirect3DVertexBuffer9_Release(buffer);
5187 refcount = IDirect3DDevice9_Release(device);
5188 ok(!refcount, "Device has %u references left.\n", refcount);
5189 IDirect3D9_Release(d3d9);
5190 DestroyWindow(window);
5193 static const char *debug_d3dpool(D3DPOOL pool)
5195 switch (pool)
5197 case D3DPOOL_DEFAULT:
5198 return "D3DPOOL_DEFAULT";
5199 case D3DPOOL_SYSTEMMEM:
5200 return "D3DPOOL_SYSTEMMEM";
5201 case D3DPOOL_SCRATCH:
5202 return "D3DPOOL_SCRATCH";
5203 case D3DPOOL_MANAGED:
5204 return "D3DPOOL_MANAGED";
5205 default:
5206 return "unknown pool";
5210 static void test_vertex_buffer_alignment(void)
5212 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5213 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5214 IDirect3DVertexBuffer9 *buffer = NULL;
5215 const unsigned int align = 16;
5216 IDirect3DDevice9 *device;
5217 unsigned int i, j;
5218 IDirect3D9 *d3d9;
5219 ULONG refcount;
5220 HWND window;
5221 HRESULT hr;
5222 void *data;
5224 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5225 0, 0, 640, 480, 0, 0, 0, 0);
5226 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5227 ok(!!d3d9, "Failed to create a D3D object.\n");
5228 if (!(device = create_device(d3d9, window, NULL)))
5230 skip("Failed to create a D3D device, skipping tests.\n");
5231 IDirect3D9_Release(d3d9);
5232 DestroyWindow(window);
5233 return;
5236 for (i = 0; i < (sizeof(sizes) / sizeof(*sizes)); ++i)
5238 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
5240 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5241 if (pools[j] == D3DPOOL_SCRATCH)
5242 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5243 else
5244 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5245 debug_d3dpool(pools[j]), sizes[i], hr);
5246 if (FAILED(hr))
5247 continue;
5249 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5250 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5251 ok(!((DWORD_PTR)data & (align - 1)),
5252 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5253 data, align, sizes[i], debug_d3dpool(pools[j]));
5254 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5255 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5256 IDirect3DVertexBuffer9_Release(buffer);
5260 refcount = IDirect3DDevice9_Release(device);
5261 ok(!refcount, "Device has %u references left.\n", refcount);
5262 IDirect3D9_Release(d3d9);
5263 DestroyWindow(window);
5266 static void test_query_support(void)
5268 static const D3DQUERYTYPE queries[] =
5270 D3DQUERYTYPE_VCACHE,
5271 D3DQUERYTYPE_RESOURCEMANAGER,
5272 D3DQUERYTYPE_VERTEXSTATS,
5273 D3DQUERYTYPE_EVENT,
5274 D3DQUERYTYPE_OCCLUSION,
5275 D3DQUERYTYPE_TIMESTAMP,
5276 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5277 D3DQUERYTYPE_TIMESTAMPFREQ,
5278 D3DQUERYTYPE_PIPELINETIMINGS,
5279 D3DQUERYTYPE_INTERFACETIMINGS,
5280 D3DQUERYTYPE_VERTEXTIMINGS,
5281 D3DQUERYTYPE_PIXELTIMINGS,
5282 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5283 D3DQUERYTYPE_CACHEUTILIZATION,
5285 IDirect3DQuery9 *query = NULL;
5286 IDirect3DDevice9 *device;
5287 IDirect3D9 *d3d9;
5288 unsigned int i;
5289 ULONG refcount;
5290 BOOL supported;
5291 HWND window;
5292 HRESULT hr;
5294 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5295 0, 0, 640, 480, 0, 0, 0, 0);
5296 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5297 ok(!!d3d9, "Failed to create a D3D object.\n");
5298 if (!(device = create_device(d3d9, window, NULL)))
5300 skip("Failed to create a D3D device, skipping tests.\n");
5301 IDirect3D9_Release(d3d9);
5302 DestroyWindow(window);
5303 return;
5306 for (i = 0; i < sizeof(queries) / sizeof(*queries); ++i)
5308 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5309 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5311 supported = hr == D3D_OK;
5313 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5314 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5316 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5317 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5319 if (query)
5321 IDirect3DQuery9_Release(query);
5322 query = NULL;
5326 refcount = IDirect3DDevice9_Release(device);
5327 ok(!refcount, "Device has %u references left.\n", refcount);
5328 IDirect3D9_Release(d3d9);
5329 DestroyWindow(window);
5332 static void test_occlusion_query_states(void)
5334 static const float quad[] =
5336 -1.0f, -1.0f, 0.0f,
5337 -1.0f, 1.0f, 0.0f,
5338 1.0f, 1.0f, 0.0f,
5339 1.0f, -1.0f, 0.0f,
5341 struct device_desc device_desc;
5342 IDirect3DQuery9 *query = NULL;
5343 unsigned int data_size, i;
5344 IDirect3DDevice9 *device;
5345 IDirect3D9 *d3d9;
5346 ULONG refcount;
5347 HWND window;
5348 HRESULT hr;
5349 union
5351 WORD word[4];
5352 DWORD dword[2];
5353 } data;
5354 BOOL broken_occlusion = FALSE;
5355 DWORD expected = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5357 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5358 0, 0, 640, 480, 0, 0, 0, 0);
5359 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5360 ok(!!d3d9, "Failed to create a D3D object.\n");
5361 device_desc.device_window = window;
5362 device_desc.width = registry_mode.dmPelsWidth;
5363 device_desc.height = registry_mode.dmPelsHeight;
5364 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5365 if (!(device = create_device(d3d9, window, &device_desc)))
5367 skip("Failed to create a D3D device, skipping tests.\n");
5368 IDirect3D9_Release(d3d9);
5369 DestroyWindow(window);
5370 return;
5373 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5374 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5375 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5376 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5377 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5378 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5380 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5381 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5382 if (!query)
5384 skip("Occlusion queries are not supported, skipping tests.\n");
5385 IDirect3DDevice9_Release(device);
5386 IDirect3D9_Release(d3d9);
5387 DestroyWindow(window);
5388 return;
5391 data_size = IDirect3DQuery9_GetDataSize(query);
5392 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5394 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5395 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5396 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5397 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5399 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5400 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5401 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5402 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5403 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5404 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5406 data.dword[0] = 0x12345678;
5407 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5408 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5409 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5410 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5411 if (hr == D3D_OK)
5412 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5414 hr = IDirect3DDevice9_BeginScene(device);
5415 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5416 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5417 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5418 hr = IDirect3DDevice9_EndScene(device);
5419 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5421 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5422 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5423 for (i = 0; i < 500; ++i)
5425 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5426 break;
5427 Sleep(10);
5429 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5431 memset(&data, 0xff, sizeof(data));
5432 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5433 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5434 ok(data.dword[0] == expected || broken(!data.dword[0]),
5435 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5436 if (!data.dword[0])
5438 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5439 broken_occlusion = TRUE;
5442 memset(&data, 0xff, sizeof(data));
5443 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5444 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5445 if (!broken_occlusion)
5446 ok(data.word[0] == (WORD)expected,
5447 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5448 ok(data.word[1] == 0xffff,
5449 "data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5451 memset(&data, 0xf0, sizeof(data));
5452 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5453 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5454 if (!broken_occlusion)
5455 ok(data.dword[0] == expected,
5456 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5457 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5458 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5459 on AMD and Nvidia respectively). */
5460 if (0)
5462 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5463 data.dword[1]);
5466 memset(&data, 0xff, sizeof(data));
5467 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5468 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5469 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5471 /* This crashes on Windows. */
5472 if (0)
5474 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5475 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5478 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5479 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5480 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5481 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5482 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5483 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5485 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5487 IDirect3DQuery9_Release(query);
5488 refcount = IDirect3DDevice9_Release(device);
5489 ok(!refcount, "Device has %u references left.\n", refcount);
5490 IDirect3D9_Release(d3d9);
5491 DestroyWindow(window);
5494 static void test_timestamp_query(void)
5496 static const float quad[] =
5498 -1.0f, -1.0f, 0.0f,
5499 -1.0f, 1.0f, 0.0f,
5500 1.0f, 1.0f, 0.0f,
5501 1.0f, -1.0f, 0.0f,
5503 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5504 unsigned int data_size, i;
5505 IDirect3DDevice9 *device;
5506 IDirect3D9 *d3d9;
5507 ULONG refcount;
5508 HWND window;
5509 HRESULT hr;
5510 DWORD timestamp[2], freq[2];
5511 WORD disjoint[2];
5513 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5514 0, 0, 640, 480, 0, 0, 0, 0);
5515 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5516 ok(!!d3d9, "Failed to create a D3D object.\n");
5517 if (!(device = create_device(d3d9, window, NULL)))
5519 skip("Failed to create a D3D device, skipping tests.\n");
5520 IDirect3D9_Release(d3d9);
5521 DestroyWindow(window);
5522 return;
5525 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5526 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5527 if (FAILED(hr))
5529 skip("Timestamp queries are not supported, skipping tests.\n");
5530 IDirect3DDevice9_Release(device);
5531 IDirect3D9_Release(d3d9);
5532 DestroyWindow(window);
5533 return;
5535 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5536 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5538 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5539 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5540 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5541 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5543 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
5544 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5545 data_size = IDirect3DQuery9_GetDataSize(query);
5546 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5548 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
5549 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5550 for (i = 0; i < 500; ++i)
5552 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5553 break;
5554 Sleep(10);
5556 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5558 memset(freq, 0xff, sizeof(freq));
5559 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5560 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5561 ok(freq[1] == 0xffffffff,
5562 "freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
5563 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
5564 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5565 ok(freq[1] != 0xffffffff, "high bytes of freq were not modified (0x%.8x).\n",
5566 freq[1]);
5568 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5569 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5570 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5571 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5573 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5574 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5575 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5576 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5577 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
5578 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5580 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5581 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5583 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5584 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5585 hr = IDirect3DDevice9_BeginScene(device);
5586 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5587 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5588 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5589 hr = IDirect3DDevice9_EndScene(device);
5590 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5592 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5593 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5594 for (i = 0; i < 500; ++i)
5596 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5597 break;
5598 Sleep(10);
5600 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5602 memset(timestamp, 0xff, sizeof(timestamp));
5603 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
5604 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5605 ok(timestamp[1] == 0xffffffff,
5606 "timestamp was modified outside of the expected size (0x%.8x).\n",
5607 timestamp[1]);
5609 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5610 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5611 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5612 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5613 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5614 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5616 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
5617 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5618 for (i = 0; i < 500; ++i)
5620 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5621 break;
5622 Sleep(10);
5624 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5626 memset(disjoint, 0xff, sizeof(disjoint));
5627 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5628 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5629 ok(disjoint[1] == 0xffff,
5630 "disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
5631 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
5632 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5633 ok(disjoint[1] != 0xffff, "high bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
5635 /* It's not strictly necessary for the TIMESTAMP query to be inside
5636 * a TIMESTAMP_DISJOINT query. */
5637 hr = IDirect3DDevice9_BeginScene(device);
5638 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5639 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5640 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5641 hr = IDirect3DDevice9_EndScene(device);
5642 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5644 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5645 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5646 for (i = 0; i < 500; ++i)
5648 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5649 break;
5650 Sleep(10);
5652 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5653 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
5654 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5656 IDirect3DQuery9_Release(query);
5657 IDirect3DQuery9_Release(disjoint_query);
5658 IDirect3DQuery9_Release(freq_query);
5659 refcount = IDirect3DDevice9_Release(device);
5660 ok(!refcount, "Device has %u references left.\n", refcount);
5661 IDirect3D9_Release(d3d9);
5662 DestroyWindow(window);
5665 static void test_get_set_vertex_shader(void)
5667 IDirect3DVertexShader9 *current_shader = NULL;
5668 IDirect3DVertexShader9 *shader = NULL;
5669 const IDirect3DVertexShader9Vtbl *shader_vtbl;
5670 IDirect3DDevice9 *device;
5671 ULONG refcount, i;
5672 IDirect3D9 *d3d;
5673 D3DCAPS9 caps;
5674 HWND window;
5675 HRESULT hr;
5677 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5678 0, 0, 640, 480, 0, 0, 0, 0);
5679 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5680 ok(!!d3d, "Failed to create a D3D object.\n");
5681 if (!(device = create_device(d3d, window, NULL)))
5683 skip("Failed to create a D3D device, skipping tests.\n");
5684 IDirect3D9_Release(d3d);
5685 DestroyWindow(window);
5686 return;
5689 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5690 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5691 if (!(caps.VertexShaderVersion & 0xffff))
5693 skip("No vertex shader support, skipping tests.\n");
5694 IDirect3DDevice9_Release(device);
5695 IDirect3D9_Release(d3d);
5696 DestroyWindow(window);
5697 return;
5700 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
5701 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5702 ok(!!shader, "Got unexpected shader %p.\n", shader);
5704 /* SetVertexShader() should not touch the shader's refcount. */
5705 i = get_refcount((IUnknown *)shader);
5706 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5707 refcount = get_refcount((IUnknown *)shader);
5708 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5709 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5711 /* GetVertexShader() should increase the shader's refcount by one. */
5712 i = refcount + 1;
5713 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
5714 refcount = get_refcount((IUnknown *)shader);
5715 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
5716 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5717 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
5718 IDirect3DVertexShader9_Release(current_shader);
5720 /* SetVertexShader() with a bogus shader vtbl */
5721 shader_vtbl = shader->lpVtbl;
5722 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
5723 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5724 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5725 shader->lpVtbl = NULL;
5726 hr = IDirect3DDevice9_SetVertexShader(device, shader);
5727 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
5728 shader->lpVtbl = shader_vtbl;
5730 IDirect3DVertexShader9_Release(shader);
5731 refcount = IDirect3DDevice9_Release(device);
5732 ok(!refcount, "Device has %u references left.\n", refcount);
5733 IDirect3D9_Release(d3d);
5734 DestroyWindow(window);
5737 static void test_vertex_shader_constant(void)
5739 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};
5740 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
5741 IDirect3DDevice9 *device;
5742 IDirect3D9 *d3d;
5743 ULONG refcount;
5744 D3DCAPS9 caps;
5745 DWORD consts;
5746 HWND window;
5747 HRESULT hr;
5749 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5750 0, 0, 640, 480, 0, 0, 0, 0);
5751 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5752 ok(!!d3d, "Failed to create a D3D object.\n");
5753 if (!(device = create_device(d3d, window, NULL)))
5755 skip("Failed to create a D3D device, skipping tests.\n");
5756 IDirect3D9_Release(d3d);
5757 DestroyWindow(window);
5758 return;
5761 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5762 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5763 if (!(caps.VertexShaderVersion & 0xffff))
5765 skip("No vertex shader support, skipping tests.\n");
5766 IDirect3DDevice9_Release(device);
5767 IDirect3D9_Release(d3d);
5768 DestroyWindow(window);
5769 return;
5771 consts = caps.MaxVertexShaderConst;
5773 /* A simple check that the stuff works at all. */
5774 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
5775 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5777 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
5778 * consts from MAX - 1. */
5779 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
5780 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5781 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
5782 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5783 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
5784 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5785 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
5786 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5788 /* Constant -1. */
5789 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
5790 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5792 refcount = IDirect3DDevice9_Release(device);
5793 ok(!refcount, "Device has %u references left.\n", refcount);
5794 IDirect3D9_Release(d3d);
5795 DestroyWindow(window);
5798 static void test_get_set_pixel_shader(void)
5800 IDirect3DPixelShader9 *current_shader = NULL;
5801 IDirect3DPixelShader9 *shader = NULL;
5802 const IDirect3DPixelShader9Vtbl *shader_vtbl;
5803 IDirect3DDevice9 *device;
5804 ULONG refcount, i;
5805 IDirect3D9 *d3d;
5806 D3DCAPS9 caps;
5807 HWND window;
5808 HRESULT hr;
5810 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5811 0, 0, 640, 480, 0, 0, 0, 0);
5812 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5813 ok(!!d3d, "Failed to create a D3D object.\n");
5814 if (!(device = create_device(d3d, window, NULL)))
5816 skip("Failed to create a D3D device, skipping tests.\n");
5817 IDirect3D9_Release(d3d);
5818 DestroyWindow(window);
5819 return;
5822 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5823 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5824 if (!(caps.PixelShaderVersion & 0xffff))
5826 skip("No pixel shader support, skipping tests.\n");
5827 IDirect3DDevice9_Release(device);
5828 IDirect3D9_Release(d3d);
5829 DestroyWindow(window);
5830 return;
5833 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
5834 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
5835 ok(!!shader, "Got unexpected shader %p.\n", shader);
5837 /* SetPixelShader() should not touch the shader's refcount. */
5838 i = get_refcount((IUnknown *)shader);
5839 hr = IDirect3DDevice9_SetPixelShader(device, shader);
5840 refcount = get_refcount((IUnknown *)shader);
5841 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
5842 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5844 /* GetPixelShader() should increase the shader's refcount by one. */
5845 i = refcount + 1;
5846 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
5847 refcount = get_refcount((IUnknown *)shader);
5848 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
5849 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
5850 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
5851 IDirect3DPixelShader9_Release(current_shader);
5853 /* SetPixelShader() with a bogus shader vtbl */
5854 shader_vtbl = shader->lpVtbl;
5855 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
5856 hr = IDirect3DDevice9_SetPixelShader(device, shader);
5857 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
5858 shader->lpVtbl = NULL;
5859 hr = IDirect3DDevice9_SetPixelShader(device, shader);
5860 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
5861 shader->lpVtbl = shader_vtbl;
5863 IDirect3DPixelShader9_Release(shader);
5864 refcount = IDirect3DDevice9_Release(device);
5865 ok(!refcount, "Device has %u references left.\n", refcount);
5866 IDirect3D9_Release(d3d);
5867 DestroyWindow(window);
5870 static void test_pixel_shader_constant(void)
5872 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};
5873 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
5874 IDirect3DDevice9 *device;
5875 DWORD consts = 0;
5876 IDirect3D9 *d3d;
5877 ULONG refcount;
5878 D3DCAPS9 caps;
5879 HWND window;
5880 HRESULT hr;
5882 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5883 0, 0, 640, 480, 0, 0, 0, 0);
5884 d3d = Direct3DCreate9(D3D_SDK_VERSION);
5885 ok(!!d3d, "Failed to create a D3D object.\n");
5886 if (!(device = create_device(d3d, window, NULL)))
5888 skip("Failed to create a D3D device, skipping tests.\n");
5889 IDirect3D9_Release(d3d);
5890 DestroyWindow(window);
5891 return;
5894 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5895 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5896 if (!(caps.PixelShaderVersion & 0xffff))
5898 skip("No pixel shader support, skipping tests.\n");
5899 IDirect3DDevice9_Release(device);
5900 IDirect3D9_Release(d3d);
5901 DestroyWindow(window);
5902 return;
5905 /* A simple check that the stuff works at all. */
5906 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
5907 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5909 /* Is there really no max pixel shader constant value??? Test how far I can go. */
5910 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
5911 consts = consts - 1;
5912 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
5914 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
5915 * pointless given the way the constant limit was determined. */
5916 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
5917 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5919 /* Constant -1. */
5920 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
5921 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
5923 refcount = IDirect3DDevice9_Release(device);
5924 ok(!refcount, "Device has %u references left.\n", refcount);
5925 IDirect3D9_Release(d3d);
5926 DestroyWindow(window);
5929 static void test_unsupported_shaders(void)
5931 static const DWORD vs_3_0[] =
5933 0xfffe0300, /* vs_3_0 */
5934 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
5935 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
5936 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
5937 0x0000ffff, /* end */
5940 #if 0
5941 float4 main(const float4 color : COLOR) : SV_TARGET
5943 float4 o;
5945 o = color;
5947 return o;
5949 #endif
5950 static const DWORD ps_4_0[] =
5952 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
5953 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
5954 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
5955 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
5956 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
5957 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
5958 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
5959 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
5960 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
5961 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
5962 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
5963 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
5964 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
5965 0x00000000, 0x00000000, 0x00000000,
5967 #if 0
5968 vs_1_1
5969 dcl_position v0
5970 def c255, 1.0, 1.0, 1.0, 1.0
5971 add r0, v0, c255
5972 mov oPos, r0
5973 #endif
5974 static const DWORD vs_1_255[] =
5976 0xfffe0101,
5977 0x0000001f, 0x80000000, 0x900f0000,
5978 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
5979 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
5980 0x00000001, 0xc00f0000, 0x80e40000,
5981 0x0000ffff
5983 #if 0
5984 vs_1_1
5985 dcl_position v0
5986 def c256, 1.0, 1.0, 1.0, 1.0
5987 add r0, v0, c256
5988 mov oPos, r0
5989 #endif
5990 static const DWORD vs_1_256[] =
5992 0xfffe0101,
5993 0x0000001f, 0x80000000, 0x900f0000,
5994 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
5995 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
5996 0x00000001, 0xc00f0000, 0x80e40000,
5997 0x0000ffff
5999 #if 0
6000 vs_3_0
6001 dcl_position v0
6002 dcl_position o0
6003 def c256, 1.0, 1.0, 1.0, 1.0
6004 add r0, v0, c256
6005 mov o0, r0
6006 #endif
6007 static const DWORD vs_3_256[] =
6009 0xfffe0300,
6010 0x0200001f, 0x80000000, 0x900f0000,
6011 0x0200001f, 0x80000000, 0xe00f0000,
6012 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6013 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6014 0x02000001, 0xe00f0000, 0x80e40000,
6015 0x0000ffff
6017 #if 0
6018 /* This shader source generates syntax errors with the native shader assembler
6019 * due to the constant register index values.
6020 * The bytecode was modified by hand to use the intended values. */
6021 vs_3_0
6022 dcl_position v0
6023 dcl_position o0
6024 defi i16, 1, 1, 1, 1
6025 rep i16
6026 add r0, r0, v0
6027 endrep
6028 mov o0, r0
6029 #endif
6030 static const DWORD vs_3_i16[] =
6032 0xfffe0300,
6033 0x0200001f, 0x80000000, 0x900f0000,
6034 0x0200001f, 0x80000000, 0xe00f0000,
6035 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6036 0x01000026, 0xf0e40010,
6037 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6038 0x00000027,
6039 0x02000001, 0xe00f0000, 0x80e40000,
6040 0x0000ffff
6042 #if 0
6043 /* This shader source generates syntax errors with the native shader assembler
6044 * due to the constant register index values.
6045 * The bytecode was modified by hand to use the intended values. */
6046 vs_3_0
6047 dcl_position v0
6048 dcl_position o0
6049 defb b16, true
6050 mov r0, v0
6051 if b16
6052 add r0, r0, v0
6053 endif
6054 mov o0, r0
6055 #endif
6056 static const DWORD vs_3_b16[] =
6058 0xfffe0300,
6059 0x0200001f, 0x80000000, 0x900f0000,
6060 0x0200001f, 0x80000000, 0xe00f0000,
6061 0x0200002f, 0xe00f0810, 0x00000001,
6062 0x02000001, 0x800f0000, 0x90e40000,
6063 0x01000028, 0xe0e40810,
6064 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6065 0x0000002b,
6066 0x02000001, 0xe00f0000, 0x80e40000,
6067 0x0000ffff
6069 #if 0
6070 /* This shader source generates syntax errors with the native shader assembler
6071 * due to the constant register index values.
6072 * The bytecode was modified by hand to use the intended values. */
6073 ps_1_1
6074 def c8, 1.0, 1.0, 1.0, 1.0
6075 add r0, v0, c8
6076 #endif
6077 static const DWORD ps_1_8[] =
6079 0xffff0101,
6080 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6081 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6082 0x0000ffff
6084 #if 0
6085 /* This shader source generates syntax errors with the native shader assembler
6086 * due to the constant register index values.
6087 * The bytecode was modified by hand to use the intended values. */
6088 ps_2_0
6089 def c32, 1.0, 1.0, 1.0, 1.0
6090 add oC0, v0, c32
6091 #endif
6092 static const DWORD ps_2_32[] =
6094 0xffff0200,
6095 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6096 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6097 0x0000ffff
6099 #if 0
6100 /* This shader source generates syntax errors with the native shader assembler
6101 * due to the constant register index values.
6102 * The bytecode was modified by hand to use the intended values. */
6103 ps_3_0
6104 dcl_color0 v0
6105 def c224, 1.0, 1.0, 1.0, 1.0
6106 add oC0, v0, c224
6107 #endif
6108 static const DWORD ps_3_224[] =
6110 0xffff0300,
6111 0x0200001f, 0x8000000a, 0x900f0000,
6112 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6113 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6114 0x0000ffff
6116 #if 0
6117 /* This shader source generates syntax errors with the native shader assembler
6118 * due to the constant register index values.
6119 * The bytecode was modified by hand to use the intended values. */
6120 ps_2_0
6121 defb b0, true
6122 defi i0, 1, 1, 1, 1
6123 rep i0
6124 if b0
6125 add r0, r0, v0
6126 endif
6127 endrep
6128 mov oC0, r0
6129 #endif
6130 static const DWORD ps_2_0_boolint[] =
6132 0xffff0200,
6133 0x0200002f, 0xe00f0800, 0x00000001,
6134 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6135 0x01000026, 0xf0e40000,
6136 0x01000028, 0xe0e40800,
6137 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6138 0x0000002b,
6139 0x00000027,
6140 0x02000001, 0x800f0800, 0x80e40000,
6141 0x0000ffff
6144 IDirect3DVertexShader9 *vs = NULL;
6145 IDirect3DPixelShader9 *ps = NULL;
6146 IDirect3DDevice9 *device;
6147 IDirect3D9 * d3d;
6148 ULONG refcount;
6149 D3DCAPS9 caps;
6150 HWND window;
6151 HRESULT hr;
6153 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6154 0, 0, 640, 480, 0, 0, 0, 0);
6155 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6156 ok(!!d3d, "Failed to create a D3D object.\n");
6157 if (!(device = create_device(d3d, window, NULL)))
6159 skip("Failed to create a D3D device, skipping tests.\n");
6160 IDirect3D9_Release(d3d);
6161 DestroyWindow(window);
6162 return;
6165 /* These should always fail, regardless of supported shader version. */
6166 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6167 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6168 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6169 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6170 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6171 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6173 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6174 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6175 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6177 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6178 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6179 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6181 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6182 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6184 else
6186 skip("GPU supports SM2+, skipping SM1 test.\n");
6189 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6191 else
6193 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6195 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6196 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6197 IDirect3DVertexShader9_Release(vs);
6198 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6199 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6200 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6201 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6202 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6203 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6204 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6205 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6208 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6210 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6211 goto cleanup;
6213 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6214 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6215 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6216 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6217 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6218 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6219 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6220 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6221 if (ps)
6222 IDirect3DPixelShader9_Release(ps);
6224 cleanup:
6225 refcount = IDirect3DDevice9_Release(device);
6226 ok(!refcount, "Device has %u references left.\n", refcount);
6227 IDirect3D9_Release(d3d);
6228 DestroyWindow(window);
6231 /* Test the default texture stage state values */
6232 static void test_texture_stage_states(void)
6234 IDirect3DDevice9 *device;
6235 IDirect3D9 *d3d;
6236 unsigned int i;
6237 ULONG refcount;
6238 D3DCAPS9 caps;
6239 DWORD value;
6240 HWND window;
6241 HRESULT hr;
6243 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6244 0, 0, 640, 480, 0, 0, 0, 0);
6245 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6246 ok(!!d3d, "Failed to create a D3D object.\n");
6247 if (!(device = create_device(d3d, window, NULL)))
6249 skip("Failed to create a D3D device, skipping tests.\n");
6250 IDirect3D9_Release(d3d);
6251 DestroyWindow(window);
6252 return;
6255 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6256 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6258 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6260 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6261 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6262 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6263 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6264 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6265 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6266 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6267 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6268 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6269 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6270 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6271 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6272 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6273 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6274 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6275 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6276 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6277 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6278 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6279 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6280 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6281 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6282 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6283 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6284 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6285 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6286 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6287 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6288 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6289 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6290 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6291 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6292 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6293 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6294 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6295 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6296 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6297 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6298 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6299 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6300 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6301 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6302 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6303 ok(value == D3DTTFF_DISABLE,
6304 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6305 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6306 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6307 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6308 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6309 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6310 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6311 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6312 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6313 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6314 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6315 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6316 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6319 refcount = IDirect3DDevice9_Release(device);
6320 ok(!refcount, "Device has %u references left.\n", refcount);
6321 IDirect3D9_Release(d3d);
6322 DestroyWindow(window);
6325 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6327 IDirect3DCubeTexture9 *texture;
6328 IDirect3D9 *d3d;
6329 HRESULT hr;
6331 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6332 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6333 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6334 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6335 IDirect3D9_Release(d3d);
6336 if (FAILED(hr))
6338 skip("No cube mipmap generation support, skipping tests.\n");
6339 return;
6342 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6343 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6344 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6345 IDirect3DCubeTexture9_Release(texture);
6347 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6348 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6349 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6350 IDirect3DCubeTexture9_Release(texture);
6353 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6355 IDirect3DCubeTexture9 *texture;
6356 IDirect3DSurface9 *surface;
6357 D3DSURFACE_DESC desc;
6358 DWORD levels;
6359 HRESULT hr;
6360 D3DCAPS9 caps;
6362 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6363 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6364 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6365 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6367 skip("Failed to create cube texture, skipping tests.\n");
6368 return;
6371 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6372 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6373 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6374 else
6375 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6377 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6378 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6379 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6380 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6381 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6382 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6384 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6385 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6386 IDirect3DSurface9_Release(surface);
6387 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6388 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6389 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6390 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6392 IDirect3DCubeTexture9_Release(texture);
6395 static void test_cube_textures(void)
6397 IDirect3DCubeTexture9 *texture;
6398 IDirect3DDevice9 *device;
6399 IDirect3D9 *d3d;
6400 ULONG refcount;
6401 D3DCAPS9 caps;
6402 HWND window;
6403 HRESULT hr;
6405 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6406 0, 0, 640, 480, 0, 0, 0, 0);
6407 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6408 ok(!!d3d, "Failed to create a D3D object.\n");
6409 if (!(device = create_device(d3d, window, NULL)))
6411 skip("Failed to create a D3D device, skipping tests.\n");
6412 IDirect3D9_Release(d3d);
6413 DestroyWindow(window);
6414 return;
6417 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6418 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6420 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
6422 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6423 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
6424 IDirect3DCubeTexture9_Release(texture);
6425 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6426 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
6427 IDirect3DCubeTexture9_Release(texture);
6428 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6429 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
6430 IDirect3DCubeTexture9_Release(texture);
6432 else
6434 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6435 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
6436 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6437 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
6438 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
6439 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
6441 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
6442 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
6443 IDirect3DCubeTexture9_Release(texture);
6445 test_cube_texture_mipmap_gen(device);
6446 test_cube_texture_levels(device);
6448 refcount = IDirect3DDevice9_Release(device);
6449 ok(!refcount, "Device has %u references left.\n", refcount);
6450 IDirect3D9_Release(d3d);
6451 DestroyWindow(window);
6454 static void test_mipmap_gen(void)
6456 D3DTEXTUREFILTERTYPE filter_type;
6457 IDirect3DTexture9 *texture;
6458 IDirect3DSurface9 *surface;
6459 IDirect3DDevice9 *device;
6460 D3DSURFACE_DESC desc;
6461 D3DLOCKED_RECT lr;
6462 IDirect3D9 *d3d;
6463 ULONG refcount;
6464 unsigned int i;
6465 DWORD levels;
6466 HWND window;
6467 HRESULT hr;
6469 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6470 ok(!!d3d, "Failed to create a D3D object.\n");
6472 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6473 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8)))
6475 skip("No mipmap generation support, skipping tests.\n");
6476 IDirect3D9_Release(d3d);
6477 return;
6480 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6481 0, 0, 640, 480, 0, 0, 0, 0);
6482 if (!(device = create_device(d3d, window, NULL)))
6484 skip("Failed to create a D3D device, skipping tests.\n");
6485 IDirect3D9_Release(d3d);
6486 DestroyWindow(window);
6487 return;
6490 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6491 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6492 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6493 IDirect3DTexture9_Release(texture);
6495 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6496 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6497 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6499 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6500 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
6501 "Got unexpected filter_type %#x.\n", filter_type);
6502 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
6503 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6504 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
6505 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6506 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
6507 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
6508 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
6509 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6511 levels = IDirect3DTexture9_GetLevelCount(texture);
6512 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6514 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
6516 surface = NULL;
6517 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
6518 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6519 if (surface)
6520 IDirect3DSurface9_Release(surface);
6522 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
6523 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6525 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
6526 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
6527 if (SUCCEEDED(hr))
6529 hr = IDirect3DTexture9_UnlockRect(texture, i);
6530 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
6533 IDirect3DTexture9_Release(texture);
6535 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
6536 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6537 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6538 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
6539 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6540 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6542 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
6543 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
6544 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6545 levels = IDirect3DTexture9_GetLevelCount(texture);
6546 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6547 IDirect3DTexture9_Release(texture);
6549 refcount = IDirect3DDevice9_Release(device);
6550 ok(!refcount, "Device has %u references left.\n", refcount);
6551 IDirect3D9_Release(d3d);
6552 DestroyWindow(window);
6555 static void test_filter(void)
6557 static const struct
6559 DWORD magfilter, minfilter, mipfilter;
6560 BOOL has_texture;
6561 HRESULT result;
6563 tests[] =
6565 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6566 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6567 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6568 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
6569 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
6571 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6572 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6573 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
6574 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
6576 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6577 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
6578 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
6579 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
6580 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
6582 IDirect3DTexture9 *texture;
6583 IDirect3DDevice9 *device;
6584 IDirect3D9 *d3d;
6585 unsigned int i;
6586 ULONG refcount;
6587 DWORD passes;
6588 HWND window;
6589 HRESULT hr;
6591 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6592 ok(!!d3d, "Failed to create a D3D object.\n");
6594 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6595 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6597 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
6598 IDirect3D9_Release(d3d);
6599 return;
6602 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6603 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
6605 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
6606 IDirect3D9_Release(d3d);
6607 return;
6610 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6611 0, 0, 640, 480, 0, 0, 0, 0);
6612 if (!(device = create_device(d3d, window, NULL)))
6614 skip("Failed to create a D3D device, skipping tests.\n");
6615 IDirect3D9_Release(d3d);
6616 DestroyWindow(window);
6617 return;
6620 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
6621 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
6622 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6624 /* Needed for ValidateDevice(). */
6625 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6626 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
6628 for (i = 0; i < (sizeof(tests) / sizeof(*tests)); ++i)
6630 if (tests[i].has_texture)
6632 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
6633 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6635 else
6637 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6638 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6641 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
6642 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6643 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
6644 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6645 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
6646 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
6648 passes = 0xdeadbeef;
6649 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
6650 ok(hr == tests[i].result,
6651 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
6652 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
6653 tests[i].mipfilter, tests[i].has_texture);
6654 if (SUCCEEDED(hr))
6655 ok(!!passes, "Got unexpected passes %#x.\n", passes);
6656 else
6657 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
6660 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6661 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6662 IDirect3DTexture9_Release(texture);
6664 refcount = IDirect3DDevice9_Release(device);
6665 ok(!refcount, "Device has %u references left.\n", refcount);
6666 IDirect3D9_Release(d3d);
6667 DestroyWindow(window);
6670 static void test_get_set_texture(void)
6672 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
6673 IDirect3DBaseTexture9 *texture;
6674 IDirect3DDevice9 *device;
6675 IDirect3D9 *d3d;
6676 ULONG refcount;
6677 HWND window;
6678 HRESULT hr;
6680 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6681 0, 0, 640, 480, 0, 0, 0, 0);
6682 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6683 ok(!!d3d, "Failed to create a D3D object.\n");
6684 if (!(device = create_device(d3d, window, NULL)))
6686 skip("Failed to create a D3D device, skipping tests.\n");
6687 IDirect3D9_Release(d3d);
6688 DestroyWindow(window);
6689 return;
6692 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
6693 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6694 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6695 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
6696 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6697 ok(!texture, "Got unexpected texture %p.\n", texture);
6699 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
6700 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
6701 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6702 texture_vtbl = texture->lpVtbl;
6703 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
6704 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6705 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6706 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6707 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6708 texture->lpVtbl = NULL;
6709 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
6710 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6711 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6712 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
6713 texture->lpVtbl = texture_vtbl;
6714 IDirect3DBaseTexture9_Release(texture);
6716 refcount = IDirect3DDevice9_Release(device);
6717 ok(!refcount, "Device has %u references left.\n", refcount);
6718 IDirect3D9_Release(d3d);
6719 DestroyWindow(window);
6722 static void test_lod(void)
6724 IDirect3DTexture9 *texture;
6725 IDirect3DDevice9 *device;
6726 IDirect3D9 *d3d;
6727 ULONG refcount;
6728 HWND window;
6729 HRESULT hr;
6730 DWORD ret;
6732 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6733 0, 0, 640, 480, 0, 0, 0, 0);
6734 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6735 ok(!!d3d, "Failed to create a D3D object.\n");
6736 if (!(device = create_device(d3d, window, NULL)))
6738 skip("Failed to create a D3D device, skipping tests.\n");
6739 IDirect3D9_Release(d3d);
6740 DestroyWindow(window);
6741 return;
6744 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
6745 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6746 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6748 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
6749 * return a HRESULT, so it can't return a normal error. Instead, the call
6750 * is simply ignored. */
6751 ret = IDirect3DTexture9_SetLOD(texture, 0);
6752 ok(!ret, "Got unexpected ret %u.\n", ret);
6753 ret = IDirect3DTexture9_SetLOD(texture, 1);
6754 ok(!ret, "Got unexpected ret %u.\n", ret);
6755 ret = IDirect3DTexture9_SetLOD(texture, 2);
6756 ok(!ret, "Got unexpected ret %u.\n", ret);
6757 ret = IDirect3DTexture9_GetLOD(texture);
6758 ok(!ret, "Got unexpected ret %u.\n", ret);
6760 IDirect3DTexture9_Release(texture);
6761 refcount = IDirect3DDevice9_Release(device);
6762 ok(!refcount, "Device has %u references left.\n", refcount);
6763 IDirect3D9_Release(d3d);
6764 DestroyWindow(window);
6767 static void test_surface_get_container(void)
6769 IDirect3DTexture9 *texture = NULL;
6770 IDirect3DSurface9 *surface = NULL;
6771 IDirect3DDevice9 *device;
6772 IUnknown *container;
6773 IDirect3D9 *d3d;
6774 ULONG refcount;
6775 HWND window;
6776 HRESULT hr;
6778 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6779 0, 0, 640, 480, 0, 0, 0, 0);
6780 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6781 ok(!!d3d, "Failed to create a D3D object.\n");
6782 if (!(device = create_device(d3d, window, NULL)))
6784 skip("Failed to create a D3D device, skipping tests.\n");
6785 IDirect3D9_Release(d3d);
6786 DestroyWindow(window);
6787 return;
6790 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
6791 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6792 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
6793 ok(!!texture, "Got unexpected texture %p.\n", texture);
6795 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6796 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
6797 ok(!!surface, "Got unexpected surface %p.\n", surface);
6799 /* These should work... */
6800 container = NULL;
6801 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
6802 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6803 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6804 IUnknown_Release(container);
6806 container = NULL;
6807 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
6808 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6809 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6810 IUnknown_Release(container);
6812 container = NULL;
6813 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
6814 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6815 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6816 IUnknown_Release(container);
6818 container = NULL;
6819 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
6820 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
6821 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
6822 IUnknown_Release(container);
6824 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
6825 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
6826 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
6827 ok(!container, "Got unexpected container %p.\n", container);
6829 IDirect3DSurface9_Release(surface);
6830 IDirect3DTexture9_Release(texture);
6831 refcount = IDirect3DDevice9_Release(device);
6832 ok(!refcount, "Device has %u references left.\n", refcount);
6833 IDirect3D9_Release(d3d);
6834 DestroyWindow(window);
6837 static void test_surface_alignment(void)
6839 IDirect3DSurface9 *surface;
6840 IDirect3DDevice9 *device;
6841 D3DLOCKED_RECT lr;
6842 unsigned int i, j;
6843 IDirect3D9 *d3d;
6844 ULONG refcount;
6845 HWND window;
6846 HRESULT hr;
6848 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6849 0, 0, 640, 480, 0, 0, 0, 0);
6850 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6851 ok(!!d3d, "Failed to create a D3D object.\n");
6852 if (!(device = create_device(d3d, window, NULL)))
6854 skip("Failed to create a D3D device, skipping tests.\n");
6855 IDirect3D9_Release(d3d);
6856 DestroyWindow(window);
6857 return;
6860 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
6861 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
6862 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
6863 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6865 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
6866 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6867 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
6868 /* Some applications also depend on the exact pitch, rather than just the
6869 * alignment. */
6870 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
6871 hr = IDirect3DSurface9_UnlockRect(surface);
6872 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6873 IDirect3DSurface9_Release(surface);
6875 for (i = 0; i < 5; ++i)
6877 IDirect3DTexture9 *texture;
6878 unsigned int level_count;
6879 D3DSURFACE_DESC desc;
6880 int expected_pitch;
6882 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
6883 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
6884 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6885 if (FAILED(hr))
6887 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
6888 continue;
6891 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
6892 for (j = 0; j < level_count; ++j)
6894 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
6895 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
6896 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
6897 hr = IDirect3DTexture9_UnlockRect(texture, j);
6898 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
6900 expected_pitch = ((desc.Width + 3) >> 2) << 3;
6901 if (i > 0)
6902 expected_pitch <<= 1;
6903 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
6904 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
6906 IDirect3DTexture9_Release(texture);
6909 refcount = IDirect3DDevice9_Release(device);
6910 ok(!refcount, "Device has %u references left.\n", refcount);
6911 IDirect3D9_Release(d3d);
6912 DestroyWindow(window);
6915 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
6916 * different from regular formats. This test verifies we return the correct
6917 * memory offsets. */
6918 static void test_lockrect_offset(void)
6920 static const struct
6922 D3DFORMAT format;
6923 const char *name;
6924 unsigned int block_width;
6925 unsigned int block_height;
6926 unsigned int block_size;
6928 dxt_formats[] =
6930 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
6931 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
6932 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
6933 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
6934 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
6935 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
6936 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
6938 unsigned int expected_offset, offset, i;
6939 const RECT rect = {60, 60, 68, 68};
6940 IDirect3DSurface9 *surface;
6941 D3DLOCKED_RECT locked_rect;
6942 IDirect3DDevice9 *device;
6943 int expected_pitch;
6944 IDirect3D9 *d3d;
6945 ULONG refcount;
6946 HWND window;
6947 BYTE *base;
6948 HRESULT hr;
6950 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6951 0, 0, 640, 480, 0, 0, 0, 0);
6952 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6953 ok(!!d3d, "Failed to create a D3D object.\n");
6954 if (!(device = create_device(d3d, window, NULL)))
6956 skip("Failed to create a D3D device, skipping tests.\n");
6957 IDirect3D9_Release(d3d);
6958 DestroyWindow(window);
6959 return;
6962 for (i = 0; i < (sizeof(dxt_formats) / sizeof(*dxt_formats)); ++i)
6964 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6965 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
6967 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
6968 continue;
6971 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
6972 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
6973 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
6975 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
6976 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6978 base = locked_rect.pBits;
6979 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
6980 * dxt_formats[i].block_size;
6981 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
6982 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
6984 hr = IDirect3DSurface9_UnlockRect(surface);
6985 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6987 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
6988 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
6990 offset = (BYTE *)locked_rect.pBits - base;
6991 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
6992 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
6993 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
6994 offset, dxt_formats[i].name, expected_offset);
6996 hr = IDirect3DSurface9_UnlockRect(surface);
6997 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
6999 IDirect3DSurface9_Release(surface);
7002 refcount = IDirect3DDevice9_Release(device);
7003 ok(!refcount, "Device has %u references left.\n", refcount);
7004 IDirect3D9_Release(d3d);
7005 DestroyWindow(window);
7008 static void test_lockrect_invalid(void)
7010 static const struct
7012 RECT rect;
7013 HRESULT win7_result;
7015 test_data[] =
7017 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7018 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7019 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7020 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7021 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7022 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7023 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7024 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7025 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7026 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7027 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7028 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7029 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7031 static const RECT test_rect_2 = {0, 0, 8, 8};
7032 IDirect3DSurface9 *surface = NULL;
7033 D3DLOCKED_RECT locked_rect;
7034 IDirect3DDevice9 *device;
7035 IDirect3DTexture9 *texture;
7036 IDirect3DCubeTexture9 *cube_texture;
7037 IDirect3D9 *d3d;
7038 unsigned int i, r;
7039 ULONG refcount;
7040 HWND window;
7041 BYTE *base;
7042 HRESULT hr;
7043 static const struct
7045 D3DRESOURCETYPE type;
7046 D3DPOOL pool;
7047 const char *name;
7049 resources[] =
7051 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7052 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7053 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7054 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7055 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7056 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7057 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7060 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7061 0, 0, 640, 480, 0, 0, 0, 0);
7062 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7063 ok(!!d3d, "Failed to create a D3D object.\n");
7064 if (!(device = create_device(d3d, window, NULL)))
7066 skip("Failed to create a D3D device, skipping tests.\n");
7067 IDirect3D9_Release(d3d);
7068 DestroyWindow(window);
7069 return;
7072 for (r = 0; r < sizeof(resources) / sizeof(*resources); ++r)
7074 texture = NULL;
7075 cube_texture = NULL;
7076 switch (resources[r].type)
7078 case D3DRTYPE_SURFACE:
7079 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7080 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7081 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7082 hr, resources[r].name);
7083 break;
7085 case D3DRTYPE_TEXTURE:
7086 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7087 resources[r].pool, &texture, NULL);
7088 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7089 hr, resources[r].name);
7090 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7091 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7092 hr, resources[r].name);
7093 break;
7095 case D3DRTYPE_CUBETEXTURE:
7096 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7097 resources[r].pool, &cube_texture, NULL);
7098 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7099 hr, resources[r].name);
7100 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7101 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7102 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7103 hr, resources[r].name);
7104 break;
7106 default:
7107 break;
7110 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7111 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7112 base = locked_rect.pBits;
7113 hr = IDirect3DSurface9_UnlockRect(surface);
7114 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7116 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
7118 unsigned int offset, expected_offset;
7119 const RECT *rect = &test_data[i].rect;
7121 locked_rect.pBits = (BYTE *)0xdeadbeef;
7122 locked_rect.Pitch = 0xdeadbeef;
7124 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7125 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7126 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7127 * one broken. */
7128 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7129 "Failed to lock surface with rect [%d, %d]->[%d, %d], hr %#x, type %s.\n",
7130 rect->left, rect->top, rect->right, rect->bottom, hr, resources[r].name);
7131 if (FAILED(hr))
7132 continue;
7134 offset = (BYTE *)locked_rect.pBits - base;
7135 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7136 ok(offset == expected_offset,
7137 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d], type %s.\n",
7138 offset, expected_offset, rect->left, rect->top,
7139 rect->right, rect->bottom, resources[r].name);
7141 hr = IDirect3DSurface9_UnlockRect(surface);
7142 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7144 if (texture)
7146 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7147 ok(SUCCEEDED(hr),
7148 "Failed to lock texture with rect [%d, %d]->[%d, %d], hr %#x, type %s.\n",
7149 rect->left, rect->top, rect->right, rect->bottom, hr, resources[r].name);
7150 if (FAILED(hr))
7151 continue;
7153 offset = (BYTE *)locked_rect.pBits - base;
7154 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7155 ok(offset == expected_offset,
7156 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d], type %s.\n",
7157 offset, expected_offset, rect->left, rect->top,
7158 rect->right, rect->bottom, resources[r].name);
7160 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7161 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7163 if (cube_texture)
7165 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7166 &locked_rect, rect, 0);
7167 ok(SUCCEEDED(hr),
7168 "Failed to lock texture with rect [%d, %d]->[%d, %d], hr %#x, type %s.\n",
7169 rect->left, rect->top, rect->right, rect->bottom, hr, resources[r].name);
7170 if (FAILED(hr))
7171 continue;
7173 offset = (BYTE *)locked_rect.pBits - base;
7174 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7175 ok(offset == expected_offset,
7176 "Got unexpected offset %u (expected %u) for rect [%d, %d]->[%d, %d], type %s.\n",
7177 offset, expected_offset, rect->left, rect->top,
7178 rect->right, rect->bottom, resources[r].name);
7180 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7181 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7185 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7186 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7187 locked_rect.pBits = (BYTE *)0xdeadbeef;
7188 locked_rect.Pitch = 1;
7189 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7190 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7191 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7192 locked_rect.pBits, resources[r].name);
7193 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7194 locked_rect.Pitch, resources[r].name);
7195 hr = IDirect3DSurface9_UnlockRect(surface);
7196 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7198 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7199 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7200 hr, test_data[0].rect.left, test_data[0].rect.top,
7201 test_data[0].rect.right, test_data[0].rect.bottom, resources[r].name);
7202 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7203 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7204 hr, test_data[0].rect.left, test_data[0].rect.top,
7205 test_data[0].rect.right, test_data[0].rect.bottom, resources[r].name);
7206 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7207 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7208 hr, test_rect_2.left, test_rect_2.top,
7209 test_rect_2.right, test_rect_2.bottom, resources[r].name);
7210 hr = IDirect3DSurface9_UnlockRect(surface);
7211 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7213 IDirect3DSurface9_Release(surface);
7215 if (texture)
7217 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7218 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7219 hr, resources[r].name);
7220 locked_rect.pBits = (BYTE *)0xdeadbeef;
7221 locked_rect.Pitch = 1;
7222 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7223 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7224 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7225 locked_rect.pBits, resources[r].name);
7226 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7227 locked_rect.Pitch, resources[r].name);
7228 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7229 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7230 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7231 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7233 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7234 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7235 hr, test_data[0].rect.left, test_data[0].rect.top,
7236 test_data[0].rect.right, test_data[0].rect.bottom, resources[r].name);
7237 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7238 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7239 hr, test_data[0].rect.left, test_data[0].rect.top,
7240 test_data[0].rect.right, test_data[0].rect.bottom, resources[r].name);
7241 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7242 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7243 hr, test_rect_2.left, test_rect_2.top,
7244 test_rect_2.right, test_rect_2.bottom, resources[r].name);
7245 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7246 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7248 IDirect3DTexture9_Release(texture);
7250 if (cube_texture)
7252 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7253 &locked_rect, NULL, 0);
7254 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7255 hr, resources[r].name);
7256 locked_rect.pBits = (BYTE *)0xdeadbeef;
7257 locked_rect.Pitch = 1;
7258 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7259 &locked_rect, NULL, 0);
7260 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7261 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7262 locked_rect.pBits, resources[r].name);
7263 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7264 locked_rect.Pitch, resources[r].name);
7265 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7266 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7267 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7268 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7270 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7271 &locked_rect, &test_data[0].rect, 0);
7272 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7273 hr, test_data[0].rect.left, test_data[0].rect.top,
7274 test_data[0].rect.right, test_data[0].rect.bottom, resources[r].name);
7275 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7276 &locked_rect, &test_data[0].rect, 0);
7277 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7278 hr, test_data[0].rect.left, test_data[0].rect.top,
7279 test_data[0].rect.right, test_data[0].rect.bottom, resources[r].name);
7280 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7281 &locked_rect, &test_rect_2, 0);
7282 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%d, %d]->[%d, %d], type %s.\n",
7283 hr, test_rect_2.left, test_rect_2.top,
7284 test_rect_2.right, test_rect_2.bottom, resources[r].name);
7285 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7286 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7288 IDirect3DCubeTexture9_Release(cube_texture);
7292 refcount = IDirect3DDevice9_Release(device);
7293 ok(!refcount, "Device has %u references left.\n", refcount);
7294 IDirect3D9_Release(d3d);
7295 DestroyWindow(window);
7298 static void test_private_data(void)
7300 ULONG refcount, expected_refcount;
7301 IDirect3DTexture9 *texture;
7302 IDirect3DSurface9 *surface, *surface2;
7303 IDirect3DDevice9 *device;
7304 IDirect3D9 *d3d;
7305 IUnknown *ptr;
7306 HWND window;
7307 HRESULT hr;
7308 DWORD size;
7309 DWORD data[4] = {1, 2, 3, 4};
7310 static const GUID d3d9_private_data_test_guid2 =
7312 0x2e5afac2,
7313 0x87b5,
7314 0x4c10,
7315 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7318 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7319 0, 0, 640, 480, 0, 0, 0, 0);
7320 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7321 ok(!!d3d, "Failed to create a D3D object.\n");
7322 if (!(device = create_device(d3d, window, NULL)))
7324 skip("Failed to create a D3D device, skipping tests.\n");
7325 IDirect3D9_Release(d3d);
7326 DestroyWindow(window);
7327 return;
7330 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7331 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7332 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7334 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7335 device, 0, D3DSPD_IUNKNOWN);
7336 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7337 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7338 device, 5, D3DSPD_IUNKNOWN);
7339 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7340 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7341 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7342 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7344 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7345 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7346 sizeof(device), D3DSPD_IUNKNOWN);
7347 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7348 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7349 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7350 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7351 size = sizeof(ptr);
7352 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7353 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7354 IUnknown_Release(ptr);
7355 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7356 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7358 refcount = get_refcount((IUnknown *)device);
7359 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7360 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7361 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7362 expected_refcount = refcount + 1;
7363 refcount = get_refcount((IUnknown *)device);
7364 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7365 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7366 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7367 expected_refcount = refcount - 1;
7368 refcount = get_refcount((IUnknown *)device);
7369 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7371 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7372 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7373 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7374 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7375 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7376 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7377 refcount = get_refcount((IUnknown *)device);
7378 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7380 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7381 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7382 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7383 size = 2 * sizeof(ptr);
7384 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7385 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7386 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7387 expected_refcount = refcount + 2;
7388 refcount = get_refcount((IUnknown *)device);
7389 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7390 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
7391 IUnknown_Release(ptr);
7392 expected_refcount--;
7394 ptr = (IUnknown *)0xdeadbeef;
7395 size = 1;
7396 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7397 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7398 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7399 size = 2 * sizeof(ptr);
7400 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
7401 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7402 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7403 refcount = get_refcount((IUnknown *)device);
7404 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7405 size = 1;
7406 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7407 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
7408 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
7409 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7410 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
7411 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7412 size = 0xdeadbabe;
7413 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
7414 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7415 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
7416 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
7417 /* GetPrivateData with size = NULL causes an access violation on Windows if the
7418 * requested data exists. */
7420 /* Destroying the surface frees the held reference. */
7421 IDirect3DSurface9_Release(surface);
7422 expected_refcount = refcount - 2;
7423 refcount = get_refcount((IUnknown *)device);
7424 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7426 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
7427 &texture, NULL);
7428 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7429 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7430 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
7431 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
7432 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
7434 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7435 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7437 memset(data, 0, sizeof(data));
7438 size = sizeof(data);
7439 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
7440 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7441 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
7442 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7443 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
7444 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
7446 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
7447 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7449 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
7450 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7451 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
7452 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
7454 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7455 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7457 IDirect3DSurface9_Release(surface2);
7458 IDirect3DSurface9_Release(surface);
7459 IDirect3DTexture9_Release(texture);
7461 refcount = IDirect3DDevice9_Release(device);
7462 ok(!refcount, "Device has %u references left.\n", refcount);
7463 IDirect3D9_Release(d3d);
7464 DestroyWindow(window);
7467 static void test_getdc(void)
7469 static const struct
7471 const char *name;
7472 D3DFORMAT format;
7473 BOOL getdc_supported;
7475 testdata[] =
7477 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, TRUE },
7478 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, TRUE },
7479 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, TRUE },
7480 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, TRUE },
7481 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, TRUE },
7482 {"D3DFMT_R8G8B8", D3DFMT_R8G8B8, TRUE },
7483 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, FALSE}, /* Untested, card on windows didn't support it. */
7484 {"D3DFMT_V8U8", D3DFMT_V8U8, FALSE},
7485 {"D3DFMT_Q8W8V8U8", D3DFMT_Q8W8V8U8, FALSE},
7486 {"D3DFMT_A8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
7487 {"D3DFMT_X8B8G8R8", D3DFMT_A8B8G8R8, FALSE},
7488 {"D3DFMT_R3G3B2", D3DFMT_R3G3B2, FALSE},
7489 {"D3DFMT_P8", D3DFMT_P8, FALSE},
7490 {"D3DFMT_L8", D3DFMT_L8, FALSE},
7491 {"D3DFMT_A8L8", D3DFMT_A8L8, FALSE},
7492 {"D3DFMT_DXT1", D3DFMT_DXT1, FALSE},
7493 {"D3DFMT_DXT2", D3DFMT_DXT2, FALSE},
7494 {"D3DFMT_DXT3", D3DFMT_DXT3, FALSE},
7495 {"D3DFMT_DXT4", D3DFMT_DXT4, FALSE},
7496 {"D3DFMT_DXT5", D3DFMT_DXT5, FALSE},
7498 IDirect3DTexture9 *texture;
7499 IDirect3DSurface9 *surface;
7500 IDirect3DDevice9 *device;
7501 IDirect3D9 *d3d;
7502 unsigned int i;
7503 ULONG refcount;
7504 HWND window;
7505 HRESULT hr;
7506 HDC dc;
7508 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7509 0, 0, 640, 480, 0, 0, 0, 0);
7510 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7511 ok(!!d3d, "Failed to create a D3D object.\n");
7512 if (!(device = create_device(d3d, window, NULL)))
7514 skip("Failed to create a D3D device, skipping tests.\n");
7515 IDirect3D9_Release(d3d);
7516 DestroyWindow(window);
7517 return;
7520 for (i = 0; i < (sizeof(testdata) / sizeof(*testdata)); ++i)
7522 texture = NULL;
7523 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7524 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
7525 if (FAILED(hr))
7527 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
7528 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
7529 if (FAILED(hr))
7531 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
7532 continue;
7534 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7535 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7538 dc = (void *)0x1234;
7539 hr = IDirect3DSurface9_GetDC(surface, &dc);
7540 if (testdata[i].getdc_supported)
7541 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7542 else
7543 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
7545 if (SUCCEEDED(hr))
7547 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
7548 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
7550 else
7552 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
7555 IDirect3DSurface9_Release(surface);
7556 if (texture)
7557 IDirect3DTexture9_Release(texture);
7560 refcount = IDirect3DDevice9_Release(device);
7561 ok(!refcount, "Device has %u references left.\n", refcount);
7562 IDirect3D9_Release(d3d);
7563 DestroyWindow(window);
7566 static void test_surface_dimensions(void)
7568 IDirect3DSurface9 *surface;
7569 IDirect3DDevice9 *device;
7570 IDirect3D9 *d3d;
7571 ULONG refcount;
7572 HWND window;
7573 HRESULT hr;
7575 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7576 0, 0, 640, 480, 0, 0, 0, 0);
7577 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7578 ok(!!d3d, "Failed to create a D3D object.\n");
7579 if (!(device = create_device(d3d, window, NULL)))
7581 skip("Failed to create a D3D device, skipping tests.\n");
7582 IDirect3D9_Release(d3d);
7583 DestroyWindow(window);
7584 return;
7587 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
7588 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7589 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7590 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
7591 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7592 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7594 refcount = IDirect3DDevice9_Release(device);
7595 ok(!refcount, "Device has %u references left.\n", refcount);
7596 IDirect3D9_Release(d3d);
7597 DestroyWindow(window);
7600 static void test_surface_format_null(void)
7602 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
7603 IDirect3DTexture9 *texture;
7604 IDirect3DSurface9 *surface;
7605 IDirect3DSurface9 *rt, *ds;
7606 D3DLOCKED_RECT locked_rect;
7607 IDirect3DDevice9 *device;
7608 D3DSURFACE_DESC desc;
7609 IDirect3D9 *d3d;
7610 ULONG refcount;
7611 HWND window;
7612 HRESULT hr;
7614 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7615 ok(!!d3d, "Failed to create a D3D object.\n");
7617 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7618 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
7619 if (hr != D3D_OK)
7621 skip("No D3DFMT_NULL support, skipping test.\n");
7622 IDirect3D9_Release(d3d);
7623 return;
7626 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7627 0, 0, 640, 480, 0, 0, 0, 0);
7628 if (!(device = create_device(d3d, window, NULL)))
7630 skip("Failed to create a D3D device, skipping tests.\n");
7631 IDirect3D9_Release(d3d);
7632 DestroyWindow(window);
7633 return;
7636 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7637 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
7638 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
7640 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7641 D3DFMT_NULL, D3DFMT_D24S8);
7642 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
7644 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
7645 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
7646 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
7648 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
7649 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
7651 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
7652 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
7654 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
7655 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
7657 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
7658 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
7660 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
7661 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
7663 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
7664 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
7666 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
7667 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
7669 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
7670 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
7672 IDirect3DSurface9_Release(rt);
7673 IDirect3DSurface9_Release(ds);
7675 hr = IDirect3DSurface9_GetDesc(surface, &desc);
7676 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
7677 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
7678 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
7680 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7681 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7682 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
7683 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
7685 hr = IDirect3DSurface9_UnlockRect(surface);
7686 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7688 IDirect3DSurface9_Release(surface);
7690 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
7691 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
7692 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7693 IDirect3DTexture9_Release(texture);
7695 refcount = IDirect3DDevice9_Release(device);
7696 ok(!refcount, "Device has %u references left.\n", refcount);
7697 IDirect3D9_Release(d3d);
7698 DestroyWindow(window);
7701 static void test_surface_double_unlock(void)
7703 static const D3DPOOL pools[] =
7705 D3DPOOL_DEFAULT,
7706 D3DPOOL_SCRATCH,
7707 D3DPOOL_SYSTEMMEM,
7709 IDirect3DSurface9 *surface;
7710 IDirect3DDevice9 *device;
7711 D3DLOCKED_RECT lr;
7712 IDirect3D9 *d3d;
7713 unsigned int i;
7714 ULONG refcount;
7715 HWND window;
7716 HRESULT hr;
7718 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7719 0, 0, 640, 480, 0, 0, 0, 0);
7720 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7721 ok(!!d3d, "Failed to create a D3D object.\n");
7722 if (!(device = create_device(d3d, window, NULL)))
7724 skip("Failed to create a D3D device, skipping tests.\n");
7725 IDirect3D9_Release(d3d);
7726 DestroyWindow(window);
7727 return;
7730 for (i = 0; i < (sizeof(pools) / sizeof(*pools)); ++i)
7732 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
7733 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
7734 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
7736 hr = IDirect3DSurface9_UnlockRect(surface);
7737 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
7738 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7739 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
7740 hr = IDirect3DSurface9_UnlockRect(surface);
7741 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
7742 hr = IDirect3DSurface9_UnlockRect(surface);
7743 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
7745 IDirect3DSurface9_Release(surface);
7748 refcount = IDirect3DDevice9_Release(device);
7749 ok(!refcount, "Device has %u references left.\n", refcount);
7750 IDirect3D9_Release(d3d);
7751 DestroyWindow(window);
7754 static void test_surface_blocks(void)
7756 static const struct
7758 D3DFORMAT fmt;
7759 const char *name;
7760 unsigned int block_width;
7761 unsigned int block_height;
7762 BOOL broken;
7763 BOOL create_size_checked, core_fmt;
7765 formats[] =
7767 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
7768 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
7769 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
7770 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
7771 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
7772 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
7773 * which doesn't match the format spec. On newer Nvidia cards
7774 * they have the correct 4x4 block size */
7775 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
7776 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
7777 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
7778 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
7780 static const struct
7782 D3DPOOL pool;
7783 const char *name;
7784 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
7785 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
7786 BOOL success;
7788 pools[] =
7790 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
7791 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
7792 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
7793 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
7795 static struct
7797 D3DRESOURCETYPE rtype;
7798 const char *type_name;
7799 D3DPOOL pool;
7800 const char *pool_name;
7801 BOOL need_driver_support, need_runtime_support;
7803 create_tests[] =
7805 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7806 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
7807 /* Managed offscreen plain surfaces are not supported */
7808 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7810 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7811 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
7812 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
7813 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7815 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
7816 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
7817 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
7818 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
7820 IDirect3DTexture9 *texture;
7821 IDirect3DCubeTexture9 *cube_texture;
7822 IDirect3DSurface9 *surface;
7823 D3DLOCKED_RECT locked_rect;
7824 IDirect3DDevice9 *device;
7825 unsigned int i, j, k, w, h;
7826 BOOL surface_only;
7827 IDirect3D9 *d3d;
7828 ULONG refcount;
7829 HWND window;
7830 HRESULT hr;
7831 RECT rect;
7832 BOOL tex_pow2, cube_pow2;
7833 D3DCAPS9 caps;
7834 static const RECT invalid[] =
7836 {60, 60, 60, 68}, /* 0 height */
7837 {60, 60, 68, 60}, /* 0 width */
7838 {68, 60, 60, 68}, /* left > right */
7839 {60, 68, 68, 60}, /* top > bottom */
7840 {-8, 60, 0, 68}, /* left < surface */
7841 {60, -8, 68, 0}, /* top < surface */
7842 {-16, 60, -8, 68}, /* right < surface */
7843 {60, -16, 68, -8}, /* bottom < surface */
7844 {60, 60, 136, 68}, /* right > surface */
7845 {60, 60, 68, 136}, /* bottom > surface */
7846 {136, 60, 144, 68}, /* left > surface */
7847 {60, 136, 68, 144}, /* top > surface */
7850 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7851 0, 0, 640, 480, 0, 0, 0, 0);
7852 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7853 ok(!!d3d, "Failed to create a D3D object.\n");
7854 if (!(device = create_device(d3d, window, NULL)))
7856 skip("Failed to create a D3D device, skipping tests.\n");
7857 IDirect3D9_Release(d3d);
7858 DestroyWindow(window);
7859 return;
7862 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7863 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
7864 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
7865 if (tex_pow2)
7866 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
7867 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
7869 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
7871 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
7873 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7874 0, D3DRTYPE_TEXTURE, formats[i].fmt);
7875 tex_support = SUCCEEDED(hr);
7876 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7877 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
7878 cube_support = SUCCEEDED(hr);
7879 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7880 0, D3DRTYPE_SURFACE, formats[i].fmt);
7881 surface_support = SUCCEEDED(hr);
7883 /* Scratch pool in general allows texture creation even if the driver does
7884 * not support the format. If the format is an extension format that is not
7885 * known to the runtime, like ATI2N, some driver support is required for
7886 * this to work.
7888 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
7889 * about ATI2N. I cannot check this because all my Vista+ machines support
7890 * ATI2N in hardware, but none of my WinXP machines do. */
7891 format_known = tex_support || cube_support || surface_support;
7893 for (w = 1; w <= 8; w++)
7895 for (h = 1; h <= 8; h++)
7897 BOOL block_aligned = TRUE;
7898 BOOL size_is_pow2;
7900 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
7901 block_aligned = FALSE;
7903 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
7905 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
7907 BOOL support, pow2;
7908 HRESULT expect_hr;
7909 BOOL may_succeed = FALSE;
7910 IUnknown **check_null;
7912 if (!formats[i].core_fmt)
7914 /* AMD warns against creating ATI2N textures smaller than
7915 * the block size because the runtime cannot calculate the
7916 * correct texture size. Generalize this for all extension
7917 * formats. */
7918 if (w < formats[i].block_width || h < formats[i].block_height)
7919 continue;
7922 texture = (IDirect3DTexture9 *)0xdeadbeef;
7923 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
7924 surface = (IDirect3DSurface9 *)0xdeadbeef;
7926 switch (create_tests[j].rtype)
7928 case D3DRTYPE_TEXTURE:
7929 check_null = (IUnknown **)&texture;
7930 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
7931 formats[i].fmt, create_tests[j].pool, &texture, NULL);
7932 support = tex_support;
7933 pow2 = tex_pow2;
7934 break;
7936 case D3DRTYPE_CUBETEXTURE:
7937 if (w != h)
7938 continue;
7939 check_null = (IUnknown **)&cube_texture;
7940 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
7941 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
7942 support = cube_support;
7943 pow2 = cube_pow2;
7944 break;
7946 case D3DRTYPE_SURFACE:
7947 check_null = (IUnknown **)&surface;
7948 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
7949 formats[i].fmt, create_tests[j].pool, &surface, NULL);
7950 support = surface_support;
7951 pow2 = FALSE;
7952 break;
7954 default:
7955 check_null = NULL;
7956 pow2 = FALSE;
7957 support = FALSE;
7958 break;
7961 if (create_tests[j].need_driver_support && !support)
7962 expect_hr = D3DERR_INVALIDCALL;
7963 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
7964 expect_hr = D3DERR_INVALIDCALL;
7965 else if (formats[i].create_size_checked && !block_aligned)
7966 expect_hr = D3DERR_INVALIDCALL;
7967 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
7968 expect_hr = D3DERR_INVALIDCALL;
7969 else
7970 expect_hr = D3D_OK;
7972 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
7973 * does not support it. Accept scratch creation of extension formats on
7974 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
7975 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
7976 * support it. */
7977 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
7978 may_succeed = TRUE;
7980 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
7981 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
7982 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
7983 if (FAILED(hr))
7984 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
7985 else
7986 IUnknown_Release(*check_null);
7991 surface_only = FALSE;
7992 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7993 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
7994 dynamic_tex_support = SUCCEEDED(hr);
7995 if (!dynamic_tex_support)
7997 if (!surface_support)
7999 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8000 continue;
8002 surface_only = TRUE;
8005 for (j = 0; j < (sizeof(pools) / sizeof(*pools)); ++j)
8007 switch (pools[j].pool)
8009 case D3DPOOL_SYSTEMMEM:
8010 case D3DPOOL_MANAGED:
8011 if (surface_only)
8012 continue;
8013 /* Fall through */
8014 case D3DPOOL_DEFAULT:
8015 if (surface_only)
8017 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8018 formats[i].fmt, pools[j].pool, &surface, NULL);
8019 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8021 else
8023 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8024 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8025 formats[i].fmt, pools[j].pool, &texture, NULL);
8026 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8027 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8028 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8029 IDirect3DTexture9_Release(texture);
8031 break;
8033 case D3DPOOL_SCRATCH:
8034 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8035 formats[i].fmt, pools[j].pool, &surface, NULL);
8036 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8037 break;
8039 default:
8040 break;
8043 if (formats[i].block_width > 1)
8045 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8046 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8047 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8048 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8049 SUCCEEDED(hr) ? "succeeded" : "failed",
8050 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8051 if (SUCCEEDED(hr))
8053 hr = IDirect3DSurface9_UnlockRect(surface);
8054 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8057 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8058 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8059 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8060 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8061 SUCCEEDED(hr) ? "succeeded" : "failed",
8062 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8063 if (SUCCEEDED(hr))
8065 hr = IDirect3DSurface9_UnlockRect(surface);
8066 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8070 if (formats[i].block_height > 1)
8072 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
8073 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8074 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8075 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8076 SUCCEEDED(hr) ? "succeeded" : "failed",
8077 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8078 if (SUCCEEDED(hr))
8080 hr = IDirect3DSurface9_UnlockRect(surface);
8081 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8084 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
8085 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8086 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8087 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8088 SUCCEEDED(hr) ? "succeeded" : "failed",
8089 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8090 if (SUCCEEDED(hr))
8092 hr = IDirect3DSurface9_UnlockRect(surface);
8093 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8097 for (k = 0; k < sizeof(invalid) / sizeof(*invalid); ++k)
8099 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
8100 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
8101 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
8102 formats[i].name, pools[j].name, k);
8103 if (SUCCEEDED(hr))
8105 hr = IDirect3DSurface9_UnlockRect(surface);
8106 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8110 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8111 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8112 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
8113 hr = IDirect3DSurface9_UnlockRect(surface);
8114 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8116 IDirect3DSurface9_Release(surface);
8119 if (!dynamic_tex_support)
8121 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
8122 continue;
8125 if (formats[i].block_width == 1 && formats[i].block_height == 1)
8126 continue;
8127 if (!formats[i].core_fmt)
8128 continue;
8130 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
8131 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
8132 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
8134 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
8135 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8136 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8137 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8139 rect.left = 0;
8140 rect.top = 0;
8141 rect.right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
8142 rect.bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
8143 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8144 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8145 hr = IDirect3DTexture9_UnlockRect(texture, 1);
8146 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
8148 rect.right = formats[i].block_width;
8149 rect.bottom = formats[i].block_height;
8150 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
8151 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8152 if (SUCCEEDED(hr))
8153 IDirect3DTexture9_UnlockRect(texture, 1);
8155 IDirect3DTexture9_Release(texture);
8158 refcount = IDirect3DDevice9_Release(device);
8159 ok(!refcount, "Device has %u references left.\n", refcount);
8160 IDirect3D9_Release(d3d);
8161 DestroyWindow(window);
8164 static void test_set_palette(void)
8166 IDirect3DDevice9 *device;
8167 IDirect3D9 *d3d9;
8168 UINT refcount;
8169 HWND window;
8170 HRESULT hr;
8171 PALETTEENTRY pal[256];
8172 unsigned int i;
8173 D3DCAPS9 caps;
8175 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8176 0, 0, 640, 480, 0, 0, 0, 0);
8177 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8178 ok(!!d3d9, "Failed to create a D3D object.\n");
8179 if (!(device = create_device(d3d9, window, NULL)))
8181 skip("Failed to create a D3D device, skipping tests.\n");
8182 DestroyWindow(window);
8183 return;
8186 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8188 pal[i].peRed = i;
8189 pal[i].peGreen = i;
8190 pal[i].peBlue = i;
8191 pal[i].peFlags = 0xff;
8193 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8194 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8196 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8197 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
8198 for (i = 0; i < sizeof(pal) / sizeof(*pal); i++)
8200 pal[i].peRed = i;
8201 pal[i].peGreen = i;
8202 pal[i].peBlue = i;
8203 pal[i].peFlags = i;
8205 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
8207 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8208 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
8210 else
8212 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
8213 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
8216 refcount = IDirect3DDevice9_Release(device);
8217 ok(!refcount, "Device has %u references left.\n", refcount);
8218 IDirect3D9_Release(d3d9);
8219 DestroyWindow(window);
8222 static void test_swvp_buffer(void)
8224 IDirect3DDevice9 *device;
8225 IDirect3D9 *d3d9;
8226 UINT refcount;
8227 HWND window;
8228 HRESULT hr;
8229 unsigned int i;
8230 IDirect3DVertexBuffer9 *buffer;
8231 static const unsigned int bufsize = 1024;
8232 D3DVERTEXBUFFER_DESC desc;
8233 struct device_desc device_desc;
8234 struct
8236 float x, y, z;
8237 } *ptr, *ptr2;
8239 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8240 0, 0, 640, 480, 0, 0, 0, 0);
8241 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8242 ok(!!d3d9, "Failed to create a D3D object.\n");
8244 device_desc.device_window = window;
8245 device_desc.width = 640;
8246 device_desc.height = 480;
8247 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
8248 if (!(device = create_device(d3d9, window, &device_desc)))
8250 skip("Failed to create a D3D device, skipping tests.\n");
8251 DestroyWindow(window);
8252 IDirect3D9_Release(d3d9);
8253 return;
8256 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
8257 D3DPOOL_DEFAULT, &buffer, NULL);
8258 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8259 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8260 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8261 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
8262 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
8263 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
8265 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8266 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8267 for (i = 0; i < bufsize; i++)
8269 ptr[i].x = i * 1.0f;
8270 ptr[i].y = i * 2.0f;
8271 ptr[i].z = i * 3.0f;
8273 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8274 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8276 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8277 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8278 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8279 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8280 hr = IDirect3DDevice9_BeginScene(device);
8281 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8282 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8283 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8284 hr = IDirect3DDevice9_EndScene(device);
8285 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8287 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8288 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8289 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
8290 for (i = 0; i < bufsize; i++)
8292 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8294 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
8295 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8296 break;
8299 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8300 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8302 IDirect3DVertexBuffer9_Release(buffer);
8303 refcount = IDirect3DDevice9_Release(device);
8304 ok(!refcount, "Device has %u references left.\n", refcount);
8305 IDirect3D9_Release(d3d9);
8306 DestroyWindow(window);
8309 static void test_managed_buffer(void)
8311 static const unsigned int vertex_count = 1024;
8312 IDirect3DVertexBuffer9 *buffer;
8313 D3DVERTEXBUFFER_DESC desc;
8314 IDirect3DDevice9 *device;
8315 struct vec3 *ptr, *ptr2;
8316 IDirect3D9 *d3d9;
8317 unsigned int i;
8318 UINT refcount;
8319 HWND window;
8320 HRESULT hr;
8322 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8323 0, 0, 640, 480, 0, 0, 0, 0);
8324 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8325 ok(!!d3d9, "Failed to create a D3D object.\n");
8326 if (!(device = create_device(d3d9, window, NULL)))
8328 skip("Failed to create a D3D device, skipping tests.\n");
8329 IDirect3D9_Release(d3d9);
8330 DestroyWindow(window);
8331 return;
8334 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
8335 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
8336 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
8337 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
8338 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
8339 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
8340 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
8342 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
8343 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8344 for (i = 0; i < vertex_count; ++i)
8346 ptr[i].x = i * 1.0f;
8347 ptr[i].y = i * 2.0f;
8348 ptr[i].z = i * 3.0f;
8350 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8351 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8353 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8354 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
8355 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
8356 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
8357 hr = IDirect3DDevice9_BeginScene(device);
8358 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
8359 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
8360 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
8361 hr = IDirect3DDevice9_EndScene(device);
8362 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
8364 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
8365 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
8366 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
8367 for (i = 0; i < vertex_count; ++i)
8369 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
8371 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
8372 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
8373 break;
8376 hr = IDirect3DVertexBuffer9_Unlock(buffer);
8377 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
8379 IDirect3DVertexBuffer9_Release(buffer);
8380 refcount = IDirect3DDevice9_Release(device);
8381 ok(!refcount, "Device has %u references left.\n", refcount);
8382 IDirect3D9_Release(d3d9);
8383 DestroyWindow(window);
8386 static void test_npot_textures(void)
8388 IDirect3DDevice9 *device = NULL;
8389 IDirect3D9 *d3d9;
8390 ULONG refcount;
8391 HWND window = NULL;
8392 HRESULT hr;
8393 D3DCAPS9 caps;
8394 IDirect3DTexture9 *texture;
8395 IDirect3DCubeTexture9 *cube_texture;
8396 IDirect3DVolumeTexture9 *volume_texture;
8397 struct
8399 D3DPOOL pool;
8400 const char *pool_name;
8401 HRESULT hr;
8403 pools[] =
8405 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
8406 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
8407 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
8408 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
8410 unsigned int i, levels;
8411 BOOL tex_pow2, cube_pow2, vol_pow2;
8413 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8414 0, 0, 640, 480, 0, 0, 0, 0);
8415 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8416 ok(!!d3d9, "Failed to create a D3D object.\n");
8417 if (!(device = create_device(d3d9, window, NULL)))
8419 skip("Failed to create a D3D device, skipping tests.\n");
8420 goto done;
8423 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8424 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8425 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8426 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8427 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8428 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
8429 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
8431 for (i = 0; i < sizeof(pools) / sizeof(*pools); i++)
8433 for (levels = 0; levels <= 2; levels++)
8435 HRESULT expected;
8437 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
8438 pools[i].pool, &texture, NULL);
8439 if (!tex_pow2)
8441 expected = D3D_OK;
8443 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
8445 if (levels == 1)
8446 expected = D3D_OK;
8447 else
8448 expected = pools[i].hr;
8450 else
8452 expected = pools[i].hr;
8454 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
8455 pools[i].pool_name, levels, hr, expected);
8457 if (SUCCEEDED(hr))
8458 IDirect3DTexture9_Release(texture);
8461 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8462 &cube_texture, NULL);
8463 if (tex_pow2)
8465 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8466 pools[i].pool_name, hr, pools[i].hr);
8468 else
8470 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
8471 pools[i].pool_name, hr, D3D_OK);
8474 if (SUCCEEDED(hr))
8475 IDirect3DCubeTexture9_Release(cube_texture);
8477 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
8478 &volume_texture, NULL);
8479 if (tex_pow2)
8481 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8482 pools[i].pool_name, hr, pools[i].hr);
8484 else
8486 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
8487 pools[i].pool_name, hr, D3D_OK);
8490 if (SUCCEEDED(hr))
8491 IDirect3DVolumeTexture9_Release(volume_texture);
8494 done:
8495 if (device)
8497 refcount = IDirect3DDevice9_Release(device);
8498 ok(!refcount, "Device has %u references left.\n", refcount);
8500 IDirect3D9_Release(d3d9);
8501 DestroyWindow(window);
8505 static void test_vidmem_accounting(void)
8507 IDirect3DDevice9 *device;
8508 IDirect3D9 *d3d9;
8509 ULONG refcount;
8510 HWND window;
8511 HRESULT hr = D3D_OK;
8512 IDirect3DTexture9 *textures[20];
8513 unsigned int i;
8514 UINT vidmem_start, vidmem_end, diff;
8516 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8517 0, 0, 640, 480, 0, 0, 0, 0);
8518 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8519 ok(!!d3d9, "Failed to create a D3D object.\n");
8520 if (!(device = create_device(d3d9, window, NULL)))
8522 skip("Failed to create a D3D device, skipping tests.\n");
8523 IDirect3D9_Release(d3d9);
8524 DestroyWindow(window);
8525 return;
8528 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
8529 memset(textures, 0, sizeof(textures));
8530 for (i = 0; i < sizeof(textures) / sizeof(*textures) && SUCCEEDED(hr); i++)
8532 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
8533 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
8534 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
8535 * E_FAIL is returned on address space or system memory exhaustion */
8536 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
8537 "Failed to create texture, hr %#x.\n", hr);
8539 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
8541 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
8542 diff = vidmem_start - vidmem_end;
8543 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
8544 2 * i, diff / 1024 / 1024);
8546 for (i = 0; i < sizeof(textures) / sizeof(*textures); i++)
8548 if (textures[i])
8549 IDirect3DTexture9_Release(textures[i]);
8552 refcount = IDirect3DDevice9_Release(device);
8553 ok(!refcount, "Device has %u references left.\n", refcount);
8554 IDirect3D9_Release(d3d9);
8555 DestroyWindow(window);
8558 static void test_volume_locking(void)
8560 IDirect3DDevice9 *device;
8561 IDirect3D9 *d3d9;
8562 HWND window;
8563 HRESULT hr;
8564 IDirect3DVolumeTexture9 *texture;
8565 unsigned int i;
8566 D3DLOCKED_BOX locked_box;
8567 ULONG refcount;
8568 D3DCAPS9 caps;
8569 static const struct
8571 D3DPOOL pool;
8572 DWORD usage;
8573 HRESULT create_hr, lock_hr;
8575 tests[] =
8577 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
8578 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
8579 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
8580 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
8581 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
8582 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
8583 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
8584 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
8587 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8588 0, 0, 640, 480, 0, 0, 0, 0);
8589 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8590 ok(!!d3d9, "Failed to create a D3D object.\n");
8591 if (!(device = create_device(d3d9, window, NULL)))
8593 skip("Failed to create a D3D device, skipping tests.\n");
8594 IDirect3D9_Release(d3d9);
8595 DestroyWindow(window);
8596 return;
8599 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8600 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8601 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
8603 skip("Volume textures not supported, skipping test.\n");
8604 goto out;
8607 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8609 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
8610 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
8611 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
8612 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
8613 if (FAILED(hr))
8614 continue;
8616 locked_box.pBits = (void *)0xdeadbeef;
8617 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
8618 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
8619 if (SUCCEEDED(hr))
8621 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
8622 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8624 else
8626 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
8628 IDirect3DVolumeTexture9_Release(texture);
8631 out:
8632 refcount = IDirect3DDevice9_Release(device);
8633 ok(!refcount, "Device has %u references left.\n", refcount);
8634 IDirect3D9_Release(d3d9);
8635 DestroyWindow(window);
8638 static void test_update_volumetexture(void)
8640 IDirect3DDevice9 *device;
8641 IDirect3D9 *d3d9;
8642 HWND window;
8643 HRESULT hr;
8644 IDirect3DVolumeTexture9 *src, *dst;
8645 unsigned int i;
8646 D3DLOCKED_BOX locked_box;
8647 ULONG refcount;
8648 D3DCAPS9 caps;
8649 static const struct
8651 D3DPOOL src_pool, dst_pool;
8652 HRESULT hr;
8654 tests[] =
8656 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
8657 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
8658 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
8659 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
8661 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8662 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8663 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8664 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
8666 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8667 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8668 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8669 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
8671 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8672 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8673 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8674 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
8676 static const struct
8678 UINT src_size, dst_size;
8679 UINT src_lvl, dst_lvl;
8680 D3DFORMAT src_fmt, dst_fmt;
8682 tests2[] =
8684 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8685 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8686 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8687 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8688 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
8689 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
8690 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
8691 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
8694 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8695 0, 0, 640, 480, 0, 0, 0, 0);
8696 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8697 ok(!!d3d9, "Failed to create a D3D object.\n");
8698 if (!(device = create_device(d3d9, window, NULL)))
8700 skip("Failed to create a D3D device, skipping tests.\n");
8701 IDirect3D9_Release(d3d9);
8702 DestroyWindow(window);
8703 return;
8706 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8707 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8708 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
8710 skip("Volume textures not supported, skipping test.\n");
8711 goto out;
8714 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++)
8716 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
8717 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
8719 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
8720 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
8721 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8722 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
8723 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
8724 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8726 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
8727 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
8728 *((DWORD *)locked_box.pBits) = 0x11223344;
8729 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
8730 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8732 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
8733 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
8734 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
8736 if (SUCCEEDED(hr))
8738 DWORD content = *((DWORD *)locked_box.pBits);
8739 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
8740 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
8741 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
8742 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
8743 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
8745 IDirect3DVolumeTexture9_Release(src);
8746 IDirect3DVolumeTexture9_Release(dst);
8749 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
8751 skip("Mipmapped volume maps not supported.\n");
8752 goto out;
8755 for (i = 0; i < sizeof(tests2) / sizeof(*tests2); i++)
8757 hr = IDirect3DDevice9_CreateVolumeTexture(device,
8758 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
8759 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
8760 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
8761 hr = IDirect3DDevice9_CreateVolumeTexture(device,
8762 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
8763 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
8764 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
8766 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
8767 if (FAILED(hr))
8768 todo_wine ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
8769 else
8770 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
8772 IDirect3DVolumeTexture9_Release(src);
8773 IDirect3DVolumeTexture9_Release(dst);
8776 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
8777 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
8778 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
8779 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
8780 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
8782 * I'm not adding tests for this behavior until an application needs it. */
8784 out:
8785 refcount = IDirect3DDevice9_Release(device);
8786 ok(!refcount, "Device has %u references left.\n", refcount);
8787 IDirect3D9_Release(d3d9);
8788 DestroyWindow(window);
8791 static void test_create_rt_ds_fail(void)
8793 IDirect3DDevice9 *device;
8794 HWND window;
8795 HRESULT hr;
8796 ULONG refcount;
8797 IDirect3D9 *d3d9;
8798 IDirect3DSurface9 *surface;
8800 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8801 0, 0, 640, 480, 0, 0, 0, 0);
8802 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8803 ok(!!d3d9, "Failed to create a D3D object.\n");
8804 if (!(device = create_device(d3d9, window, NULL)))
8806 skip("Failed to create a D3D device, skipping tests.\n");
8807 IDirect3D9_Release(d3d9);
8808 DestroyWindow(window);
8809 return;
8812 /* Output pointer == NULL segfaults on Windows. */
8814 surface = (IDirect3DSurface9 *)0xdeadbeef;
8815 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
8816 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
8817 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
8818 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
8819 if (SUCCEEDED(hr))
8820 IDirect3DSurface9_Release(surface);
8822 surface = (IDirect3DSurface9 *)0xdeadbeef;
8823 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
8824 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8825 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
8826 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
8827 if (SUCCEEDED(hr))
8828 IDirect3DSurface9_Release(surface);
8830 refcount = IDirect3DDevice9_Release(device);
8831 ok(!refcount, "Device has %u references left.\n", refcount);
8832 IDirect3D9_Release(d3d9);
8833 DestroyWindow(window);
8836 static void test_volume_blocks(void)
8838 IDirect3DDevice9 *device;
8839 IDirect3D9 *d3d9;
8840 UINT refcount;
8841 HWND window;
8842 HRESULT hr;
8843 D3DCAPS9 caps;
8844 IDirect3DVolumeTexture9 *texture;
8845 unsigned int w, h, d, i, j;
8846 static const struct
8848 D3DFORMAT fmt;
8849 const char *name;
8850 unsigned int block_width;
8851 unsigned int block_height;
8852 unsigned int block_depth;
8853 unsigned int block_size;
8854 unsigned int broken;
8855 BOOL create_size_checked, core_fmt;
8857 formats[] =
8859 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
8860 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
8861 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
8862 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
8863 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
8864 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
8865 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
8866 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
8867 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
8868 * which doesn't match the format spec. On newer Nvidia cards
8869 * it has the correct 4x4 block size.
8870 * ATI1N volume textures are only supported by AMD GPUs right
8871 * now and locking offsets seem just wrong. */
8872 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
8873 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
8874 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
8875 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
8877 static const struct
8879 D3DPOOL pool;
8880 const char *name;
8881 BOOL need_driver_support, need_runtime_support;
8883 create_tests[] =
8885 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8886 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8887 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
8888 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8890 static const struct
8892 unsigned int x, y, z, x2, y2, z2;
8894 offset_tests[] =
8896 {0, 0, 0, 8, 8, 8},
8897 {0, 0, 3, 8, 8, 8},
8898 {0, 4, 0, 8, 8, 8},
8899 {0, 4, 3, 8, 8, 8},
8900 {4, 0, 0, 8, 8, 8},
8901 {4, 0, 3, 8, 8, 8},
8902 {4, 4, 0, 8, 8, 8},
8903 {4, 4, 3, 8, 8, 8},
8905 D3DBOX box;
8906 D3DLOCKED_BOX locked_box;
8907 BYTE *base;
8908 INT expected_row_pitch, expected_slice_pitch;
8909 BOOL support;
8910 BOOL pow2;
8911 unsigned int offset, expected_offset;
8913 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
8914 0, 0, 640, 480, 0, 0, 0, 0);
8915 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
8916 ok(!!d3d9, "Failed to create a D3D object.\n");
8917 if (!(device = create_device(d3d9, window, NULL)))
8919 skip("Failed to create a D3D device, skipping tests.\n");
8920 IDirect3D9_Release(d3d9);
8921 DestroyWindow(window);
8922 return;
8924 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8925 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8926 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
8928 for (i = 0; i < sizeof(formats) / sizeof(*formats); i++)
8930 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8931 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
8932 support = SUCCEEDED(hr);
8934 /* Test creation restrictions */
8935 for (w = 1; w <= 8; w++)
8937 for (h = 1; h <= 8; h++)
8939 for (d = 1; d <= 8; d++)
8941 HRESULT expect_hr;
8942 BOOL size_is_pow2;
8943 BOOL block_aligned = TRUE;
8945 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8946 block_aligned = FALSE;
8948 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
8950 for (j = 0; j < sizeof(create_tests) / sizeof(*create_tests); j++)
8952 BOOL may_succeed = FALSE;
8954 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
8955 expect_hr = D3DERR_INVALIDCALL;
8956 else if (formats[i].create_size_checked && !block_aligned)
8957 expect_hr = D3DERR_INVALIDCALL;
8958 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8959 expect_hr = D3DERR_INVALIDCALL;
8960 else if (create_tests[j].need_driver_support && !support)
8961 expect_hr = D3DERR_INVALIDCALL;
8962 else
8963 expect_hr = D3D_OK;
8965 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
8966 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
8967 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8969 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8970 * does not support it. Accept scratch creation of extension formats on
8971 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8972 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8973 * support it. */
8974 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
8975 may_succeed = TRUE;
8977 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8978 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
8979 hr, formats[i].name, create_tests[j].name, w, h, d);
8981 if (FAILED(hr))
8982 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
8983 else
8984 IDirect3DVolumeTexture9_Release(texture);
8990 if (!support && !formats[i].core_fmt)
8991 continue;
8993 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
8994 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
8995 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
8997 /* Test lockrect offset */
8998 for (j = 0; j < sizeof(offset_tests) / sizeof(*offset_tests); j++)
9000 unsigned int bytes_per_pixel;
9001 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9003 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9004 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9006 base = locked_box.pBits;
9007 if (formats[i].broken == 1)
9009 expected_row_pitch = bytes_per_pixel * 24;
9011 else if (formats[i].broken == 2)
9013 expected_row_pitch = 24;
9015 else
9017 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9018 * formats[i].block_size;
9020 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9021 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9023 if (formats[i].broken)
9025 expected_slice_pitch = expected_row_pitch * 8;
9027 else
9029 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9030 * expected_row_pitch;
9032 ok(locked_box.SlicePitch == expected_slice_pitch,
9033 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9034 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9036 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9037 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9039 box.Left = offset_tests[j].x;
9040 box.Top = offset_tests[j].y;
9041 box.Front = offset_tests[j].z;
9042 box.Right = offset_tests[j].x2;
9043 box.Bottom = offset_tests[j].y2;
9044 box.Back = offset_tests[j].z2;
9045 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9046 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9048 offset = (BYTE *)locked_box.pBits - base;
9049 if (formats[i].broken == 1)
9051 expected_offset = box.Front * expected_slice_pitch
9052 + box.Top * expected_row_pitch
9053 + box.Left * bytes_per_pixel;
9055 else if (formats[i].broken == 2)
9057 expected_offset = box.Front * expected_slice_pitch
9058 + box.Top * expected_row_pitch
9059 + box.Left;
9061 else
9063 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9064 + (box.Top / formats[i].block_height) * expected_row_pitch
9065 + (box.Left / formats[i].block_width) * formats[i].block_size;
9067 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9068 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9070 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9071 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9074 /* Test partial block locks */
9075 box.Front = 0;
9076 box.Back = 1;
9077 if (formats[i].block_width > 1)
9079 box.Left = formats[i].block_width >> 1;
9080 box.Top = 0;
9081 box.Right = formats[i].block_width;
9082 box.Bottom = formats[i].block_height;
9083 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9084 ok(FAILED(hr) || broken(formats[i].broken),
9085 "Partial block lock succeeded, expected failure, format %s.\n",
9086 formats[i].name);
9087 if (SUCCEEDED(hr))
9089 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9090 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9093 box.Left = 0;
9094 box.Top = 0;
9095 box.Right = formats[i].block_width >> 1;
9096 box.Bottom = formats[i].block_height;
9097 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9098 ok(FAILED(hr) || broken(formats[i].broken),
9099 "Partial block lock succeeded, expected failure, format %s.\n",
9100 formats[i].name);
9101 if (SUCCEEDED(hr))
9103 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9104 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9108 if (formats[i].block_height > 1)
9110 box.Left = 0;
9111 box.Top = formats[i].block_height >> 1;
9112 box.Right = formats[i].block_width;
9113 box.Bottom = formats[i].block_height;
9114 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9115 ok(FAILED(hr) || broken(formats[i].broken),
9116 "Partial block lock succeeded, expected failure, format %s.\n",
9117 formats[i].name);
9118 if (SUCCEEDED(hr))
9120 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9121 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9124 box.Left = 0;
9125 box.Top = 0;
9126 box.Right = formats[i].block_width;
9127 box.Bottom = formats[i].block_height >> 1;
9128 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9129 ok(FAILED(hr) || broken(formats[i].broken),
9130 "Partial block lock succeeded, expected failure, format %s.\n",
9131 formats[i].name);
9132 if (SUCCEEDED(hr))
9134 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9135 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9139 /* Test full block lock */
9140 box.Left = 0;
9141 box.Top = 0;
9142 box.Right = formats[i].block_width;
9143 box.Bottom = formats[i].block_height;
9144 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9145 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9146 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9147 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9149 IDirect3DVolumeTexture9_Release(texture);
9151 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
9152 * does not allocate surfaces smaller than the blocksize properly. */
9153 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
9155 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
9156 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9157 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9159 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
9160 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9161 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9162 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9164 box.Left = box.Top = box.Front = 0;
9165 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
9166 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
9167 box.Back = 1;
9168 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9169 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
9170 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9171 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9173 box.Right = formats[i].block_width;
9174 box.Bottom = formats[i].block_height;
9175 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
9176 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9177 if (SUCCEEDED(hr))
9178 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
9180 IDirect3DVolumeTexture9_Release(texture);
9184 refcount = IDirect3DDevice9_Release(device);
9185 ok(!refcount, "Device has %u references left.\n", refcount);
9186 IDirect3D9_Release(d3d9);
9187 DestroyWindow(window);
9190 static void test_lockbox_invalid(void)
9192 static const struct
9194 D3DBOX box;
9195 HRESULT result;
9197 test_data[] =
9199 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
9200 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
9201 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
9202 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
9203 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
9204 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
9205 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
9206 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
9207 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
9208 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
9209 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
9210 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
9211 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
9212 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
9214 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
9215 IDirect3DVolumeTexture9 *texture = NULL;
9216 D3DLOCKED_BOX locked_box;
9217 IDirect3DDevice9 *device;
9218 IDirect3D9 *d3d;
9219 unsigned int i;
9220 ULONG refcount;
9221 HWND window;
9222 BYTE *base;
9223 HRESULT hr;
9225 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9226 0, 0, 640, 480, 0, 0, 0, 0);
9227 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9228 ok(!!d3d, "Failed to create a D3D object.\n");
9229 if (!(device = create_device(d3d, window, NULL)))
9231 skip("Failed to create a D3D device, skipping tests.\n");
9232 IDirect3D9_Release(d3d);
9233 DestroyWindow(window);
9234 return;
9237 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
9238 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
9239 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9240 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9241 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9242 base = locked_box.pBits;
9243 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9244 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9246 for (i = 0; i < (sizeof(test_data) / sizeof(*test_data)); ++i)
9248 unsigned int offset, expected_offset;
9249 const D3DBOX *box = &test_data[i].box;
9251 locked_box.pBits = (BYTE *)0xdeadbeef;
9252 locked_box.RowPitch = 0xdeadbeef;
9253 locked_box.SlicePitch = 0xdeadbeef;
9255 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
9256 /* Unlike surfaces, volumes properly check the box even in Windows XP */
9257 ok(hr == test_data[i].result,
9258 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
9259 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
9260 test_data[i].result);
9261 if (FAILED(hr))
9262 continue;
9264 offset = (BYTE *)locked_box.pBits - base;
9265 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
9266 ok(offset == expected_offset,
9267 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
9268 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
9270 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9271 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9274 /* locked_box = NULL throws an exception on Windows */
9275 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9276 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9277 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9278 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9279 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9280 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9281 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9282 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9284 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9285 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9286 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9287 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9288 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
9289 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9290 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
9291 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
9292 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
9293 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
9294 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
9295 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
9296 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9297 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9299 IDirect3DVolumeTexture9_Release(texture);
9300 refcount = IDirect3DDevice9_Release(device);
9301 ok(!refcount, "Device has %u references left.\n", refcount);
9302 IDirect3D9_Release(d3d);
9303 DestroyWindow(window);
9306 static void test_shared_handle(void)
9308 IDirect3DDevice9 *device;
9309 IDirect3D9 *d3d;
9310 ULONG refcount;
9311 HWND window;
9312 HRESULT hr;
9313 /* Native d3d9ex refuses to create a shared texture if the texture pointer
9314 * is not initialized to NULL. Make sure this doesn't cause issues here. */
9315 IDirect3DTexture9 *texture = NULL;
9316 IDirect3DSurface9 *surface = NULL;
9317 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
9318 IDirect3DIndexBuffer9 *index_buffer = NULL;
9319 HANDLE handle = NULL;
9320 void *mem;
9321 D3DCAPS9 caps;
9323 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9324 0, 0, 640, 480, 0, 0, 0, 0);
9325 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9326 ok(!!d3d, "Failed to create a D3D object.\n");
9327 if (!(device = create_device(d3d, window, NULL)))
9329 skip("Failed to create a D3D device, skipping tests.\n");
9330 IDirect3D9_Release(d3d);
9331 DestroyWindow(window);
9332 return;
9335 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9336 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9337 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
9339 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
9340 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
9341 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9342 D3DPOOL_DEFAULT, &texture, &handle);
9343 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9344 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
9345 D3DPOOL_SYSTEMMEM, &texture, &mem);
9346 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9348 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9349 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
9350 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9351 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
9352 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
9353 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9355 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9356 &vertex_buffer, &handle);
9357 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9358 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9359 &vertex_buffer, &mem);
9360 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
9362 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
9363 &index_buffer, &handle);
9364 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9365 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
9366 &index_buffer, &mem);
9367 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9369 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9371 IDirect3DCubeTexture9 *cube_texture = NULL;
9372 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9373 D3DPOOL_DEFAULT, &cube_texture, &handle);
9374 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9375 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
9376 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
9377 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9380 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
9382 IDirect3DVolumeTexture9 *volume_texture = NULL;
9383 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9384 D3DPOOL_DEFAULT, &volume_texture, &handle);
9385 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9386 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
9387 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
9388 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9391 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
9392 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9393 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9395 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
9396 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
9397 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
9399 HeapFree(GetProcessHeap(), 0, mem);
9400 refcount = IDirect3DDevice9_Release(device);
9401 ok(!refcount, "Device has %u references left.\n", refcount);
9402 IDirect3D9_Release(d3d);
9403 DestroyWindow(window);
9406 static void test_pixel_format(void)
9408 HWND hwnd, hwnd2 = NULL;
9409 HDC hdc, hdc2 = NULL;
9410 HMODULE gl = NULL;
9411 int format, test_format;
9412 PIXELFORMATDESCRIPTOR pfd;
9413 IDirect3D9 *d3d9 = NULL;
9414 IDirect3DDevice9 *device = NULL;
9415 HRESULT hr;
9416 static const float point[3] = {0.0, 0.0, 0.0};
9418 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9419 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9420 if (!hwnd)
9422 skip("Failed to create window\n");
9423 return;
9426 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
9427 100, 100, 160, 160, NULL, NULL, NULL, NULL);
9429 hdc = GetDC(hwnd);
9430 if (!hdc)
9432 skip("Failed to get DC\n");
9433 goto cleanup;
9436 if (hwnd2)
9437 hdc2 = GetDC(hwnd2);
9439 gl = LoadLibraryA("opengl32.dll");
9440 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
9442 format = GetPixelFormat(hdc);
9443 ok(format == 0, "new window has pixel format %d\n", format);
9445 ZeroMemory(&pfd, sizeof(pfd));
9446 pfd.nSize = sizeof(pfd);
9447 pfd.nVersion = 1;
9448 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
9449 pfd.iPixelType = PFD_TYPE_RGBA;
9450 pfd.iLayerType = PFD_MAIN_PLANE;
9451 format = ChoosePixelFormat(hdc, &pfd);
9452 if (format <= 0)
9454 skip("no pixel format available\n");
9455 goto cleanup;
9458 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
9460 skip("failed to set pixel format\n");
9461 goto cleanup;
9464 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
9466 skip("failed to set pixel format on second window\n");
9467 if (hdc2)
9469 ReleaseDC(hwnd2, hdc2);
9470 hdc2 = NULL;
9474 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9475 ok(!!d3d9, "Failed to create a D3D object.\n");
9477 test_format = GetPixelFormat(hdc);
9478 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9480 if (!(device = create_device(d3d9, hwnd, NULL)))
9482 skip("Failed to create device\n");
9483 goto cleanup;
9486 test_format = GetPixelFormat(hdc);
9487 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9489 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9490 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
9492 test_format = GetPixelFormat(hdc);
9493 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9495 hr = IDirect3DDevice9_BeginScene(device);
9496 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
9498 test_format = GetPixelFormat(hdc);
9499 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9501 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
9502 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9504 test_format = GetPixelFormat(hdc);
9505 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9507 hr = IDirect3DDevice9_EndScene(device);
9508 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
9510 test_format = GetPixelFormat(hdc);
9511 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9513 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9514 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9516 test_format = GetPixelFormat(hdc);
9517 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9519 if (hdc2)
9521 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
9522 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
9524 test_format = GetPixelFormat(hdc);
9525 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
9527 test_format = GetPixelFormat(hdc2);
9528 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
9531 cleanup:
9532 if (device)
9534 UINT refcount = IDirect3DDevice9_Release(device);
9535 ok(!refcount, "Device has %u references left.\n", refcount);
9537 if (d3d9) IDirect3D9_Release(d3d9);
9538 if (gl) FreeLibrary(gl);
9539 if (hdc) ReleaseDC(hwnd, hdc);
9540 if (hdc2) ReleaseDC(hwnd2, hdc2);
9541 if (hwnd) DestroyWindow(hwnd);
9542 if (hwnd2) DestroyWindow(hwnd2);
9545 static void test_begin_end_state_block(void)
9547 IDirect3DStateBlock9 *stateblock;
9548 IDirect3DDevice9 *device;
9549 IDirect3D9 *d3d;
9550 ULONG refcount;
9551 HWND window;
9552 HRESULT hr;
9554 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9555 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9556 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9557 ok(!!d3d, "Failed to create a D3D object.\n");
9558 if (!(device = create_device(d3d, window, NULL)))
9560 skip("Failed to create a D3D device, skipping tests.\n");
9561 IDirect3D9_Release(d3d);
9562 DestroyWindow(window);
9563 return;
9566 /* Should succeed. */
9567 hr = IDirect3DDevice9_BeginStateBlock(device);
9568 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
9570 /* Calling BeginStateBlock() while recording should return
9571 * D3DERR_INVALIDCALL. */
9572 hr = IDirect3DDevice9_BeginStateBlock(device);
9573 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9575 /* Should succeed. */
9576 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
9577 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9578 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
9579 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
9580 "Got unexpected stateblock %p.\n", stateblock);
9581 IDirect3DStateBlock9_Release(stateblock);
9583 /* Calling EndStateBlock() while not recording should return
9584 * D3DERR_INVALIDCALL. stateblock should not be touched. */
9585 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
9586 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9587 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9588 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
9589 "Got unexpected stateblock %p.\n", stateblock);
9591 refcount = IDirect3DDevice9_Release(device);
9592 ok(!refcount, "Device has %u references left.\n", refcount);
9593 IDirect3D9_Release(d3d);
9594 DestroyWindow(window);
9597 static void test_shader_constant_apply(void)
9599 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
9600 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
9601 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
9602 IDirect3DStateBlock9 *stateblock;
9603 DWORD vs_version, ps_version;
9604 IDirect3DDevice9 *device;
9605 IDirect3D9 *d3d;
9606 ULONG refcount;
9607 D3DCAPS9 caps;
9608 float ret[4];
9609 HWND window;
9610 HRESULT hr;
9612 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9613 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9614 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9615 ok(!!d3d, "Failed to create a D3D object.\n");
9616 if (!(device = create_device(d3d, window, NULL)))
9618 skip("Failed to create a D3D device, skipping tests.\n");
9619 IDirect3D9_Release(d3d);
9620 DestroyWindow(window);
9621 return;
9624 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9625 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9626 vs_version = caps.VertexShaderVersion & 0xffff;
9627 ps_version = caps.PixelShaderVersion & 0xffff;
9629 if (vs_version)
9631 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
9632 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9633 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
9634 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9636 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
9637 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9638 ok(!memcmp(ret, initial, sizeof(initial)),
9639 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9640 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9641 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
9642 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9643 ok(!memcmp(ret, initial, sizeof(initial)),
9644 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9645 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9647 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
9648 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9650 if (ps_version)
9652 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
9653 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9654 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
9655 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9657 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
9658 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9659 ok(!memcmp(ret, initial, sizeof(initial)),
9660 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9661 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9662 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
9663 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9664 ok(!memcmp(ret, initial, sizeof(initial)),
9665 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9666 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9668 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
9669 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9672 hr = IDirect3DDevice9_BeginStateBlock(device);
9673 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
9675 if (vs_version)
9677 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
9678 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
9680 if (ps_version)
9682 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
9683 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
9686 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9687 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
9689 if (vs_version)
9691 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
9692 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9693 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
9694 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9695 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
9696 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
9697 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9698 ok(!memcmp(ret, initial, sizeof(initial)),
9699 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9700 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9702 if (ps_version)
9704 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
9705 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9706 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
9707 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9708 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
9709 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
9710 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9711 ok(!memcmp(ret, initial, sizeof(initial)),
9712 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9713 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
9716 /* Apply doesn't overwrite constants that aren't explicitly set on the
9717 * source stateblock. */
9718 hr = IDirect3DStateBlock9_Apply(stateblock);
9719 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
9721 if (vs_version)
9723 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
9724 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9725 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
9726 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9727 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
9728 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
9729 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
9730 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
9731 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9732 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
9734 if (ps_version)
9736 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
9737 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9738 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
9739 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9740 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
9741 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
9742 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
9743 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
9744 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
9745 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
9748 IDirect3DStateBlock9_Release(stateblock);
9749 refcount = IDirect3DDevice9_Release(device);
9750 ok(!refcount, "Device has %u references left.\n", refcount);
9751 IDirect3D9_Release(d3d);
9752 DestroyWindow(window);
9755 static void test_vdecl_apply(void)
9757 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
9758 IDirect3DStateBlock9 *stateblock;
9759 IDirect3DDevice9 *device;
9760 IDirect3D9 *d3d;
9761 ULONG refcount;
9762 HWND window;
9763 HRESULT hr;
9765 static const D3DVERTEXELEMENT9 decl1[] =
9767 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9768 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9769 D3DDECL_END(),
9772 static const D3DVERTEXELEMENT9 decl2[] =
9774 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9775 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9776 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
9777 D3DDECL_END(),
9780 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9781 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9782 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9783 ok(!!d3d, "Failed to create a D3D object.\n");
9784 if (!(device = create_device(d3d, window, NULL)))
9786 skip("Failed to create a D3D device, skipping tests.\n");
9787 IDirect3D9_Release(d3d);
9788 DestroyWindow(window);
9789 return;
9792 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
9793 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
9795 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
9796 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
9798 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9799 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9800 hr = IDirect3DDevice9_BeginStateBlock(device);
9801 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
9802 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
9803 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9804 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
9805 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
9806 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9807 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9808 hr = IDirect3DStateBlock9_Apply(stateblock);
9809 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9810 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9811 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9812 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
9813 declaration, declaration1);
9814 IDirect3DVertexDeclaration9_Release(declaration);
9816 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9817 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9818 hr = IDirect3DStateBlock9_Capture(stateblock);
9819 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9820 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9821 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9822 hr = IDirect3DStateBlock9_Apply(stateblock);
9823 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9824 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9825 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9826 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9827 declaration, declaration2);
9828 IDirect3DVertexDeclaration9_Release(declaration);
9830 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9831 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9832 hr = IDirect3DStateBlock9_Capture(stateblock);
9833 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9834 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9835 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9836 hr = IDirect3DStateBlock9_Apply(stateblock);
9837 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9838 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9839 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9840 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9841 declaration, declaration2);
9842 IDirect3DVertexDeclaration9_Release(declaration);
9844 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9845 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9846 hr = IDirect3DStateBlock9_Capture(stateblock);
9847 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9848 hr = IDirect3DStateBlock9_Apply(stateblock);
9849 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9850 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9851 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9852 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
9854 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9855 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9856 hr = IDirect3DStateBlock9_Capture(stateblock);
9857 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9858 hr = IDirect3DStateBlock9_Apply(stateblock);
9859 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9860 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9861 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9862 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9863 declaration, declaration2);
9864 IDirect3DVertexDeclaration9_Release(declaration);
9866 IDirect3DStateBlock9_Release(stateblock);
9867 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
9868 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9869 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
9870 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
9871 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9872 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9873 hr = IDirect3DStateBlock9_Apply(stateblock);
9874 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9875 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9876 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9877 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
9878 declaration, declaration1);
9879 IDirect3DVertexDeclaration9_Release(declaration);
9881 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9882 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9883 hr = IDirect3DStateBlock9_Capture(stateblock);
9884 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9885 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9886 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9887 hr = IDirect3DStateBlock9_Apply(stateblock);
9888 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9889 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9890 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9891 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9892 declaration, declaration2);
9893 IDirect3DVertexDeclaration9_Release(declaration);
9895 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9896 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9897 hr = IDirect3DStateBlock9_Capture(stateblock);
9898 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9899 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9900 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9901 hr = IDirect3DStateBlock9_Apply(stateblock);
9902 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9903 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9904 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9905 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9906 declaration, declaration2);
9907 IDirect3DVertexDeclaration9_Release(declaration);
9909 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9910 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9911 hr = IDirect3DStateBlock9_Capture(stateblock);
9912 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9913 hr = IDirect3DStateBlock9_Apply(stateblock);
9914 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9915 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9916 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9917 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
9919 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
9920 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9921 hr = IDirect3DStateBlock9_Capture(stateblock);
9922 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
9923 hr = IDirect3DStateBlock9_Apply(stateblock);
9924 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
9925 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
9926 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
9927 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
9928 declaration, declaration2);
9929 IDirect3DVertexDeclaration9_Release(declaration);
9931 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
9932 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
9933 IDirect3DVertexDeclaration9_Release(declaration1);
9934 IDirect3DVertexDeclaration9_Release(declaration2);
9935 IDirect3DStateBlock9_Release(stateblock);
9936 refcount = IDirect3DDevice9_Release(device);
9937 ok(!refcount, "Device has %u references left.\n", refcount);
9938 IDirect3D9_Release(d3d);
9939 DestroyWindow(window);
9942 static void test_resource_type(void)
9944 IDirect3DDevice9 *device;
9945 IDirect3DSurface9 *surface;
9946 IDirect3DTexture9 *texture;
9947 IDirect3DCubeTexture9 *cube_texture;
9948 IDirect3DVolume9 *volume;
9949 IDirect3DVolumeTexture9 *volume_texture;
9950 D3DSURFACE_DESC surface_desc;
9951 D3DVOLUME_DESC volume_desc;
9952 D3DRESOURCETYPE type;
9953 IDirect3D9 *d3d;
9954 ULONG refcount;
9955 HWND window;
9956 HRESULT hr;
9957 D3DCAPS9 caps;
9959 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9960 0, 0, 640, 480, NULL, NULL, NULL, NULL);
9961 d3d = Direct3DCreate9(D3D_SDK_VERSION);
9962 ok(!!d3d, "Failed to create a D3D object.\n");
9963 if (!(device = create_device(d3d, window, NULL)))
9965 skip("Failed to create a D3D device, skipping tests.\n");
9966 IDirect3D9_Release(d3d);
9967 DestroyWindow(window);
9968 return;
9971 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9972 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9974 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
9975 D3DPOOL_SYSTEMMEM, &surface, NULL);
9976 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
9977 type = IDirect3DSurface9_GetType(surface);
9978 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
9979 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
9980 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
9981 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
9982 surface_desc.Type);
9983 IDirect3DSurface9_Release(surface);
9985 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
9986 D3DPOOL_SYSTEMMEM, &texture, NULL);
9987 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
9988 type = IDirect3DTexture9_GetType(texture);
9989 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
9991 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
9992 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
9993 /* The following code crashes, for the sake of completeness:
9994 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
9995 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
9997 * So applications will not depend on getting the "right" resource type - whatever it
9998 * may be - from the "wrong" vtable. */
9999 type = IDirect3DSurface9_GetType(surface);
10000 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10001 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10002 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10003 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10004 surface_desc.Type);
10005 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10006 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10007 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10008 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10009 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10010 surface_desc.Type);
10011 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10012 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10013 IDirect3DSurface9_Release(surface);
10015 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10016 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10017 type = IDirect3DSurface9_GetType(surface);
10018 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10019 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10020 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10021 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10022 surface_desc.Type);
10023 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10024 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10025 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10026 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10027 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10028 surface_desc.Type);
10029 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10030 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10031 IDirect3DSurface9_Release(surface);
10032 IDirect3DTexture9_Release(texture);
10034 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10036 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10037 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10038 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10039 type = IDirect3DCubeTexture9_GetType(cube_texture);
10040 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10042 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10043 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10044 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10045 type = IDirect3DSurface9_GetType(surface);
10046 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10047 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10048 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10049 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10050 surface_desc.Type);
10051 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10052 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10053 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10054 surface_desc.Type);
10055 IDirect3DSurface9_Release(surface);
10056 IDirect3DCubeTexture9_Release(cube_texture);
10058 else
10059 skip("Cube maps not supported.\n");
10061 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10063 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10064 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10065 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10066 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10067 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10069 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10070 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10071 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10072 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10073 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10074 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10075 volume_desc.Type);
10076 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10077 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10078 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10079 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
10080 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10081 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10082 volume_desc.Type);
10083 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10084 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10085 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10086 IDirect3DVolume9_Release(volume);
10088 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
10089 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10090 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10091 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10092 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10093 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10094 volume_desc.Type);
10095 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10096 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10097 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10098 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
10099 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10100 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10101 volume_desc.Type);
10102 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10103 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10104 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10105 IDirect3DVolume9_Release(volume);
10106 IDirect3DVolumeTexture9_Release(volume_texture);
10108 else
10109 skip("Mipmapped volume maps not supported.\n");
10111 refcount = IDirect3DDevice9_Release(device);
10112 ok(!refcount, "Device has %u references left.\n", refcount);
10113 IDirect3D9_Release(d3d);
10114 DestroyWindow(window);
10117 static void test_mipmap_lock(void)
10119 IDirect3DDevice9 *device;
10120 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
10121 IDirect3DTexture9 *texture, *texture_dst;
10122 IDirect3D9 *d3d;
10123 ULONG refcount;
10124 HWND window;
10125 HRESULT hr;
10126 D3DLOCKED_RECT locked_rect;
10128 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10129 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10130 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10131 ok(!!d3d, "Failed to create a D3D object.\n");
10132 if (!(device = create_device(d3d, window, NULL)))
10134 skip("Failed to create a D3D device, skipping tests.\n");
10135 IDirect3D9_Release(d3d);
10136 DestroyWindow(window);
10137 return;
10140 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10141 D3DPOOL_DEFAULT, &texture_dst, NULL);
10142 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10143 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
10144 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10145 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
10146 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10148 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
10149 D3DPOOL_SYSTEMMEM, &texture, NULL);
10150 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10151 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10152 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10153 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
10154 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10156 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
10157 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10158 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
10159 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
10160 hr = IDirect3DSurface9_UnlockRect(surface);
10161 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10163 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
10164 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
10165 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
10166 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10168 /* Apparently there's no validation on the container. */
10169 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
10170 (IDirect3DBaseTexture9 *)texture_dst);
10171 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
10173 hr = IDirect3DSurface9_UnlockRect(surface2);
10174 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
10176 IDirect3DSurface9_Release(surface_dst2);
10177 IDirect3DSurface9_Release(surface_dst);
10178 IDirect3DSurface9_Release(surface2);
10179 IDirect3DSurface9_Release(surface);
10180 IDirect3DTexture9_Release(texture_dst);
10181 IDirect3DTexture9_Release(texture);
10183 refcount = IDirect3DDevice9_Release(device);
10184 ok(!refcount, "Device has %u references left.\n", refcount);
10185 IDirect3D9_Release(d3d);
10186 DestroyWindow(window);
10189 static void test_writeonly_resource(void)
10191 IDirect3D9 *d3d;
10192 IDirect3DDevice9 *device;
10193 IDirect3DVertexBuffer9 *buffer;
10194 ULONG refcount;
10195 HWND window;
10196 HRESULT hr;
10197 void *ptr;
10198 static const struct
10200 struct vec3 pos;
10202 quad[] =
10204 {{-1.0f, -1.0f, 0.0f}},
10205 {{-1.0f, 1.0f, 0.0f}},
10206 {{ 1.0f, -1.0f, 0.0f}},
10207 {{ 1.0f, 1.0f, 0.0f}}
10210 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10211 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10212 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10213 ok(!!d3d, "Failed to create a D3D object.\n");
10214 if (!(device = create_device(d3d, window, NULL)))
10216 skip("Failed to create a D3D device, skipping tests.\n");
10217 IDirect3D9_Release(d3d);
10218 DestroyWindow(window);
10219 return;
10222 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
10223 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
10224 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
10226 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
10227 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10228 memcpy(ptr, quad, sizeof(quad));
10229 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10230 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10231 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
10232 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
10233 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10234 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10236 hr = IDirect3DDevice9_BeginScene(device);
10237 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
10238 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
10239 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10240 hr = IDirect3DDevice9_EndScene(device);
10241 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
10243 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
10244 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10245 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10246 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10247 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10249 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
10250 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
10251 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
10252 hr = IDirect3DVertexBuffer9_Unlock(buffer);
10253 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
10255 refcount = IDirect3DVertexBuffer9_Release(buffer);
10256 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
10257 refcount = IDirect3DDevice9_Release(device);
10258 ok(!refcount, "Device has %u references left.\n", refcount);
10259 IDirect3D9_Release(d3d);
10260 DestroyWindow(window);
10263 static void test_lost_device(void)
10265 struct device_desc device_desc;
10266 IDirect3DDevice9 *device;
10267 IDirect3D9 *d3d;
10268 ULONG refcount;
10269 HWND window;
10270 HRESULT hr;
10271 BOOL ret;
10273 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10274 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10275 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10276 ok(!!d3d, "Failed to create a D3D object.\n");
10277 device_desc.device_window = window;
10278 device_desc.width = registry_mode.dmPelsWidth;
10279 device_desc.height = registry_mode.dmPelsHeight;
10280 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10281 if (!(device = create_device(d3d, window, &device_desc)))
10283 skip("Failed to create a D3D device, skipping tests.\n");
10284 goto done;
10287 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10288 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10289 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10290 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10292 ret = SetForegroundWindow(GetDesktopWindow());
10293 ok(ret, "Failed to set foreground window.\n");
10294 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10295 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10296 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10297 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10299 ret = ShowWindow(window, SW_RESTORE);
10300 ok(ret, "Failed to restore window.\n");
10301 ret = SetForegroundWindow(window);
10302 ok(ret, "Failed to set foreground window.\n");
10303 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10304 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
10305 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10306 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10308 hr = reset_device(device, &device_desc);
10309 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10310 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10311 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10312 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10313 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10315 device_desc.flags = 0;
10316 hr = reset_device(device, &device_desc);
10317 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10318 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10319 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10320 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10321 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10323 ret = SetForegroundWindow(GetDesktopWindow());
10324 ok(ret, "Failed to set foreground window.\n");
10325 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10326 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10327 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10328 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10330 ret = ShowWindow(window, SW_RESTORE);
10331 ok(ret, "Failed to restore window.\n");
10332 ret = SetForegroundWindow(window);
10333 ok(ret, "Failed to set foreground window.\n");
10334 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10335 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10336 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10337 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10339 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
10340 hr = reset_device(device, &device_desc);
10341 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10342 hr = IDirect3DDevice9_TestCooperativeLevel(device);
10343 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10344 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10345 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10347 ret = SetForegroundWindow(GetDesktopWindow());
10348 ok(ret, "Failed to set foreground window.\n");
10349 hr = reset_device(device, &device_desc);
10350 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
10351 ret = ShowWindow(window, SW_RESTORE);
10352 ok(ret, "Failed to restore window.\n");
10353 ret = SetForegroundWindow(window);
10354 ok(ret, "Failed to set foreground window.\n");
10355 hr = reset_device(device, &device_desc);
10356 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
10358 refcount = IDirect3DDevice9_Release(device);
10359 ok(!refcount, "Device has %u references left.\n", refcount);
10360 done:
10361 IDirect3D9_Release(d3d);
10362 DestroyWindow(window);
10365 static void test_resource_priority(void)
10367 IDirect3DDevice9 *device;
10368 IDirect3DSurface9 *surface;
10369 IDirect3DTexture9 *texture;
10370 IDirect3DVertexBuffer9 *buffer;
10371 IDirect3D9 *d3d;
10372 ULONG refcount;
10373 HWND window;
10374 HRESULT hr;
10375 static const struct
10377 D3DPOOL pool;
10378 const char *name;
10379 BOOL can_set_priority;
10381 test_data[] =
10383 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
10384 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
10385 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
10386 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
10388 unsigned int i;
10389 DWORD priority;
10391 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10392 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10393 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10394 ok(!!d3d, "Failed to create a D3D object.\n");
10395 if (!(device = create_device(d3d, window, NULL)))
10397 skip("Failed to create a D3D device, skipping tests.\n");
10398 IDirect3D9_Release(d3d);
10399 DestroyWindow(window);
10400 return;
10403 for (i = 0; i < sizeof(test_data) / sizeof(*test_data); i++)
10405 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
10406 test_data[i].pool, &texture, NULL);
10407 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
10408 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10409 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10411 priority = IDirect3DTexture9_GetPriority(texture);
10412 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10413 priority = IDirect3DTexture9_SetPriority(texture, 1);
10414 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10415 priority = IDirect3DTexture9_GetPriority(texture);
10416 if (test_data[i].can_set_priority)
10418 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10419 priority = IDirect3DTexture9_SetPriority(texture, 2);
10420 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10422 else
10423 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10425 priority = IDirect3DSurface9_GetPriority(surface);
10426 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10427 priority = IDirect3DSurface9_SetPriority(surface, 1);
10428 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10429 priority = IDirect3DSurface9_GetPriority(surface);
10430 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10432 IDirect3DSurface9_Release(surface);
10433 IDirect3DTexture9_Release(texture);
10435 if (test_data[i].pool != D3DPOOL_MANAGED)
10437 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
10438 test_data[i].pool, &surface, NULL);
10439 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
10441 priority = IDirect3DSurface9_GetPriority(surface);
10442 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10443 priority = IDirect3DSurface9_SetPriority(surface, 1);
10444 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10445 priority = IDirect3DSurface9_GetPriority(surface);
10446 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10448 IDirect3DSurface9_Release(surface);
10451 if (test_data[i].pool != D3DPOOL_SCRATCH)
10453 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
10454 test_data[i].pool, &buffer, NULL);
10455 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
10457 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10458 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10459 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
10460 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10461 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
10462 if (test_data[i].can_set_priority)
10464 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10465 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
10466 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10468 else
10469 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
10471 IDirect3DVertexBuffer9_Release(buffer);
10475 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
10476 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
10478 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
10479 priority = IDirect3DSurface9_GetPriority(surface);
10480 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10481 priority = IDirect3DSurface9_SetPriority(surface, 1);
10482 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10483 priority = IDirect3DSurface9_GetPriority(surface);
10484 ok(priority == 0, "Got unexpected priority %u.\n", priority);
10486 IDirect3DSurface9_Release(surface);
10488 refcount = IDirect3DDevice9_Release(device);
10489 ok(!refcount, "Device has %u references left.\n", refcount);
10490 IDirect3D9_Release(d3d);
10491 DestroyWindow(window);
10494 static void test_swapchain_parameters(void)
10496 IDirect3DDevice9 *device;
10497 IDirect3D9 *d3d;
10498 HWND window;
10499 HRESULT hr;
10500 unsigned int i;
10501 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
10502 IDirect3DSwapChain9 *swapchain;
10503 static const struct
10505 BOOL windowed;
10506 UINT backbuffer_count;
10507 D3DSWAPEFFECT swap_effect;
10508 HRESULT hr;
10510 tests[] =
10512 /* Swap effect 0 is not allowed. */
10513 {TRUE, 1, 0, D3DERR_INVALIDCALL},
10514 {FALSE, 1, 0, D3DERR_INVALIDCALL},
10516 /* All (non-ex) swap effects are allowed in
10517 * windowed and fullscreen mode. */
10518 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10519 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10520 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
10521 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
10522 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10524 /* Only one backbuffer in copy mode. */
10525 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
10526 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
10527 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10528 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
10530 /* Ok with the others, in fullscreen and windowed mode. */
10531 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
10532 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
10533 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
10534 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
10536 /* D3D9Ex swap effects. */
10537 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
10538 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
10539 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
10540 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
10541 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
10542 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
10544 /* 3 is the highest allowed backbuffer count. */
10545 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
10546 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
10547 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
10548 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
10549 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
10552 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10553 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10554 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10555 ok(!!d3d, "Failed to create a D3D object.\n");
10556 if (!(device = create_device(d3d, window, NULL)))
10558 skip("Failed to create a D3D device, skipping tests.\n");
10559 IDirect3D9_Release(d3d);
10560 DestroyWindow(window);
10561 return;
10563 IDirect3DDevice9_Release(device);
10565 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
10566 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
10567 present_parameters_windowed.hDeviceWindow = window;
10568 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
10569 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
10570 present_parameters_windowed.Windowed = TRUE;
10571 present_parameters_windowed.BackBufferCount = 1;
10573 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
10575 memset(&present_parameters, 0, sizeof(present_parameters));
10576 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
10577 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
10578 present_parameters.hDeviceWindow = window;
10579 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
10581 present_parameters.SwapEffect = tests[i].swap_effect;
10582 present_parameters.Windowed = tests[i].windowed;
10583 present_parameters.BackBufferCount = tests[i].backbuffer_count;
10585 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
10586 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
10587 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
10588 if (SUCCEEDED(hr))
10590 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
10592 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
10593 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
10595 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
10596 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
10597 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
10598 tests[i].swap_effect, present_parameters2.SwapEffect, i);
10599 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
10600 bb_count, present_parameters2.BackBufferCount, i);
10601 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
10602 tests[i].windowed, present_parameters2.Windowed, i);
10604 IDirect3DSwapChain9_Release(swapchain);
10605 IDirect3DDevice9_Release(device);
10608 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
10609 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
10610 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
10612 memset(&present_parameters, 0, sizeof(present_parameters));
10613 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
10614 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
10615 present_parameters.hDeviceWindow = window;
10616 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
10618 present_parameters.SwapEffect = tests[i].swap_effect;
10619 present_parameters.Windowed = tests[i].windowed;
10620 present_parameters.BackBufferCount = tests[i].backbuffer_count;
10622 hr = IDirect3DDevice9_Reset(device, &present_parameters);
10623 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
10625 if (FAILED(hr))
10627 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
10628 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
10630 IDirect3DDevice9_Release(device);
10633 IDirect3D9_Release(d3d);
10634 DestroyWindow(window);
10637 START_TEST(device)
10639 WNDCLASSA wc = {0};
10640 IDirect3D9 *d3d9;
10641 DEVMODEW current_mode;
10643 memset(&current_mode, 0, sizeof(current_mode));
10644 current_mode.dmSize = sizeof(current_mode);
10645 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
10646 registry_mode.dmSize = sizeof(registry_mode);
10647 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
10648 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
10649 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
10651 skip("Current mode does not match registry mode, skipping test.\n");
10652 return;
10655 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
10657 skip("could not create D3D9 object\n");
10658 return;
10660 IDirect3D9_Release(d3d9);
10662 wc.lpfnWndProc = DefWindowProcA;
10663 wc.lpszClassName = "d3d9_test_wc";
10664 RegisterClassA(&wc);
10666 test_get_set_vertex_declaration();
10667 test_get_declaration();
10668 test_fvf_decl_conversion();
10669 test_fvf_decl_management();
10670 test_vertex_declaration_alignment();
10671 test_unused_declaration_type();
10672 test_fpu_setup();
10673 test_multi_device();
10674 test_display_formats();
10675 test_display_modes();
10676 test_swapchain();
10677 test_refcount();
10678 test_mipmap_levels();
10679 test_checkdevicemultisampletype();
10680 test_cursor();
10681 test_cursor_pos();
10682 test_reset_fullscreen();
10683 test_reset();
10684 test_scene();
10685 test_limits();
10686 test_depthstenciltest();
10687 test_get_rt();
10688 test_draw_indexed();
10689 test_null_stream();
10690 test_lights();
10691 test_set_stream_source();
10692 test_scissor_size();
10693 test_wndproc();
10694 test_wndproc_windowed();
10695 test_window_style();
10696 test_mode_change();
10697 test_device_window_reset();
10698 test_reset_resources();
10699 test_set_rt_vp_scissor();
10700 test_volume_get_container();
10701 test_volume_resource();
10702 test_vb_lock_flags();
10703 test_vertex_buffer_alignment();
10704 test_query_support();
10705 test_occlusion_query_states();
10706 test_timestamp_query();
10707 test_get_set_vertex_shader();
10708 test_vertex_shader_constant();
10709 test_get_set_pixel_shader();
10710 test_pixel_shader_constant();
10711 test_unsupported_shaders();
10712 test_texture_stage_states();
10713 test_cube_textures();
10714 test_mipmap_gen();
10715 test_filter();
10716 test_get_set_texture();
10717 test_lod();
10718 test_surface_get_container();
10719 test_surface_alignment();
10720 test_lockrect_offset();
10721 test_lockrect_invalid();
10722 test_private_data();
10723 test_getdc();
10724 test_surface_dimensions();
10725 test_surface_format_null();
10726 test_surface_double_unlock();
10727 test_surface_blocks();
10728 test_set_palette();
10729 test_swvp_buffer();
10730 test_managed_buffer();
10731 test_npot_textures();
10732 test_vidmem_accounting();
10733 test_volume_locking();
10734 test_update_volumetexture();
10735 test_create_rt_ds_fail();
10736 test_volume_blocks();
10737 test_lockbox_invalid();
10738 test_shared_handle();
10739 test_pixel_format();
10740 test_begin_end_state_block();
10741 test_shader_constant_apply();
10742 test_vdecl_apply();
10743 test_resource_type();
10744 test_mipmap_lock();
10745 test_writeonly_resource();
10746 test_lost_device();
10747 test_resource_priority();
10748 test_swapchain_parameters();
10750 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));