d3d9/tests: Extend test_mipmap_gen().
[wine.git] / dlls / d3d9 / tests / device.c
blob0ffc1aeb97278a067d7d4ae43c47f24c37759abb
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 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
32 struct vec3
34 float x, y, z;
37 #define CREATE_DEVICE_FULLSCREEN 0x01
38 #define CREATE_DEVICE_NOWINDOWCHANGES 0x02
39 #define CREATE_DEVICE_FPU_PRESERVE 0x04
40 #define CREATE_DEVICE_SWVP_ONLY 0x08
41 #define CREATE_DEVICE_MIXED_ONLY 0x10
42 #define CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT 0x20
43 #define CREATE_DEVICE_LOCKABLE_BACKBUFFER 0x40
45 struct device_desc
47 HWND device_window;
48 unsigned int width;
49 unsigned int height;
50 DWORD flags;
53 #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
54 #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
56 static DEVMODEW registry_mode;
58 static const DWORD simple_vs[] =
60 0xfffe0101, /* vs_1_1 */
61 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
62 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
63 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
64 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
65 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
66 0x0000ffff, /* end */
69 static const DWORD simple_ps[] =
71 0xffff0101, /* ps_1_1 */
72 0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0 */
73 0x00000042, 0xb00f0000, /* tex t0 */
74 0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000, /* dp3 r0, c1, c0 */
75 0x00000005, 0x800f0000, 0x90e40000, 0x80e40000, /* mul r0, v0, r0 */
76 0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000, /* mul r0, t0, r0 */
77 0x0000ffff, /* end */
80 static int get_refcount(IUnknown *object)
82 IUnknown_AddRef( object );
83 return IUnknown_Release( object );
86 static BOOL compare_elements(IDirect3DVertexDeclaration9 *declaration, const D3DVERTEXELEMENT9 *expected_elements)
88 unsigned int element_count, i;
89 D3DVERTEXELEMENT9 *elements;
90 BOOL equal = TRUE;
91 HRESULT hr;
93 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
94 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
95 elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(*elements));
96 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
97 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
99 for (i = 0; i < element_count; ++i)
101 if (memcmp(&elements[i], &expected_elements[i], sizeof(*elements)))
103 equal = FALSE;
104 break;
108 if (!equal)
110 for (i = 0; i < element_count; ++i)
112 trace("[Element %u] stream %u, offset %u, type %#x, method %#x, usage %#x, usage index %u.\n",
113 i, elements[i].Stream, elements[i].Offset, elements[i].Type,
114 elements[i].Method, elements[i].Usage, elements[i].UsageIndex);
118 HeapFree(GetProcessHeap(), 0, elements);
119 return equal;
122 /* try to make sure pending X events have been processed before continuing */
123 static void flush_events(void)
125 MSG msg;
126 int diff = 200;
127 int min_timeout = 100;
128 DWORD time = GetTickCount() + diff;
130 while (diff > 0)
132 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
133 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
134 diff = time - GetTickCount();
138 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window, const struct device_desc *desc)
140 D3DPRESENT_PARAMETERS present_parameters = {0};
141 IDirect3DDevice9 *device;
142 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
144 present_parameters.BackBufferWidth = 640;
145 present_parameters.BackBufferHeight = 480;
146 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
147 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
148 present_parameters.hDeviceWindow = focus_window;
149 present_parameters.Windowed = TRUE;
150 present_parameters.EnableAutoDepthStencil = TRUE;
151 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
153 if (desc)
155 present_parameters.BackBufferWidth = desc->width;
156 present_parameters.BackBufferHeight = desc->height;
157 if (desc->flags & CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT)
158 present_parameters.BackBufferFormat = D3DFMT_UNKNOWN;
159 present_parameters.hDeviceWindow = desc->device_window;
160 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
161 if (desc->flags & CREATE_DEVICE_LOCKABLE_BACKBUFFER)
162 present_parameters.Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
163 if (desc->flags & CREATE_DEVICE_SWVP_ONLY)
164 behavior_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
165 else if (desc->flags & CREATE_DEVICE_MIXED_ONLY)
166 behavior_flags = D3DCREATE_MIXED_VERTEXPROCESSING;
167 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
168 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
169 if (desc->flags & CREATE_DEVICE_FPU_PRESERVE)
170 behavior_flags |= D3DCREATE_FPU_PRESERVE;
173 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
174 behavior_flags, &present_parameters, &device)))
175 return device;
177 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
178 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
179 behavior_flags, &present_parameters, &device)))
180 return device;
182 if (desc && (desc->flags & (CREATE_DEVICE_SWVP_ONLY | CREATE_DEVICE_MIXED_ONLY)))
183 return NULL;
184 behavior_flags = (behavior_flags
185 & ~(D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING))
186 | D3DCREATE_HARDWARE_VERTEXPROCESSING;
188 if (SUCCEEDED(IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
189 behavior_flags, &present_parameters, &device)))
190 return device;
192 return NULL;
195 static HRESULT reset_device(IDirect3DDevice9 *device, const struct device_desc *desc)
197 D3DPRESENT_PARAMETERS present_parameters = {0};
199 present_parameters.BackBufferWidth = 640;
200 present_parameters.BackBufferHeight = 480;
201 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
202 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
203 present_parameters.hDeviceWindow = NULL;
204 present_parameters.Windowed = TRUE;
205 present_parameters.EnableAutoDepthStencil = TRUE;
206 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
208 if (desc)
210 present_parameters.BackBufferWidth = desc->width;
211 present_parameters.BackBufferHeight = desc->height;
212 present_parameters.hDeviceWindow = desc->device_window;
213 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
216 return IDirect3DDevice9_Reset(device, &present_parameters);
219 #define CHECK_CALL(r,c,d,rc) \
220 if (SUCCEEDED(r)) {\
221 int tmp1 = get_refcount( (IUnknown *)d ); \
222 int rc_new = rc; \
223 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
224 } else {\
225 trace("%s failed: %08x\n", c, r); \
228 #define CHECK_RELEASE(obj,d,rc) \
229 if (obj) { \
230 int tmp1, rc_new = rc; \
231 IUnknown_Release( (IUnknown*)obj ); \
232 tmp1 = get_refcount( (IUnknown *)d ); \
233 ok(tmp1 == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, tmp1); \
236 #define CHECK_REFCOUNT(obj,rc) \
238 int rc_new = rc; \
239 int count = get_refcount( (IUnknown *)obj ); \
240 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
243 #define CHECK_RELEASE_REFCOUNT(obj,rc) \
245 int rc_new = rc; \
246 int count = IUnknown_Release( (IUnknown *)obj ); \
247 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
250 #define CHECK_ADDREF_REFCOUNT(obj,rc) \
252 int rc_new = rc; \
253 int count = IUnknown_AddRef( (IUnknown *)obj ); \
254 ok(count == rc_new, "Invalid refcount. Expected %d got %d\n", rc_new, count); \
257 #define CHECK_SURFACE_CONTAINER(obj,iid,expected) \
259 void *container_ptr = (void *)0x1337c0d3; \
260 hr = IDirect3DSurface9_GetContainer(obj, &iid, &container_ptr); \
261 ok(SUCCEEDED(hr) && container_ptr == expected, "GetContainer returned: hr %#x, container_ptr %p. " \
262 "Expected hr %#x, container_ptr %p\n", hr, container_ptr, S_OK, expected); \
263 if (container_ptr && container_ptr != (void *)0x1337c0d3) IUnknown_Release((IUnknown *)container_ptr); \
266 static void test_get_set_vertex_declaration(void)
268 IDirect3DVertexDeclaration9 *declaration, *tmp;
269 ULONG refcount, expected_refcount;
270 IDirect3DDevice9 *device;
271 IDirect3D9 *d3d;
272 HWND window;
273 HRESULT hr;
275 static const D3DVERTEXELEMENT9 simple_decl[] =
277 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
278 D3DDECL_END()
281 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
282 0, 0, 640, 480, NULL, NULL, NULL, NULL);
283 d3d = Direct3DCreate9(D3D_SDK_VERSION);
284 ok(!!d3d, "Failed to create a D3D object.\n");
285 if (!(device = create_device(d3d, window, NULL)))
287 skip("Failed to create a D3D device, skipping tests.\n");
288 goto done;
291 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
292 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
294 /* SetVertexDeclaration() should not touch the declaration's refcount. */
295 expected_refcount = get_refcount((IUnknown *)declaration);
296 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
297 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
298 refcount = get_refcount((IUnknown *)declaration);
299 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
301 /* GetVertexDeclaration() should increase the declaration's refcount by one. */
302 tmp = NULL;
303 expected_refcount = refcount + 1;
304 hr = IDirect3DDevice9_GetVertexDeclaration(device, &tmp);
305 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
306 ok(tmp == declaration, "Got unexpected declaration %p, expected %p.\n", tmp, declaration);
307 refcount = get_refcount((IUnknown *)declaration);
308 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
309 IDirect3DVertexDeclaration9_Release(tmp);
311 IDirect3DVertexDeclaration9_Release(declaration);
312 refcount = IDirect3DDevice9_Release(device);
313 ok(!refcount, "Device has %u references left.\n", refcount);
314 done:
315 IDirect3D9_Release(d3d);
316 DestroyWindow(window);
319 static void test_get_declaration(void)
321 unsigned int element_count, expected_element_count;
322 IDirect3DVertexDeclaration9 *declaration;
323 D3DVERTEXELEMENT9 *elements;
324 IDirect3DDevice9 *device;
325 IDirect3D9 *d3d;
326 ULONG refcount;
327 HWND window;
328 HRESULT hr;
330 static const D3DVERTEXELEMENT9 simple_decl[] =
332 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
333 D3DDECL_END()
336 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
337 0, 0, 640, 480, NULL, NULL, NULL, NULL);
338 d3d = Direct3DCreate9(D3D_SDK_VERSION);
339 ok(!!d3d, "Failed to create a D3D object.\n");
340 if (!(device = create_device(d3d, window, NULL)))
342 skip("Failed to create a D3D device, skipping tests.\n");
343 goto done;
346 hr = IDirect3DDevice9_CreateVertexDeclaration(device, simple_decl, &declaration);
347 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
349 /* First test only getting the number of elements. */
350 element_count = 0x1337c0de;
351 expected_element_count = ARRAY_SIZE(simple_decl);
352 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
353 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
354 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
355 element_count, expected_element_count);
357 element_count = 0;
358 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, NULL, &element_count);
359 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
360 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
361 element_count, expected_element_count);
363 /* Also test the returned data. */
364 elements = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(simple_decl));
366 element_count = 0x1337c0de;
367 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
368 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
369 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
370 element_count, expected_element_count);
371 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
372 "Original and returned vertexdeclarations are not the same.\n");
374 memset(elements, 0, sizeof(simple_decl));
376 element_count = 0;
377 hr = IDirect3DVertexDeclaration9_GetDeclaration(declaration, elements, &element_count);
378 ok(SUCCEEDED(hr), "Failed to get declaration, hr %#x.\n", hr);
379 ok(element_count == expected_element_count, "Got unexpected element count %u, expected %u.\n",
380 element_count, expected_element_count);
381 ok(!memcmp(elements, simple_decl, element_count * sizeof(*elements)),
382 "Original and returned vertexdeclarations are not the same.\n");
384 HeapFree(GetProcessHeap(), 0, elements);
385 IDirect3DVertexDeclaration9_Release(declaration);
386 refcount = IDirect3DDevice9_Release(device);
387 ok(!refcount, "Device has %u references left.\n", refcount);
388 done:
389 IDirect3D9_Release(d3d);
390 DestroyWindow(window);
393 static void test_fvf_decl_conversion(void)
395 IDirect3DVertexDeclaration9 *default_decl;
396 IDirect3DVertexDeclaration9 *declaration;
397 IDirect3DDevice9 *device;
398 IDirect3D9 *d3d;
399 ULONG refcount;
400 unsigned int i;
401 HWND window;
402 HRESULT hr;
404 static const D3DVERTEXELEMENT9 default_elements[] =
406 {0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
407 {0, 4, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
408 D3DDECL_END()
410 /* Test conversions from vertex declaration to an FVF. For some reason
411 * those seem to occur only for POSITION/POSITIONT, otherwise the FVF is
412 * forced to 0 - maybe this is configuration specific. */
413 static const struct
415 D3DVERTEXELEMENT9 elements[7];
416 DWORD fvf;
417 BOOL todo;
419 decl_to_fvf_tests[] =
421 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}, D3DFVF_XYZ, TRUE },
422 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}, D3DFVF_XYZRHW, TRUE },
423 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
424 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
425 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
426 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0}, D3DDECL_END()}, 0, FALSE},
427 {{{0, 0, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0}, D3DDECL_END()}, 0, FALSE},
428 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}, 0, FALSE},
429 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}, 0, FALSE},
430 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}, 0, FALSE},
431 {{{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}, 0, FALSE},
432 /* No FVF mapping available. */
433 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END()}, 0, FALSE},
434 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 1}, D3DDECL_END()}, 0, FALSE},
435 /* Try empty declaration. */
436 {{ D3DDECL_END()}, 0, FALSE},
437 /* Make sure textures of different sizes work. */
438 {{{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
439 {{{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
440 {{{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
441 {{{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()}, 0, FALSE},
442 /* Make sure the TEXCOORD index works correctly - try several textures. */
445 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
446 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
447 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
448 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
449 D3DDECL_END(),
450 }, 0, FALSE,
452 /* Now try a combination test. */
455 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITIONT, 0},
456 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0},
457 {0, 24, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0},
458 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
459 {0, 32, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
460 {0, 44, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 1},
461 D3DDECL_END(),
462 }, 0, FALSE,
465 /* Test conversions from FVF to a vertex declaration. These seem to always
466 * occur internally. A new declaration object is created if necessary. */
467 static const struct
469 DWORD fvf;
470 D3DVERTEXELEMENT9 elements[7];
472 fvf_to_decl_tests[] =
474 {D3DFVF_XYZ, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
475 {D3DFVF_XYZW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()}},
476 {D3DFVF_XYZRHW, {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()}},
478 D3DFVF_XYZB5,
480 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
481 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
482 {0, 28, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDINDICES, 0},
483 D3DDECL_END(),
487 D3DFVF_XYZB5 | D3DFVF_LASTBETA_UBYTE4,
489 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
490 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
491 {0, 28, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
492 D3DDECL_END(),
496 D3DFVF_XYZB5 | D3DFVF_LASTBETA_D3DCOLOR,
498 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
499 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
500 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
501 D3DDECL_END(),
505 D3DFVF_XYZB1,
507 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
508 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
509 D3DDECL_END(),
513 D3DFVF_XYZB1 | D3DFVF_LASTBETA_UBYTE4,
515 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
516 {0, 12, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
517 D3DDECL_END(),
521 D3DFVF_XYZB1 | D3DFVF_LASTBETA_D3DCOLOR,
523 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
524 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
525 D3DDECL_END(),
529 D3DFVF_XYZB2,
531 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
532 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
533 D3DDECL_END(),
537 D3DFVF_XYZB2 | D3DFVF_LASTBETA_UBYTE4,
539 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
540 {0, 12, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
541 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
542 D3DDECL_END(),
546 D3DFVF_XYZB2 | D3DFVF_LASTBETA_D3DCOLOR,
548 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
549 {0, 12, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
550 {0, 16, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
551 D3DDECL_END(),
555 D3DFVF_XYZB3,
557 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
558 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
559 D3DDECL_END(),
563 D3DFVF_XYZB3 | D3DFVF_LASTBETA_UBYTE4,
565 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
566 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
567 {0, 20, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
568 D3DDECL_END(),
572 D3DFVF_XYZB3 | D3DFVF_LASTBETA_D3DCOLOR,
574 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
575 {0, 12, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
576 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
577 D3DDECL_END(),
581 D3DFVF_XYZB4,
583 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
584 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
585 D3DDECL_END(),
589 D3DFVF_XYZB4 | D3DFVF_LASTBETA_UBYTE4,
591 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
592 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
593 {0, 24, D3DDECLTYPE_UBYTE4, 0, D3DDECLUSAGE_BLENDINDICES, 0},
594 D3DDECL_END(),
598 D3DFVF_XYZB4 | D3DFVF_LASTBETA_D3DCOLOR,
600 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
601 {0, 12, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
602 {0, 24, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_BLENDINDICES, 0},
603 D3DDECL_END(),
606 {D3DFVF_NORMAL, {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()}},
607 {D3DFVF_PSIZE, {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_PSIZE, 0}, D3DDECL_END()}},
608 {D3DFVF_DIFFUSE, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0}, D3DDECL_END()}},
609 {D3DFVF_SPECULAR, {{0, 0, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1}, D3DDECL_END()}},
610 /* Make sure textures of different sizes work. */
612 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEX1,
613 {{0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
616 D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEX1,
617 {{0, 0, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
620 D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1,
621 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
624 D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1,
625 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END()},
627 /* Make sure the TEXCOORD index works correctly - try several textures. */
629 D3DFVF_TEXCOORDSIZE1(0) | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEXCOORDSIZE2(2)
630 | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEX4,
632 {0, 0, D3DDECLTYPE_FLOAT1, 0, D3DDECLUSAGE_TEXCOORD, 0},
633 {0, 4, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
634 {0, 16, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 2},
635 {0, 24, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_TEXCOORD, 3},
636 D3DDECL_END(),
639 /* Now try a combination test. */
641 D3DFVF_XYZB4 | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEXCOORDSIZE2(0)
642 | D3DFVF_TEXCOORDSIZE3(1) | D3DFVF_TEX2,
644 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
645 {0, 12, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_BLENDWEIGHT, 0},
646 {0, 28, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
647 {0, 32, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 1},
648 {0, 36, D3DDECLTYPE_FLOAT2, 0, D3DDECLUSAGE_TEXCOORD, 0},
649 {0, 44, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_TEXCOORD, 1},
650 D3DDECL_END(),
655 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
656 0, 0, 640, 480, NULL, NULL, NULL, NULL);
657 d3d = Direct3DCreate9(D3D_SDK_VERSION);
658 ok(!!d3d, "Failed to create a D3D object.\n");
659 if (!(device = create_device(d3d, window, NULL)))
661 skip("Failed to create a D3D device, skipping tests.\n");
662 goto done;
665 for (i = 0; i < ARRAY_SIZE(decl_to_fvf_tests); ++i)
667 DWORD fvf = 0xdeadbeef;
668 HRESULT hr;
670 /* Set a default FVF of SPECULAR and DIFFUSE to make sure it is changed
671 * back to 0. */
672 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
673 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
675 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_to_fvf_tests[i].elements, &declaration);
676 ok(SUCCEEDED(hr), "Test %u: Failed to create vertex declaration, hr %#x.\n", i, hr);
677 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration);
678 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
680 /* Check the FVF. */
681 hr = IDirect3DDevice9_GetFVF(device, &fvf);
682 ok(SUCCEEDED(hr), "Test %u: Failed to get FVF, hr %#x.\n", i, hr);
684 todo_wine_if (decl_to_fvf_tests[i].todo)
685 ok(fvf == decl_to_fvf_tests[i].fvf,
686 "Test %u: Got unexpected FVF %#x, expected %#x.\n",
687 i, fvf, decl_to_fvf_tests[i].fvf);
689 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
690 IDirect3DVertexDeclaration9_Release(declaration);
693 /* Create a default declaration and FVF that does not match any of the
694 * tests. */
695 hr = IDirect3DDevice9_CreateVertexDeclaration(device, default_elements, &default_decl);
696 ok(SUCCEEDED(hr), "Failed to create vertex declaration, hr %#x.\n", hr);
698 for (i = 0; i < ARRAY_SIZE(fvf_to_decl_tests); ++i)
700 /* Set a default declaration to make sure it is changed. */
701 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
702 ok(SUCCEEDED(hr), "Test %u: Failed to set vertex declaration, hr %#x.\n", i, hr);
704 hr = IDirect3DDevice9_SetFVF(device, fvf_to_decl_tests[i].fvf);
705 ok(SUCCEEDED(hr), "Test %u: Failed to set FVF, hr %#x.\n", i, hr);
707 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
708 ok(SUCCEEDED(hr), "Test %u: Failed to get vertex declaration, hr %#x.\n", i, hr);
709 ok(!!declaration && declaration != default_decl,
710 "Test %u: Got unexpected declaration %p.\n", i, declaration);
711 ok(compare_elements(declaration, fvf_to_decl_tests[i].elements),
712 "Test %u: Declaration does not match.\n", i);
713 IDirect3DVertexDeclaration9_Release(declaration);
716 /* Setting the FVF to 0 should result in no change to the default decl. */
717 hr = IDirect3DDevice9_SetVertexDeclaration(device, default_decl);
718 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
719 hr = IDirect3DDevice9_SetFVF(device, 0);
720 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
721 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
722 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
723 ok(declaration == default_decl, "Got unexpected declaration %p, expected %p.\n", declaration, default_decl);
724 IDirect3DVertexDeclaration9_Release(declaration);
726 IDirect3DVertexDeclaration9_Release(default_decl);
727 refcount = IDirect3DDevice9_Release(device);
728 ok(!refcount, "Device has %u references left.\n", refcount);
729 done:
730 IDirect3D9_Release(d3d);
731 DestroyWindow(window);
734 /* Check whether a declaration converted from FVF is shared.
735 * Check whether refcounts behave as expected. */
736 static void test_fvf_decl_management(void)
738 IDirect3DVertexDeclaration9 *declaration1;
739 IDirect3DVertexDeclaration9 *declaration2;
740 IDirect3DVertexDeclaration9 *declaration3;
741 IDirect3DVertexDeclaration9 *declaration4;
742 IDirect3DDevice9 *device;
743 IDirect3D9 *d3d;
744 ULONG refcount;
745 HWND window;
746 HRESULT hr;
748 static const D3DVERTEXELEMENT9 test_elements1[] =
749 {{0, 0, D3DDECLTYPE_FLOAT4, 0, D3DDECLUSAGE_POSITIONT, 0}, D3DDECL_END()};
750 static const D3DVERTEXELEMENT9 test_elements2[] =
751 {{0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_NORMAL, 0}, D3DDECL_END()};
753 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
754 0, 0, 640, 480, NULL, NULL, NULL, NULL);
755 d3d = Direct3DCreate9(D3D_SDK_VERSION);
756 ok(!!d3d, "Failed to create a D3D object.\n");
757 if (!(device = create_device(d3d, window, NULL)))
759 skip("Failed to create a D3D device, skipping tests.\n");
760 goto done;
763 /* Clear down any current vertex declaration. */
764 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
765 ok(SUCCEEDED(hr), "Failed to set vertex declaration, hr %#x.\n", hr);
766 /* Conversion. */
767 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
768 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
769 /* Get converted decl (#1). */
770 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration1);
771 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
772 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
773 /* Get converted decl again (#2). */
774 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration2);
775 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
776 ok(declaration2 == declaration1, "Got unexpected declaration2 %p, expected %p.\n", declaration2, declaration1);
778 /* Conversion. */
779 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_NORMAL);
780 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
781 /* Get converted decl (#3). */
782 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration3);
783 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
784 ok(declaration3 != declaration2, "Got unexpected declaration3 %p.\n", declaration3);
785 /* The contents should correspond to the second conversion. */
786 ok(compare_elements(declaration3, test_elements2), "Declaration does not match.\n");
787 /* Re-Check if the first decl was overwritten by the new Get(). */
788 ok(compare_elements(declaration1, test_elements1), "Declaration does not match.\n");
790 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW);
791 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
792 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration4);
793 ok(SUCCEEDED(hr), "Failed to get vertex declaration, hr %#x.\n", hr);
794 ok(declaration4 == declaration1, "Got unexpected declaration4 %p, expected %p.\n", declaration4, declaration1);
796 refcount = get_refcount((IUnknown*)declaration1);
797 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
798 refcount = get_refcount((IUnknown*)declaration2);
799 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
800 refcount = get_refcount((IUnknown*)declaration3);
801 ok(refcount == 1, "Got unexpected refcount %u.\n", refcount);
802 refcount = get_refcount((IUnknown*)declaration4);
803 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
805 IDirect3DVertexDeclaration9_Release(declaration4);
806 IDirect3DVertexDeclaration9_Release(declaration3);
807 IDirect3DVertexDeclaration9_Release(declaration2);
808 IDirect3DVertexDeclaration9_Release(declaration1);
810 refcount = IDirect3DDevice9_Release(device);
811 ok(!refcount, "Device has %u references left.\n", refcount);
812 done:
813 IDirect3D9_Release(d3d);
814 DestroyWindow(window);
817 static void test_vertex_declaration_alignment(void)
819 IDirect3DVertexDeclaration9 *declaration;
820 IDirect3DDevice9 *device;
821 IDirect3D9 *d3d;
822 unsigned int i;
823 ULONG refcount;
824 HWND window;
825 HRESULT hr;
827 static const struct
829 D3DVERTEXELEMENT9 elements[3];
830 HRESULT hr;
832 test_data[] =
836 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
837 {0, 16, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
838 D3DDECL_END(),
839 }, D3D_OK,
843 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
844 {0, 17, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
845 D3DDECL_END(),
846 }, E_FAIL,
850 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
851 {0, 18, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
852 D3DDECL_END(),
853 }, E_FAIL,
857 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
858 {0, 19, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
859 D3DDECL_END(),
860 }, E_FAIL,
864 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0},
865 {0, 20, D3DDECLTYPE_D3DCOLOR, 0, D3DDECLUSAGE_COLOR, 0},
866 D3DDECL_END(),
867 }, D3D_OK,
871 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
872 0, 0, 640, 480, NULL, NULL, NULL, NULL);
873 d3d = Direct3DCreate9(D3D_SDK_VERSION);
874 ok(!!d3d, "Failed to create a D3D object.\n");
875 if (!(device = create_device(d3d, window, NULL)))
877 skip("Failed to create a D3D device, skipping tests.\n");
878 goto done;
881 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
883 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_data[i].elements, &declaration);
884 ok(hr == test_data[i].hr, "Test %u: Got unexpected hr %#x, expected %#x.\n", i, hr, test_data[i].hr);
885 if (SUCCEEDED(hr))
886 IDirect3DVertexDeclaration9_Release(declaration);
889 refcount = IDirect3DDevice9_Release(device);
890 ok(!refcount, "Device has %u references left.\n", refcount);
891 done:
892 IDirect3D9_Release(d3d);
893 DestroyWindow(window);
896 static void test_unused_declaration_type(void)
898 IDirect3DVertexDeclaration9 *declaration;
899 IDirect3DDevice9 *device;
900 IDirect3D9 *d3d;
901 unsigned int i;
902 ULONG refcount;
903 HWND window;
904 HRESULT hr;
906 static const D3DVERTEXELEMENT9 test_elements[][3] =
909 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
910 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_COLOR , 0 },
911 D3DDECL_END(),
914 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
915 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 0 },
916 D3DDECL_END(),
919 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
920 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 1 },
921 D3DDECL_END(),
924 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
925 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
926 D3DDECL_END(),
929 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
930 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_TEXCOORD, 12},
931 D3DDECL_END(),
934 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
935 {0, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
936 D3DDECL_END(),
939 {0, 0, D3DDECLTYPE_FLOAT3, 0, D3DDECLUSAGE_POSITION, 0 },
940 {1, 16, D3DDECLTYPE_UNUSED, 0, D3DDECLUSAGE_NORMAL, 0 },
941 D3DDECL_END(),
945 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
946 0, 0, 640, 480, NULL, NULL, NULL, NULL);
947 d3d = Direct3DCreate9(D3D_SDK_VERSION);
948 ok(!!d3d, "Failed to create a D3D object.\n");
949 if (!(device = create_device(d3d, window, NULL)))
951 skip("Failed to create a D3D device, skipping tests.\n");
952 goto done;
955 for (i = 0; i < ARRAY_SIZE(test_elements); ++i)
957 hr = IDirect3DDevice9_CreateVertexDeclaration(device, test_elements[i], &declaration);
958 ok(hr == E_FAIL, "Test %u: Got unexpected hr %#x.\n", i, hr);
961 refcount = IDirect3DDevice9_Release(device);
962 ok(!refcount, "Device has %u references left.\n", refcount);
963 done:
964 IDirect3D9_Release(d3d);
965 DestroyWindow(window);
968 static void check_mipmap_levels(IDirect3DDevice9 *device, UINT width, UINT height, UINT count)
970 IDirect3DBaseTexture9* texture = NULL;
971 HRESULT hr = IDirect3DDevice9_CreateTexture( device, width, height, 0, 0,
972 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DTexture9**) &texture, NULL );
974 if (SUCCEEDED(hr)) {
975 DWORD levels = IDirect3DBaseTexture9_GetLevelCount(texture);
976 ok(levels == count, "Invalid level count. Expected %d got %u\n", count, levels);
977 } else
978 trace("CreateTexture failed: %08x\n", hr);
980 if (texture) IDirect3DBaseTexture9_Release( texture );
983 static void test_mipmap_levels(void)
985 IDirect3DDevice9 *device;
986 IDirect3D9 *d3d;
987 ULONG refcount;
988 HWND window;
990 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
991 0, 0, 640, 480, NULL, NULL, NULL, NULL);
992 ok(!!window, "Failed to create a window.\n");
993 d3d = Direct3DCreate9(D3D_SDK_VERSION);
994 ok(!!d3d, "Failed to create a D3D object.\n");
995 if (!(device = create_device(d3d, window, NULL)))
997 skip("Failed to create a 3D device, skipping test.\n");
998 goto cleanup;
1001 check_mipmap_levels(device, 32, 32, 6);
1002 check_mipmap_levels(device, 256, 1, 9);
1003 check_mipmap_levels(device, 1, 256, 9);
1004 check_mipmap_levels(device, 1, 1, 1);
1006 refcount = IDirect3DDevice9_Release(device);
1007 ok(!refcount, "Device has %u references left.\n", refcount);
1008 cleanup:
1009 IDirect3D9_Release(d3d);
1010 DestroyWindow(window);
1013 static void test_checkdevicemultisampletype(void)
1015 DWORD quality_levels;
1016 IDirect3D9 *d3d;
1017 HWND window;
1018 HRESULT hr;
1020 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1021 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1022 ok(!!window, "Failed to create a window.\n");
1023 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1024 ok(!!d3d, "Failed to create a D3D object.\n");
1026 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1027 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL) == D3DERR_NOTAVAILABLE)
1029 skip("Multisampling not supported for D3DFMT_X8R8G8B8, skipping test.\n");
1030 goto cleanup;
1033 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1034 D3DFMT_UNKNOWN, TRUE, D3DMULTISAMPLE_NONE, NULL);
1035 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1036 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1037 65536, TRUE, D3DMULTISAMPLE_NONE, NULL);
1038 todo_wine ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1040 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1041 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, NULL);
1042 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1044 quality_levels = 0;
1045 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1046 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONE, &quality_levels);
1047 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1048 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1049 quality_levels = 0;
1050 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1051 D3DFMT_X8R8G8B8, FALSE, D3DMULTISAMPLE_NONE, &quality_levels);
1052 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1053 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1055 quality_levels = 0;
1056 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1057 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, NULL);
1058 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1059 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1060 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels);
1061 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1062 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1064 quality_levels = 0;
1065 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1066 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1067 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1068 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1069 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels);
1070 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1071 ok(quality_levels, "Got unexpected quality_levels %u.\n", quality_levels);
1073 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1074 quality_levels = 0;
1075 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1076 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1077 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1078 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1079 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, &quality_levels);
1080 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1081 ok(quality_levels == 1, "Got unexpected quality_levels %u.\n", quality_levels);
1083 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1084 D3DFMT_X8R8G8B8, TRUE, 65536, NULL);
1085 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1087 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1088 D3DFMT_DXT5, TRUE, D3DMULTISAMPLE_2_SAMPLES, NULL);
1089 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1091 cleanup:
1092 IDirect3D9_Release(d3d);
1093 DestroyWindow(window);
1096 static void test_invalid_multisample(void)
1098 IDirect3DDevice9 *device;
1099 IDirect3DSurface9 *rt;
1100 DWORD quality_levels;
1101 IDirect3D9 *d3d;
1102 BOOL available;
1103 ULONG refcount;
1104 HWND window;
1105 HRESULT hr;
1107 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1108 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1109 ok(!!window, "Failed to create a window.\n");
1110 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1111 ok(!!d3d, "Failed to create a D3D object.\n");
1113 if (!(device = create_device(d3d, window, NULL)))
1115 skip("Failed to create a 3D device, skipping test.\n");
1116 goto cleanup;
1119 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1120 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_NONMASKABLE, &quality_levels));
1121 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1122 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, 0, FALSE, &rt, NULL);
1123 if (available)
1125 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1126 IDirect3DSurface9_Release(rt);
1127 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1128 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONMASKABLE, quality_levels, FALSE, &rt, NULL);
1129 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1131 else
1133 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1136 available = SUCCEEDED(IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1137 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels));
1138 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1139 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, FALSE, &rt, NULL);
1140 if (available)
1142 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
1143 IDirect3DSurface9_Release(rt);
1144 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1145 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, quality_levels, FALSE, &rt, NULL);
1146 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1148 else
1150 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1153 /* We assume D3DMULTISAMPLE_15_SAMPLES is never supported in practice. */
1154 hr = IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
1155 D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_15_SAMPLES, NULL);
1156 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
1157 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
1158 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_15_SAMPLES, 0, FALSE, &rt, NULL);
1159 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1161 refcount = IDirect3DDevice9_Release(device);
1162 ok(!refcount, "Device has %u references left.\n", refcount);
1163 cleanup:
1164 IDirect3D9_Release(d3d);
1165 DestroyWindow(window);
1168 static void test_swapchain(void)
1170 IDirect3DSwapChain9 *swapchain0;
1171 IDirect3DSwapChain9 *swapchain1;
1172 IDirect3DSwapChain9 *swapchain2;
1173 IDirect3DSwapChain9 *swapchain3;
1174 IDirect3DSwapChain9 *swapchainX;
1175 IDirect3DSurface9 *backbuffer, *stereo_buffer;
1176 D3DPRESENT_PARAMETERS d3dpp;
1177 IDirect3DDevice9 *device;
1178 IDirect3D9 *d3d;
1179 ULONG refcount;
1180 HWND window, window2;
1181 HRESULT hr;
1182 struct device_desc device_desc;
1184 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1185 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1186 ok(!!window, "Failed to create a window.\n");
1187 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1188 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1189 ok(!!window2, "Failed to create a window.\n");
1190 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1191 ok(!!d3d, "Failed to create a D3D object.\n");
1192 if (!(device = create_device(d3d, window, NULL)))
1194 skip("Failed to create a 3D device, skipping test.\n");
1195 goto cleanup;
1198 /* Get the implicit swapchain */
1199 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain0);
1200 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
1201 /* Check if the back buffer count was modified */
1202 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain0, &d3dpp);
1203 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1204 ok(d3dpp.BackBufferCount == 1, "Got unexpected back buffer count %u.\n", d3dpp.BackBufferCount);
1205 IDirect3DSwapChain9_Release(swapchain0);
1207 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, NULL);
1208 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1209 /* IDirect3DDevice9::GetBackBuffer crashes if a NULL output pointer is passed. */
1210 backbuffer = (void *)0xdeadbeef;
1211 hr = IDirect3DDevice9_GetBackBuffer(device, 1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1212 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1213 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1214 backbuffer = (void *)0xdeadbeef;
1215 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 1, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1216 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1217 ok(!backbuffer, "The back buffer pointer is %p, expected NULL.\n", backbuffer);
1219 /* Check if there is a back buffer */
1220 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1221 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1222 ok(backbuffer != NULL, "The back buffer is NULL\n");
1223 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1225 /* The back buffer type value is ignored. */
1226 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1227 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1228 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1229 IDirect3DSurface9_Release(stereo_buffer);
1230 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1231 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1232 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1233 IDirect3DSurface9_Release(stereo_buffer);
1234 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1235 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1236 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1237 IDirect3DSurface9_Release(stereo_buffer);
1239 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_LEFT, &stereo_buffer);
1240 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1241 ok(stereo_buffer == backbuffer, "Expected left back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1242 IDirect3DSurface9_Release(stereo_buffer);
1243 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_RIGHT, &stereo_buffer);
1244 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1245 ok(stereo_buffer == backbuffer, "Expected right back buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1246 IDirect3DSurface9_Release(stereo_buffer);
1247 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, (D3DBACKBUFFER_TYPE)0xdeadbeef, &stereo_buffer);
1248 ok(SUCCEEDED(hr), "Failed to get the back buffer, hr %#x.\n", hr);
1249 ok(stereo_buffer == backbuffer, "Expected unknown buffer = %p, got %p.\n", backbuffer, stereo_buffer);
1250 IDirect3DSurface9_Release(stereo_buffer);
1252 /* Try to get a nonexistent swapchain */
1253 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1254 ok(hr == D3DERR_INVALIDCALL, "GetSwapChain on an nonexistent swapchain returned (%08x)\n", hr);
1255 ok(swapchainX == NULL, "Swapchain 1 is %p\n", swapchainX);
1256 if(swapchainX) IDirect3DSwapChain9_Release(swapchainX);
1258 /* Create a bunch of swapchains */
1259 d3dpp.BackBufferCount = 0;
1260 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1261 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1262 ok(d3dpp.BackBufferCount == 1, "The back buffer count in the presentparams struct is %d\n", d3dpp.BackBufferCount);
1264 d3dpp.BackBufferCount = 1;
1265 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain2);
1266 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1268 d3dpp.BackBufferCount = 2;
1269 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain3);
1270 ok(SUCCEEDED(hr), "Failed to create a swapchain (%08x)\n", hr);
1271 if(SUCCEEDED(hr)) {
1272 /* Swapchain 3, created with backbuffercount 2 */
1273 backbuffer = (void *) 0xdeadbeef;
1274 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 0, 0, &backbuffer);
1275 ok(SUCCEEDED(hr), "Failed to get the 1st back buffer (%08x)\n", hr);
1276 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1277 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1279 backbuffer = (void *) 0xdeadbeef;
1280 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 1, 0, &backbuffer);
1281 ok(SUCCEEDED(hr), "Failed to get the 2nd back buffer (%08x)\n", hr);
1282 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1283 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1285 backbuffer = (void *) 0xdeadbeef;
1286 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 2, 0, &backbuffer);
1287 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1288 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1289 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1291 backbuffer = (void *) 0xdeadbeef;
1292 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain3, 3, 0, &backbuffer);
1293 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1294 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1295 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1298 /* Check the back buffers of the swapchains */
1299 /* Swapchain 1, created with backbuffercount 0 */
1300 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1301 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1302 ok(backbuffer != NULL, "The back buffer is NULL (%08x)\n", hr);
1303 if(backbuffer) IDirect3DSurface9_Release(backbuffer);
1305 backbuffer = (void *) 0xdeadbeef;
1306 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain1, 1, 0, &backbuffer);
1307 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1308 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1309 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1311 /* Swapchain 2 - created with backbuffercount 1 */
1312 backbuffer = (void *) 0xdeadbeef;
1313 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 0, 0, &backbuffer);
1314 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
1315 ok(backbuffer != NULL && backbuffer != (void *) 0xdeadbeef, "The back buffer is %p\n", backbuffer);
1316 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1318 backbuffer = (void *) 0xdeadbeef;
1319 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 1, 0, &backbuffer);
1320 ok(hr == D3DERR_INVALIDCALL, "GetBackBuffer returned %08x\n", hr);
1321 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1322 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1324 backbuffer = (void *) 0xdeadbeef;
1325 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain2, 2, 0, &backbuffer);
1326 ok(FAILED(hr), "Failed to get the back buffer (%08x)\n", hr);
1327 ok(backbuffer == (void *) 0xdeadbeef, "The back buffer pointer was modified (%p)\n", backbuffer);
1328 if(backbuffer && backbuffer != (void *) 0xdeadbeef) IDirect3DSurface9_Release(backbuffer);
1330 /* Try getSwapChain on a manually created swapchain
1331 * it should fail, apparently GetSwapChain only returns implicit swapchains
1333 swapchainX = (void *) 0xdeadbeef;
1334 hr = IDirect3DDevice9_GetSwapChain(device, 1, &swapchainX);
1335 ok(hr == D3DERR_INVALIDCALL, "Failed to get the second swapchain (%08x)\n", hr);
1336 ok(swapchainX == NULL, "The swapchain pointer is %p\n", swapchainX);
1337 if(swapchainX && swapchainX != (void *) 0xdeadbeef ) IDirect3DSwapChain9_Release(swapchainX);
1339 IDirect3DSwapChain9_Release(swapchain3);
1340 IDirect3DSwapChain9_Release(swapchain2);
1341 IDirect3DSwapChain9_Release(swapchain1);
1343 d3dpp.Windowed = FALSE;
1344 d3dpp.hDeviceWindow = window;
1345 d3dpp.BackBufferCount = 1;
1346 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1347 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1348 d3dpp.hDeviceWindow = window2;
1349 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1350 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1352 device_desc.width = registry_mode.dmPelsWidth;
1353 device_desc.height = registry_mode.dmPelsHeight;
1354 device_desc.device_window = window;
1355 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
1356 hr = reset_device(device, &device_desc);
1357 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1359 d3dpp.hDeviceWindow = window;
1360 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1361 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1362 d3dpp.hDeviceWindow = window2;
1363 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1364 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1365 d3dpp.Windowed = TRUE;
1366 d3dpp.hDeviceWindow = window;
1367 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1368 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1369 d3dpp.hDeviceWindow = window2;
1370 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &swapchain1);
1371 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x\n", hr);
1373 refcount = IDirect3DDevice9_Release(device);
1374 ok(!refcount, "Device has %u references left.\n", refcount);
1375 cleanup:
1376 IDirect3D9_Release(d3d);
1377 DestroyWindow(window2);
1378 DestroyWindow(window);
1381 static void test_refcount(void)
1383 IDirect3DVertexBuffer9 *pVertexBuffer = NULL;
1384 IDirect3DIndexBuffer9 *pIndexBuffer = NULL;
1385 IDirect3DVertexDeclaration9 *pVertexDeclaration = NULL;
1386 IDirect3DVertexShader9 *pVertexShader = NULL;
1387 IDirect3DPixelShader9 *pPixelShader = NULL;
1388 IDirect3DCubeTexture9 *pCubeTexture = NULL;
1389 IDirect3DTexture9 *pTexture = NULL;
1390 IDirect3DVolumeTexture9 *pVolumeTexture = NULL;
1391 IDirect3DVolume9 *pVolumeLevel = NULL;
1392 IDirect3DSurface9 *pStencilSurface = NULL;
1393 IDirect3DSurface9 *pOffscreenSurface = NULL;
1394 IDirect3DSurface9 *pRenderTarget = NULL;
1395 IDirect3DSurface9 *pRenderTarget2 = NULL;
1396 IDirect3DSurface9 *pRenderTarget3 = NULL;
1397 IDirect3DSurface9 *pTextureLevel = NULL;
1398 IDirect3DSurface9 *pBackBuffer = NULL;
1399 IDirect3DStateBlock9 *pStateBlock = NULL;
1400 IDirect3DStateBlock9 *pStateBlock1 = NULL;
1401 IDirect3DSwapChain9 *pSwapChain = NULL;
1402 IDirect3DQuery9 *pQuery = NULL;
1403 D3DPRESENT_PARAMETERS d3dpp;
1404 IDirect3DDevice9 *device;
1405 ULONG refcount = 0, tmp;
1406 IDirect3D9 *d3d, *d3d2;
1407 HWND window;
1408 HRESULT hr;
1410 D3DVERTEXELEMENT9 decl[] =
1412 D3DDECL_END()
1415 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1416 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1417 ok(!!window, "Failed to create a window.\n");
1418 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1419 ok(!!d3d, "Failed to create a D3D object.\n");
1421 CHECK_REFCOUNT(d3d, 1);
1423 if (!(device = create_device(d3d, window, NULL)))
1425 skip("Failed to create a 3D device, skipping test.\n");
1426 goto cleanup;
1429 refcount = get_refcount((IUnknown *)device);
1430 ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
1432 CHECK_REFCOUNT(d3d, 2);
1434 hr = IDirect3DDevice9_GetDirect3D(device, &d3d2);
1435 CHECK_CALL(hr, "GetDirect3D", device, refcount);
1437 ok(d3d2 == d3d, "Expected IDirect3D9 pointers to be equal.\n");
1438 CHECK_REFCOUNT(d3d, 3);
1439 CHECK_RELEASE_REFCOUNT(d3d, 2);
1442 * Check refcount of implicit surfaces and implicit swapchain. Findings:
1443 * - the container is the device OR swapchain
1444 * - they hold a reference to the device
1445 * - they are created with a refcount of 0 (Get/Release returns original refcount)
1446 * - they are not freed if refcount reaches 0.
1447 * - the refcount is not forwarded to the container.
1449 hr = IDirect3DDevice9_GetSwapChain(device, 0, &pSwapChain);
1450 CHECK_CALL(hr, "GetSwapChain", device, ++refcount);
1451 if (pSwapChain)
1453 CHECK_REFCOUNT(pSwapChain, 1);
1455 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1456 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1457 CHECK_REFCOUNT(pSwapChain, 1);
1458 if (pRenderTarget)
1460 CHECK_SURFACE_CONTAINER(pRenderTarget, IID_IDirect3DSwapChain9, pSwapChain);
1461 CHECK_REFCOUNT(pRenderTarget, 1);
1463 CHECK_ADDREF_REFCOUNT(pRenderTarget, 2);
1464 CHECK_REFCOUNT(device, refcount);
1465 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1466 CHECK_REFCOUNT(device, refcount);
1468 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget);
1469 CHECK_CALL(hr, "GetRenderTarget", device, refcount);
1470 CHECK_REFCOUNT(pRenderTarget, 2);
1471 CHECK_RELEASE_REFCOUNT(pRenderTarget, 1);
1472 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1473 CHECK_REFCOUNT(device, --refcount);
1475 /* The render target is released with the device, so AddRef with refcount=0 is fine here. */
1476 CHECK_ADDREF_REFCOUNT(pRenderTarget, 1);
1477 CHECK_REFCOUNT(device, ++refcount);
1478 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1479 CHECK_REFCOUNT(device, --refcount);
1480 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1481 CHECK_RELEASE_REFCOUNT(pRenderTarget, 0);
1484 /* Render target and back buffer are identical. */
1485 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, 0, &pBackBuffer);
1486 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1487 if (pBackBuffer)
1489 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1490 ok(pRenderTarget == pBackBuffer, "RenderTarget=%p and BackBuffer=%p should be the same.\n",
1491 pRenderTarget, pBackBuffer);
1492 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1493 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1494 pBackBuffer = NULL;
1496 CHECK_REFCOUNT(device, --refcount);
1498 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &pStencilSurface);
1499 CHECK_CALL(hr, "GetDepthStencilSurface", device, ++refcount);
1500 CHECK_REFCOUNT(pSwapChain, 1);
1501 if (pStencilSurface)
1503 CHECK_SURFACE_CONTAINER(pStencilSurface, IID_IDirect3DDevice9, device);
1504 CHECK_REFCOUNT( pStencilSurface, 1);
1506 CHECK_ADDREF_REFCOUNT(pStencilSurface, 2);
1507 CHECK_REFCOUNT(device, refcount);
1508 CHECK_RELEASE_REFCOUNT(pStencilSurface, 1);
1509 CHECK_REFCOUNT(device, refcount);
1511 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1512 CHECK_REFCOUNT(device, --refcount);
1514 /* The stencil surface is released with the device, so AddRef with refcount=0 is fine here. */
1515 CHECK_ADDREF_REFCOUNT(pStencilSurface, 1);
1516 CHECK_REFCOUNT(device, ++refcount);
1517 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1518 CHECK_REFCOUNT(device, --refcount);
1519 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1520 CHECK_RELEASE_REFCOUNT(pStencilSurface, 0);
1521 pStencilSurface = NULL;
1524 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1525 CHECK_REFCOUNT(device, --refcount);
1526 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1527 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1529 /* The implicit swapchwin is released with the device, so AddRef with refcount=0 is fine here. */
1530 CHECK_ADDREF_REFCOUNT(pSwapChain, 1);
1531 CHECK_REFCOUNT(device, ++refcount);
1532 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1533 CHECK_REFCOUNT(device, --refcount);
1534 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1535 CHECK_RELEASE_REFCOUNT(pSwapChain, 0);
1536 pSwapChain = NULL;
1539 /* Buffers */
1540 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &pIndexBuffer, NULL);
1541 CHECK_CALL(hr, "CreateIndexBuffer", device, ++refcount );
1542 if(pIndexBuffer)
1544 tmp = get_refcount((IUnknown *)pIndexBuffer);
1546 hr = IDirect3DDevice9_SetIndices(device, pIndexBuffer);
1547 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1548 hr = IDirect3DDevice9_SetIndices(device, NULL);
1549 CHECK_CALL( hr, "SetIndices", pIndexBuffer, tmp);
1552 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, D3DFVF_XYZ, D3DPOOL_DEFAULT, &pVertexBuffer, NULL);
1553 CHECK_CALL(hr, "CreateVertexBuffer", device, ++refcount);
1554 if(pVertexBuffer)
1556 IDirect3DVertexBuffer9 *pVBuf = (void*)~0;
1557 UINT offset = ~0;
1558 UINT stride = ~0;
1560 tmp = get_refcount( (IUnknown *)pVertexBuffer );
1562 hr = IDirect3DDevice9_SetStreamSource(device, 0, pVertexBuffer, 0, 3 * sizeof(float));
1563 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1564 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1565 CHECK_CALL( hr, "SetStreamSource", pVertexBuffer, tmp);
1567 hr = IDirect3DDevice9_GetStreamSource(device, 0, &pVBuf, &offset, &stride);
1568 ok(SUCCEEDED(hr), "GetStreamSource did not succeed with NULL stream!\n");
1569 ok(pVBuf==NULL, "pVBuf not NULL (%p)!\n", pVBuf);
1570 ok(stride==3*sizeof(float), "stride not 3 floats (got %u)!\n", stride);
1571 ok(offset==0, "offset not 0 (got %u)!\n", offset);
1573 /* Shaders */
1574 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pVertexDeclaration);
1575 CHECK_CALL(hr, "CreateVertexDeclaration", device, ++refcount);
1576 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &pVertexShader);
1577 CHECK_CALL(hr, "CreateVertexShader", device, ++refcount);
1578 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &pPixelShader);
1579 CHECK_CALL(hr, "CreatePixelShader", device, ++refcount);
1580 /* Textures */
1581 hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 3, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
1582 CHECK_CALL(hr, "CreateTexture", device, ++refcount);
1583 if (pTexture)
1585 tmp = get_refcount( (IUnknown *)pTexture );
1587 /* SetTexture should not increase refcounts */
1588 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)pTexture);
1589 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1590 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1591 CHECK_CALL(hr, "SetTexture", pTexture, tmp);
1593 /* This should not increment device refcount */
1594 hr = IDirect3DTexture9_GetSurfaceLevel( pTexture, 1, &pTextureLevel );
1595 CHECK_CALL(hr, "GetSurfaceLevel", device, refcount);
1596 /* But should increment texture's refcount */
1597 CHECK_REFCOUNT( pTexture, tmp+1 );
1598 /* Because the texture and surface refcount are identical */
1599 if (pTextureLevel)
1601 CHECK_REFCOUNT ( pTextureLevel, tmp+1 );
1602 CHECK_ADDREF_REFCOUNT ( pTextureLevel, tmp+2 );
1603 CHECK_REFCOUNT ( pTexture , tmp+2 );
1604 CHECK_RELEASE_REFCOUNT( pTextureLevel, tmp+1 );
1605 CHECK_REFCOUNT ( pTexture , tmp+1 );
1606 CHECK_RELEASE_REFCOUNT( pTexture , tmp );
1607 CHECK_REFCOUNT ( pTextureLevel, tmp );
1610 hr = IDirect3DDevice9_CreateCubeTexture(device, 32, 0, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pCubeTexture, NULL);
1611 CHECK_CALL(hr, "CreateCubeTexture", device, ++refcount);
1612 hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 2, 0, 0,
1613 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pVolumeTexture, NULL);
1614 CHECK_CALL(hr, "CreateVolumeTexture", device, ++refcount);
1615 if (pVolumeTexture)
1617 tmp = get_refcount( (IUnknown *)pVolumeTexture );
1619 /* This should not increment device refcount */
1620 hr = IDirect3DVolumeTexture9_GetVolumeLevel(pVolumeTexture, 0, &pVolumeLevel);
1621 CHECK_CALL(hr, "GetVolumeLevel", device, refcount);
1622 /* But should increment volume texture's refcount */
1623 CHECK_REFCOUNT( pVolumeTexture, tmp+1 );
1624 /* Because the volume texture and volume refcount are identical */
1625 if (pVolumeLevel)
1627 CHECK_REFCOUNT ( pVolumeLevel , tmp+1 );
1628 CHECK_ADDREF_REFCOUNT ( pVolumeLevel , tmp+2 );
1629 CHECK_REFCOUNT ( pVolumeTexture, tmp+2 );
1630 CHECK_RELEASE_REFCOUNT( pVolumeLevel , tmp+1 );
1631 CHECK_REFCOUNT ( pVolumeTexture, tmp+1 );
1632 CHECK_RELEASE_REFCOUNT( pVolumeTexture, tmp );
1633 CHECK_REFCOUNT ( pVolumeLevel , tmp );
1636 /* Surfaces */
1637 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32,
1638 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &pStencilSurface, NULL);
1639 CHECK_CALL(hr, "CreateDepthStencilSurface", device, ++refcount);
1640 CHECK_REFCOUNT( pStencilSurface, 1 );
1641 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1642 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pOffscreenSurface, NULL);
1643 CHECK_CALL(hr, "CreateOffscreenPlainSurface", device, ++refcount);
1644 CHECK_REFCOUNT( pOffscreenSurface, 1 );
1645 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
1646 D3DFMT_X8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &pRenderTarget3, NULL);
1647 CHECK_CALL(hr, "CreateRenderTarget", device, ++refcount);
1648 CHECK_REFCOUNT( pRenderTarget3, 1 );
1649 /* Misc */
1650 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_ALL, &pStateBlock);
1651 CHECK_CALL(hr, "CreateStateBlock", device, ++refcount);
1653 memset(&d3dpp, 0, sizeof(d3dpp));
1654 d3dpp.Windowed = TRUE;
1655 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1656 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1657 d3dpp.EnableAutoDepthStencil = TRUE;
1658 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1659 hr = IDirect3DDevice9_CreateAdditionalSwapChain(device, &d3dpp, &pSwapChain);
1660 CHECK_CALL(hr, "CreateAdditionalSwapChain", device, ++refcount);
1661 if (pSwapChain)
1663 /* check implicit back buffer */
1664 hr = IDirect3DSwapChain9_GetBackBuffer(pSwapChain, 0, 0, &pBackBuffer);
1665 CHECK_CALL(hr, "GetBackBuffer", device, ++refcount);
1666 CHECK_REFCOUNT(pSwapChain, 1);
1667 if (pBackBuffer)
1669 CHECK_SURFACE_CONTAINER(pBackBuffer, IID_IDirect3DSwapChain9, pSwapChain);
1670 CHECK_REFCOUNT(pBackBuffer, 1);
1671 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1672 CHECK_REFCOUNT(device, --refcount);
1674 /* The back buffer is released with the swapchain, so AddRef with refcount=0 is fine here. */
1675 CHECK_ADDREF_REFCOUNT(pBackBuffer, 1);
1676 CHECK_REFCOUNT(device, ++refcount);
1677 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1678 CHECK_REFCOUNT(device, --refcount);
1679 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1680 CHECK_RELEASE_REFCOUNT(pBackBuffer, 0);
1681 pBackBuffer = NULL;
1683 CHECK_REFCOUNT(pSwapChain, 1);
1685 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_EVENT, &pQuery);
1686 CHECK_CALL(hr, "CreateQuery", device, ++refcount);
1688 hr = IDirect3DDevice9_BeginStateBlock(device);
1689 CHECK_CALL(hr, "BeginStateBlock", device, refcount);
1690 hr = IDirect3DDevice9_EndStateBlock(device, &pStateBlock1);
1691 CHECK_CALL(hr, "EndStateBlock", device, ++refcount);
1693 /* The implicit render target is not freed if refcount reaches 0.
1694 * Otherwise GetRenderTarget would re-allocate it and the pointer would change.*/
1695 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &pRenderTarget2);
1696 CHECK_CALL(hr, "GetRenderTarget", device, ++refcount);
1697 if (pRenderTarget2)
1699 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1700 ok(pRenderTarget == pRenderTarget2, "RenderTarget=%p and RenderTarget2=%p should be the same.\n",
1701 pRenderTarget, pRenderTarget2);
1702 CHECK_REFCOUNT(device, --refcount);
1703 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1704 CHECK_RELEASE_REFCOUNT(pRenderTarget2, 0);
1705 pRenderTarget2 = NULL;
1707 pRenderTarget = NULL;
1709 cleanup:
1710 CHECK_RELEASE(device, device, --refcount);
1712 /* Buffers */
1713 CHECK_RELEASE(pVertexBuffer, device, --refcount);
1714 CHECK_RELEASE(pIndexBuffer, device, --refcount);
1715 /* Shaders */
1716 CHECK_RELEASE(pVertexDeclaration, device, --refcount);
1717 CHECK_RELEASE(pVertexShader, device, --refcount);
1718 CHECK_RELEASE(pPixelShader, device, --refcount);
1719 /* Textures */
1720 CHECK_RELEASE(pTextureLevel, device, --refcount);
1721 CHECK_RELEASE(pCubeTexture, device, --refcount);
1722 CHECK_RELEASE(pVolumeTexture, device, --refcount);
1723 /* Surfaces */
1724 CHECK_RELEASE(pStencilSurface, device, --refcount);
1725 CHECK_RELEASE(pOffscreenSurface, device, --refcount);
1726 CHECK_RELEASE(pRenderTarget3, device, --refcount);
1727 /* Misc */
1728 CHECK_RELEASE(pStateBlock, device, --refcount);
1729 CHECK_RELEASE(pSwapChain, device, --refcount);
1730 CHECK_RELEASE(pQuery, device, --refcount);
1731 /* This will destroy device - cannot check the refcount here */
1732 if (pStateBlock1) CHECK_RELEASE_REFCOUNT( pStateBlock1, 0);
1733 CHECK_RELEASE_REFCOUNT(d3d, 0);
1734 DestroyWindow(window);
1737 static void test_cursor(void)
1739 IDirect3DSurface9 *cursor = NULL;
1740 IDirect3DDevice9 *device;
1741 CURSORINFO info;
1742 IDirect3D9 *d3d;
1743 ULONG refcount;
1744 HCURSOR cur;
1745 HWND window;
1746 HRESULT hr;
1747 BOOL ret;
1749 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1750 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1751 ok(!!window, "Failed to create a window.\n");
1753 ret = SetCursorPos(50, 50);
1754 ok(ret, "Failed to set cursor position.\n");
1755 flush_events();
1756 memset(&info, 0, sizeof(info));
1757 info.cbSize = sizeof(info);
1758 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1759 cur = info.hCursor;
1761 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1762 ok(!!d3d, "Failed to create a D3D object.\n");
1763 if (!(device = create_device(d3d, window, NULL)))
1765 skip("Failed to create a 3D device, skipping test.\n");
1766 goto cleanup;
1769 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
1770 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
1771 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
1773 /* Initially hidden */
1774 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1775 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1777 /* Not enabled without a surface*/
1778 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1779 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1781 /* Fails */
1782 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, NULL);
1783 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1785 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
1786 ok(hr == D3D_OK, "IDirect3DDevice9_SetCursorProperties returned %08x\n", hr);
1788 IDirect3DSurface9_Release(cursor);
1790 memset(&info, 0, sizeof(info));
1791 info.cbSize = sizeof(info);
1792 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1793 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1794 ok(info.hCursor == cur, "The cursor handle is %p\n", info.hCursor); /* unchanged */
1796 /* Still hidden */
1797 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1798 ok(!ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1800 /* Enabled now*/
1801 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
1802 ok(ret, "IDirect3DDevice9_ShowCursor returned %d\n", ret);
1804 memset(&info, 0, sizeof(info));
1805 info.cbSize = sizeof(info);
1806 ok(GetCursorInfo(&info), "GetCursorInfo failed\n");
1807 ok(info.flags & (CURSOR_SHOWING|CURSOR_SUPPRESSED), "The gdi cursor is hidden (%08x)\n", info.flags);
1808 ok(info.hCursor != cur, "The cursor handle is %p\n", info.hCursor);
1810 refcount = IDirect3DDevice9_Release(device);
1811 ok(!refcount, "Device has %u references left.\n", refcount);
1812 cleanup:
1813 IDirect3D9_Release(d3d);
1814 DestroyWindow(window);
1817 static void test_reset(void)
1819 HRESULT hr;
1820 RECT winrect, client_rect;
1821 D3DPRESENT_PARAMETERS d3dpp;
1822 D3DDISPLAYMODE d3ddm, d3ddm2;
1823 D3DVIEWPORT9 vp;
1824 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1825 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1826 IDirect3DSurface9 *surface;
1827 IDirect3DTexture9 *texture;
1828 IDirect3DVertexShader9 *shader;
1829 UINT i, adapter_mode_count;
1830 D3DLOCKED_RECT lockrect;
1831 IDirect3DDevice9 *device1 = NULL;
1832 IDirect3DDevice9 *device2 = NULL;
1833 IDirect3DSwapChain9 *swapchain;
1834 struct device_desc device_desc;
1835 DEVMODEW devmode;
1836 IDirect3D9 *d3d;
1837 D3DCAPS9 caps;
1838 DWORD value;
1839 HWND hwnd;
1840 LONG ret;
1841 struct
1843 UINT w;
1844 UINT h;
1845 } *modes = NULL;
1846 UINT mode_count = 0;
1848 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
1849 100, 100, 160, 160, NULL, NULL, NULL, NULL);
1850 ok(!!hwnd, "Failed to create a window.\n");
1851 d3d = Direct3DCreate9(D3D_SDK_VERSION);
1852 ok(!!d3d, "Failed to create a D3D object.\n");
1854 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
1855 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
1856 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1857 for(i = 0; i < adapter_mode_count; ++i)
1859 UINT j;
1860 ZeroMemory( &d3ddm2, sizeof(d3ddm2) );
1861 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
1862 ok(hr == D3D_OK, "IDirect3D9_EnumAdapterModes returned %#x\n", hr);
1864 for (j = 0; j < mode_count; ++j)
1866 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
1867 break;
1869 if (j == mode_count)
1871 modes[j].w = d3ddm2.Width;
1872 modes[j].h = d3ddm2.Height;
1873 ++mode_count;
1876 /* We use them as invalid modes */
1877 if((d3ddm2.Width == 801 && d3ddm2.Height == 600) ||
1878 (d3ddm2.Width == 32 && d3ddm2.Height == 32)) {
1879 skip("This system supports a screen resolution of %dx%d, not running mode tests\n",
1880 d3ddm2.Width, d3ddm2.Height);
1881 goto cleanup;
1885 if (mode_count < 2)
1887 skip("Less than 2 modes supported, skipping mode tests\n");
1888 goto cleanup;
1891 i = 0;
1892 if (modes[i].w == orig_width && modes[i].h == orig_height) ++i;
1894 device_desc.width = modes[i].w;
1895 device_desc.height = modes[i].h;
1896 device_desc.device_window = hwnd;
1897 device_desc.flags = CREATE_DEVICE_FULLSCREEN | CREATE_DEVICE_SWVP_ONLY;
1898 if (!(device1 = create_device(d3d, hwnd, &device_desc)))
1900 skip("Failed to create a D3D device, skipping tests.\n");
1901 goto cleanup;
1903 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1904 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
1906 hr = IDirect3DDevice9_GetDeviceCaps(device1, &caps);
1907 ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1909 width = GetSystemMetrics(SM_CXSCREEN);
1910 height = GetSystemMetrics(SM_CYSCREEN);
1911 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1912 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1914 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1915 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1916 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1917 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1918 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1919 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1920 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1921 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1923 i = 1;
1924 vp.X = 10;
1925 vp.Y = 20;
1926 vp.MinZ = 2;
1927 vp.MaxZ = 3;
1928 hr = IDirect3DDevice9_SetViewport(device1, &vp);
1929 ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
1931 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1932 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1933 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1934 hr = IDirect3DDevice9_SetRenderState(device1, D3DRS_LIGHTING, FALSE);
1935 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1937 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1938 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1939 d3dpp.Windowed = FALSE;
1940 d3dpp.BackBufferWidth = modes[i].w;
1941 d3dpp.BackBufferHeight = modes[i].h;
1942 d3dpp.BackBufferFormat = d3ddm.Format;
1943 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1944 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1945 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1946 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1948 hr = IDirect3DDevice9_GetRenderState(device1, D3DRS_LIGHTING, &value);
1949 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1950 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1952 ZeroMemory(&vp, sizeof(vp));
1953 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1954 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1955 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1956 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1957 ok(vp.Width == modes[i].w, "D3DVIEWPORT->Width = %u, expected %u\n", vp.Width, modes[i].w);
1958 ok(vp.Height == modes[i].h, "D3DVIEWPORT->Height = %u, expected %u\n", vp.Height, modes[i].h);
1959 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
1960 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
1962 width = GetSystemMetrics(SM_CXSCREEN);
1963 height = GetSystemMetrics(SM_CYSCREEN);
1964 ok(width == modes[i].w, "Screen width is %u, expected %u\n", width, modes[i].w);
1965 ok(height == modes[i].h, "Screen height is %u, expected %u\n", height, modes[i].h);
1967 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
1968 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1969 memset(&d3dpp, 0, sizeof(d3dpp));
1970 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1971 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1972 ok(d3dpp.BackBufferWidth == modes[i].w, "Got unexpected BackBufferWidth %u, expected %u.\n",
1973 d3dpp.BackBufferWidth, modes[i].w);
1974 ok(d3dpp.BackBufferHeight == modes[i].h, "Got unexpected BackBufferHeight %u, expected %u.\n",
1975 d3dpp.BackBufferHeight, modes[i].h);
1976 IDirect3DSwapChain9_Release(swapchain);
1978 ZeroMemory( &d3dpp, sizeof(d3dpp) );
1979 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1980 d3dpp.Windowed = TRUE;
1981 d3dpp.BackBufferWidth = 400;
1982 d3dpp.BackBufferHeight = 300;
1983 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1984 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
1985 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
1986 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
1987 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
1989 width = GetSystemMetrics(SM_CXSCREEN);
1990 height = GetSystemMetrics(SM_CYSCREEN);
1991 ok(width == orig_width, "Screen width is %d\n", width);
1992 ok(height == orig_height, "Screen height is %d\n", height);
1994 ZeroMemory(&vp, sizeof(vp));
1995 hr = IDirect3DDevice9_GetViewport(device1, &vp);
1996 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
1997 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
1998 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
1999 ok(vp.Width == 400, "D3DVIEWPORT->Width = %d\n", vp.Width);
2000 ok(vp.Height == 300, "D3DVIEWPORT->Height = %d\n", vp.Height);
2001 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2002 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2004 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2005 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2006 memset(&d3dpp, 0, sizeof(d3dpp));
2007 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2008 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2009 ok(d3dpp.BackBufferWidth == 400, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2010 ok(d3dpp.BackBufferHeight == 300, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2011 IDirect3DSwapChain9_Release(swapchain);
2013 memset(&devmode, 0, sizeof(devmode));
2014 devmode.dmSize = sizeof(devmode);
2015 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2016 devmode.dmPelsWidth = modes[1].w;
2017 devmode.dmPelsHeight = modes[1].h;
2018 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2019 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2020 width = GetSystemMetrics(SM_CXSCREEN);
2021 height = GetSystemMetrics(SM_CYSCREEN);
2022 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2023 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2025 d3dpp.BackBufferWidth = 500;
2026 d3dpp.BackBufferHeight = 400;
2027 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
2028 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2029 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed, hr %#x.\n", hr);
2030 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2031 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x.\n", hr);
2033 width = GetSystemMetrics(SM_CXSCREEN);
2034 height = GetSystemMetrics(SM_CYSCREEN);
2035 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
2036 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
2038 ZeroMemory(&vp, sizeof(vp));
2039 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2040 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed, hr %#x.\n", hr);
2041 ok(vp.X == 0, "D3DVIEWPORT->X = %d.\n", vp.X);
2042 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d.\n", vp.Y);
2043 ok(vp.Width == 500, "D3DVIEWPORT->Width = %d.\n", vp.Width);
2044 ok(vp.Height == 400, "D3DVIEWPORT->Height = %d.\n", vp.Height);
2045 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f.\n", vp.MinZ);
2046 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f.\n", vp.MaxZ);
2048 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2049 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2050 memset(&d3dpp, 0, sizeof(d3dpp));
2051 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2052 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2053 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
2054 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
2055 IDirect3DSwapChain9_Release(swapchain);
2057 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2058 devmode.dmPelsWidth = orig_width;
2059 devmode.dmPelsHeight = orig_height;
2060 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2061 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
2062 width = GetSystemMetrics(SM_CXSCREEN);
2063 height = GetSystemMetrics(SM_CYSCREEN);
2064 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
2065 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
2067 SetRect(&winrect, 0, 0, 200, 150);
2068 ok(AdjustWindowRect(&winrect, WS_OVERLAPPEDWINDOW, FALSE), "AdjustWindowRect failed\n");
2069 ok(SetWindowPos(hwnd, NULL, 0, 0,
2070 winrect.right-winrect.left,
2071 winrect.bottom-winrect.top,
2072 SWP_NOMOVE|SWP_NOZORDER),
2073 "SetWindowPos failed\n");
2075 /* Windows 10 gives us a different size than we requested with some DPI scaling settings (e.g. 172%). */
2076 GetClientRect(hwnd, &client_rect);
2078 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2079 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2080 d3dpp.Windowed = TRUE;
2081 d3dpp.BackBufferWidth = 0;
2082 d3dpp.BackBufferHeight = 0;
2083 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
2084 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2085 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2086 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2087 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2089 ok(d3dpp.BackBufferWidth == client_rect.right, "Got unexpected BackBufferWidth %u, expected %d.\n",
2090 d3dpp.BackBufferWidth, client_rect.right);
2091 ok(d3dpp.BackBufferHeight == client_rect.bottom, "Got unexpected BackBufferHeight %u, expected %d.\n",
2092 d3dpp.BackBufferHeight, client_rect.bottom);
2093 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2094 d3dpp.BackBufferFormat, d3ddm.Format);
2095 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2096 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2097 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2098 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2099 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
2100 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2101 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2102 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2103 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2104 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2105 d3dpp.FullScreen_RefreshRateInHz);
2106 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2108 ZeroMemory(&vp, sizeof(vp));
2109 hr = IDirect3DDevice9_GetViewport(device1, &vp);
2110 ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
2111 ok(vp.X == 0, "D3DVIEWPORT->X = %d\n", vp.X);
2112 ok(vp.Y == 0, "D3DVIEWPORT->Y = %d\n", vp.Y);
2113 ok(vp.Width == client_rect.right, "D3DVIEWPORT->Width = %d, expected %d\n",
2114 vp.Width, client_rect.right);
2115 ok(vp.Height == client_rect.bottom, "D3DVIEWPORT->Height = %d, expected %d\n",
2116 vp.Height, client_rect.bottom);
2117 ok(vp.MinZ == 0, "D3DVIEWPORT->MinZ = %f\n", vp.MinZ);
2118 ok(vp.MaxZ == 1, "D3DVIEWPORT->MaxZ = %f\n", vp.MaxZ);
2120 hr = IDirect3DDevice9_GetSwapChain(device1, 0, &swapchain);
2121 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
2122 memset(&d3dpp, 0, sizeof(d3dpp));
2123 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
2124 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
2125 ok(d3dpp.BackBufferWidth == client_rect.right,
2126 "Got unexpected BackBufferWidth %u, expected %d.\n", d3dpp.BackBufferWidth, client_rect.right);
2127 ok(d3dpp.BackBufferHeight == client_rect.bottom,
2128 "Got unexpected BackBufferHeight %u, expected %d.\n", d3dpp.BackBufferHeight, client_rect.bottom);
2129 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
2130 d3dpp.BackBufferFormat, d3ddm.Format);
2131 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
2132 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
2133 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
2134 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
2135 ok(d3dpp.hDeviceWindow == hwnd, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, hwnd);
2136 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
2137 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
2138 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
2139 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
2140 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
2141 d3dpp.FullScreen_RefreshRateInHz);
2142 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
2143 IDirect3DSwapChain9_Release(swapchain);
2145 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2146 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2147 d3dpp.Windowed = TRUE;
2148 d3dpp.BackBufferWidth = 400;
2149 d3dpp.BackBufferHeight = 300;
2151 /* _Reset fails if there is a resource in the default pool */
2152 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
2153 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2154 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2155 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2156 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2157 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2158 IDirect3DSurface9_Release(surface);
2159 /* Reset again to get the device out of the lost state */
2160 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2161 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2162 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2163 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2165 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
2167 IDirect3DVolumeTexture9 *volume_texture;
2169 hr = IDirect3DDevice9_CreateVolumeTexture(device1, 16, 16, 4, 1, 0,
2170 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
2171 ok(SUCCEEDED(hr), "CreateVolumeTexture failed, hr %#x.\n", hr);
2172 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2173 ok(hr == D3DERR_INVALIDCALL, "Reset returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2174 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2175 ok(hr == D3DERR_DEVICENOTRESET, "TestCooperativeLevel returned %#x, expected %#x.\n",
2176 hr, D3DERR_DEVICENOTRESET);
2177 IDirect3DVolumeTexture9_Release(volume_texture);
2178 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2179 ok(SUCCEEDED(hr), "Reset failed, hr %#x.\n", hr);
2180 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2181 ok(SUCCEEDED(hr), "TestCooperativeLevel failed, hr %#x.\n", hr);
2183 else
2185 skip("Volume textures not supported.\n");
2188 /* Scratch, sysmem and managed pools are fine */
2189 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2190 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2191 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2192 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2193 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2194 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2195 IDirect3DSurface9_Release(surface);
2197 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2198 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2199 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2200 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2201 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2202 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2203 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2204 IDirect3DSurface9_Release(surface);
2206 /* The depth stencil should get reset to the auto depth stencil when present. */
2207 hr = IDirect3DDevice9_SetDepthStencilSurface(device1, NULL);
2208 ok(hr == D3D_OK, "SetDepthStencilSurface failed with 0x%08x\n", hr);
2210 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2211 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2212 ok(surface == NULL, "Depth stencil should be NULL\n");
2214 d3dpp.EnableAutoDepthStencil = TRUE;
2215 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2216 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2217 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2219 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2220 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2221 ok(surface != NULL, "Depth stencil should not be NULL\n");
2222 if (surface) IDirect3DSurface9_Release(surface);
2224 d3dpp.EnableAutoDepthStencil = FALSE;
2225 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2226 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2228 hr = IDirect3DDevice9_GetDepthStencilSurface(device1, &surface);
2229 ok(hr == D3DERR_NOTFOUND, "GetDepthStencilSurface returned 0x%08x, expected D3DERR_NOTFOUND\n", hr);
2230 ok(surface == NULL, "Depth stencil should be NULL\n");
2232 /* Will a sysmem or scratch survive while locked */
2233 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16,
2234 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
2235 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2236 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2237 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2238 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2239 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2240 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2241 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2242 IDirect3DSurface9_UnlockRect(surface);
2243 IDirect3DSurface9_Release(surface);
2245 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device1, 16, 16, D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
2246 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface returned %08x\n", hr);
2247 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
2248 ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
2249 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2250 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2251 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2252 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2253 IDirect3DSurface9_UnlockRect(surface);
2254 IDirect3DSurface9_Release(surface);
2256 hr = IDirect3DDevice9_CreateTexture(device1, 16, 16, 0, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &texture, NULL);
2257 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
2258 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2259 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2260 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2261 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2262 IDirect3DTexture9_Release(texture);
2264 /* A reference held to an implicit surface causes failures as well */
2265 hr = IDirect3DDevice9_GetBackBuffer(device1, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
2266 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer returned %08x\n", hr);
2267 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2268 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2269 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2270 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2271 IDirect3DSurface9_Release(surface);
2272 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2273 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2274 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2275 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
2277 /* Shaders are fine as well */
2278 hr = IDirect3DDevice9_CreateVertexShader(device1, simple_vs, &shader);
2279 ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2280 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2281 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
2282 IDirect3DVertexShader9_Release(shader);
2284 /* Try setting invalid modes */
2285 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2286 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2287 d3dpp.Windowed = FALSE;
2288 d3dpp.BackBufferWidth = 32;
2289 d3dpp.BackBufferHeight = 32;
2290 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2291 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=32, h=32, windowed=FALSE failed with %08x\n", hr);
2292 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2293 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2295 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2296 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2297 d3dpp.Windowed = FALSE;
2298 d3dpp.BackBufferWidth = 801;
2299 d3dpp.BackBufferHeight = 600;
2300 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2301 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=801, h=600, windowed=FALSE failed with %08x\n", hr);
2302 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2303 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2305 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2306 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2307 d3dpp.Windowed = FALSE;
2308 d3dpp.BackBufferWidth = 0;
2309 d3dpp.BackBufferHeight = 0;
2310 hr = IDirect3DDevice9_Reset(device1, &d3dpp);
2311 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Reset to w=0, h=0, windowed=FALSE failed with %08x\n", hr);
2312 hr = IDirect3DDevice9_TestCooperativeLevel(device1);
2313 ok(hr == D3DERR_DEVICENOTRESET, "IDirect3DDevice9_TestCooperativeLevel after a failed reset returned %#x\n", hr);
2315 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2317 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2318 d3dpp.Windowed = TRUE;
2319 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2320 d3dpp.BackBufferFormat = d3ddm.Format;
2321 d3dpp.EnableAutoDepthStencil = FALSE;
2322 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2324 if (FAILED(hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
2325 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device2)))
2327 skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hr);
2328 goto cleanup;
2331 hr = IDirect3DDevice9_TestCooperativeLevel(device2);
2332 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after creation returned %#x\n", hr);
2334 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2335 d3dpp.Windowed = TRUE;
2336 d3dpp.BackBufferWidth = 400;
2337 d3dpp.BackBufferHeight = 300;
2338 d3dpp.EnableAutoDepthStencil = TRUE;
2339 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
2341 hr = IDirect3DDevice9_Reset(device2, &d3dpp);
2342 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with 0x%08x\n", hr);
2344 if (FAILED(hr)) goto cleanup;
2346 hr = IDirect3DDevice9_GetDepthStencilSurface(device2, &surface);
2347 ok(hr == D3D_OK, "GetDepthStencilSurface failed with 0x%08x\n", hr);
2348 ok(surface != NULL, "Depth stencil should not be NULL\n");
2349 if (surface) IDirect3DSurface9_Release(surface);
2351 cleanup:
2352 HeapFree(GetProcessHeap(), 0, modes);
2353 if (device2)
2355 UINT refcount = IDirect3DDevice9_Release(device2);
2356 ok(!refcount, "Device has %u references left.\n", refcount);
2358 if (device1)
2360 UINT refcount = IDirect3DDevice9_Release(device1);
2361 ok(!refcount, "Device has %u references left.\n", refcount);
2363 IDirect3D9_Release(d3d);
2364 DestroyWindow(hwnd);
2367 /* Test adapter display modes */
2368 static void test_display_modes(void)
2370 D3DDISPLAYMODE dmode;
2371 IDirect3D9 *d3d;
2373 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2374 ok(!!d3d, "Failed to create a D3D object.\n");
2376 #define TEST_FMT(x,r) do { \
2377 HRESULT res = IDirect3D9_EnumAdapterModes(d3d, 0, (x), 0, &dmode); \
2378 ok(res==(r), "EnumAdapterModes("#x") did not return "#r" (got %08x)!\n", res); \
2379 } while(0)
2381 TEST_FMT(D3DFMT_R8G8B8, D3DERR_INVALIDCALL);
2382 TEST_FMT(D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
2383 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2384 /* D3DFMT_R5G6B5 */
2385 TEST_FMT(D3DFMT_X1R5G5B5, D3DERR_INVALIDCALL);
2386 TEST_FMT(D3DFMT_A1R5G5B5, D3DERR_INVALIDCALL);
2387 TEST_FMT(D3DFMT_A4R4G4B4, D3DERR_INVALIDCALL);
2388 TEST_FMT(D3DFMT_R3G3B2, D3DERR_INVALIDCALL);
2389 TEST_FMT(D3DFMT_A8, D3DERR_INVALIDCALL);
2390 TEST_FMT(D3DFMT_A8R3G3B2, D3DERR_INVALIDCALL);
2391 TEST_FMT(D3DFMT_X4R4G4B4, D3DERR_INVALIDCALL);
2392 TEST_FMT(D3DFMT_A2B10G10R10, D3DERR_INVALIDCALL);
2393 TEST_FMT(D3DFMT_A8B8G8R8, D3DERR_INVALIDCALL);
2394 TEST_FMT(D3DFMT_X8B8G8R8, D3DERR_INVALIDCALL);
2395 TEST_FMT(D3DFMT_G16R16, D3DERR_INVALIDCALL);
2396 TEST_FMT(D3DFMT_A16B16G16R16, D3DERR_INVALIDCALL);
2398 TEST_FMT(D3DFMT_A8P8, D3DERR_INVALIDCALL);
2399 TEST_FMT(D3DFMT_P8, D3DERR_INVALIDCALL);
2401 TEST_FMT(D3DFMT_L8, D3DERR_INVALIDCALL);
2402 TEST_FMT(D3DFMT_A8L8, D3DERR_INVALIDCALL);
2403 TEST_FMT(D3DFMT_A4L4, D3DERR_INVALIDCALL);
2405 TEST_FMT(D3DFMT_V8U8, D3DERR_INVALIDCALL);
2406 TEST_FMT(D3DFMT_L6V5U5, D3DERR_INVALIDCALL);
2407 TEST_FMT(D3DFMT_X8L8V8U8, D3DERR_INVALIDCALL);
2408 TEST_FMT(D3DFMT_Q8W8V8U8, D3DERR_INVALIDCALL);
2409 TEST_FMT(D3DFMT_V16U16, D3DERR_INVALIDCALL);
2410 TEST_FMT(D3DFMT_A2W10V10U10, D3DERR_INVALIDCALL);
2412 TEST_FMT(D3DFMT_UYVY, D3DERR_INVALIDCALL);
2413 TEST_FMT(D3DFMT_YUY2, D3DERR_INVALIDCALL);
2414 TEST_FMT(D3DFMT_DXT1, D3DERR_INVALIDCALL);
2415 TEST_FMT(D3DFMT_DXT2, D3DERR_INVALIDCALL);
2416 TEST_FMT(D3DFMT_DXT3, D3DERR_INVALIDCALL);
2417 TEST_FMT(D3DFMT_DXT4, D3DERR_INVALIDCALL);
2418 TEST_FMT(D3DFMT_DXT5, D3DERR_INVALIDCALL);
2419 TEST_FMT(D3DFMT_MULTI2_ARGB8, D3DERR_INVALIDCALL);
2420 TEST_FMT(D3DFMT_G8R8_G8B8, D3DERR_INVALIDCALL);
2421 TEST_FMT(D3DFMT_R8G8_B8G8, D3DERR_INVALIDCALL);
2423 TEST_FMT(D3DFMT_D16_LOCKABLE, D3DERR_INVALIDCALL);
2424 TEST_FMT(D3DFMT_D32, D3DERR_INVALIDCALL);
2425 TEST_FMT(D3DFMT_D15S1, D3DERR_INVALIDCALL);
2426 TEST_FMT(D3DFMT_D24S8, D3DERR_INVALIDCALL);
2427 TEST_FMT(D3DFMT_D24X8, D3DERR_INVALIDCALL);
2428 TEST_FMT(D3DFMT_D24X4S4, D3DERR_INVALIDCALL);
2429 TEST_FMT(D3DFMT_D16, D3DERR_INVALIDCALL);
2430 TEST_FMT(D3DFMT_L16, D3DERR_INVALIDCALL);
2431 TEST_FMT(D3DFMT_D32F_LOCKABLE, D3DERR_INVALIDCALL);
2432 TEST_FMT(D3DFMT_D24FS8, D3DERR_INVALIDCALL);
2434 TEST_FMT(D3DFMT_VERTEXDATA, D3DERR_INVALIDCALL);
2435 TEST_FMT(D3DFMT_INDEX16, D3DERR_INVALIDCALL);
2436 TEST_FMT(D3DFMT_INDEX32, D3DERR_INVALIDCALL);
2437 TEST_FMT(D3DFMT_Q16W16V16U16, D3DERR_INVALIDCALL);
2438 /* Floating point formats */
2439 TEST_FMT(D3DFMT_R16F, D3DERR_INVALIDCALL);
2440 TEST_FMT(D3DFMT_G16R16F, D3DERR_INVALIDCALL);
2441 TEST_FMT(D3DFMT_A16B16G16R16F, D3DERR_INVALIDCALL);
2443 /* IEEE formats */
2444 TEST_FMT(D3DFMT_R32F, D3DERR_INVALIDCALL);
2445 TEST_FMT(D3DFMT_G32R32F, D3DERR_INVALIDCALL);
2446 TEST_FMT(D3DFMT_A32B32G32R32F, D3DERR_INVALIDCALL);
2448 TEST_FMT(D3DFMT_CxV8U8, D3DERR_INVALIDCALL);
2450 TEST_FMT(0, D3DERR_INVALIDCALL);
2452 IDirect3D9_Release(d3d);
2455 static void test_scene(void)
2457 IDirect3DSurface9 *surface1, *surface2, *surface3;
2458 IDirect3DSurface9 *backBuffer, *rt, *ds;
2459 RECT rect = {0, 0, 128, 128};
2460 IDirect3DDevice9 *device;
2461 IDirect3D9 *d3d;
2462 ULONG refcount;
2463 D3DCAPS9 caps;
2464 HWND window;
2465 HRESULT hr;
2467 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2468 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2469 ok(!!window, "Failed to create a window.\n");
2470 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2471 ok(!!d3d, "Failed to create a D3D object.\n");
2472 if (!(device = create_device(d3d, window, NULL)))
2474 skip("Failed to create a 3D device, skipping test.\n");
2475 goto cleanup;
2478 /* Get the caps, they will be needed to tell if an operation is supposed to be valid */
2479 memset(&caps, 0, sizeof(caps));
2480 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2481 ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed with %08x\n", hr);
2483 /* Test an EndScene without BeginScene. Should return an error */
2484 hr = IDirect3DDevice9_EndScene(device);
2485 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2487 /* Test a normal BeginScene / EndScene pair, this should work */
2488 hr = IDirect3DDevice9_BeginScene(device);
2489 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2490 hr = IDirect3DDevice9_EndScene(device);
2491 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2493 /* Test another EndScene without having begun a new scene. Should return an error */
2494 hr = IDirect3DDevice9_EndScene(device);
2495 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2497 /* Two nested BeginScene and EndScene calls */
2498 hr = IDirect3DDevice9_BeginScene(device);
2499 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2500 hr = IDirect3DDevice9_BeginScene(device);
2501 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
2502 hr = IDirect3DDevice9_EndScene(device);
2503 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2504 hr = IDirect3DDevice9_EndScene(device);
2505 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_EndScene returned %08x\n", hr);
2507 /* Create some surfaces to test stretchrect between the scenes */
2508 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2509 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface1, NULL);
2510 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2511 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
2512 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface2, NULL);
2513 ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2514 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 800, 600,
2515 D3DFMT_D16, D3DMULTISAMPLE_NONE, 0, FALSE, &surface3, NULL);
2516 ok(hr == D3D_OK, "IDirect3DDevice9_CreateDepthStencilSurface failed with %08x\n", hr);
2517 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128,
2518 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
2519 ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
2521 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
2522 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2523 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
2524 ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
2526 /* First make sure a simple StretchRect call works */
2527 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2528 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2529 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2530 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2531 if (0) /* Disabled for now because it crashes in wine */
2533 HRESULT expected = caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ? D3D_OK : D3DERR_INVALIDCALL;
2534 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2535 ok(hr == expected, "Got unexpected hr %#x, expected %#x.\n", hr, expected);
2538 /* Now try it in a BeginScene - EndScene pair. Seems to be allowed in a
2539 * BeginScene - Endscene pair with normal surfaces and render targets, but
2540 * not depth stencil surfaces. */
2541 hr = IDirect3DDevice9_BeginScene(device);
2542 ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2544 hr = IDirect3DDevice9_StretchRect(device, surface1, NULL, surface2, NULL, 0);
2545 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2546 hr = IDirect3DDevice9_StretchRect(device, backBuffer, &rect, rt, NULL, 0);
2547 ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2548 /* This is supposed to fail inside a BeginScene - EndScene pair. */
2549 hr = IDirect3DDevice9_StretchRect(device, ds, NULL, surface3, NULL, 0);
2550 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect returned %08x, expected D3DERR_INVALIDCALL\n", hr);
2552 hr = IDirect3DDevice9_EndScene(device);
2553 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2555 /* Does a SetRenderTarget influence BeginScene / EndScene ?
2556 * Set a new render target, then see if it started a new scene. Flip the rt back and see if that maybe
2557 * ended the scene. Expected result is that the scene is not affected by SetRenderTarget
2559 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
2560 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2561 hr = IDirect3DDevice9_BeginScene(device);
2562 ok( hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2563 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backBuffer);
2564 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
2565 hr = IDirect3DDevice9_EndScene(device);
2566 ok( hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2568 IDirect3DSurface9_Release(rt);
2569 IDirect3DSurface9_Release(ds);
2570 IDirect3DSurface9_Release(backBuffer);
2571 IDirect3DSurface9_Release(surface1);
2572 IDirect3DSurface9_Release(surface2);
2573 IDirect3DSurface9_Release(surface3);
2574 refcount = IDirect3DDevice9_Release(device);
2575 ok(!refcount, "Device has %u references left.\n", refcount);
2576 cleanup:
2577 IDirect3D9_Release(d3d);
2578 DestroyWindow(window);
2581 static void test_limits(void)
2583 IDirect3DTexture9 *texture;
2584 IDirect3DDevice9 *device;
2585 IDirect3D9 *d3d;
2586 unsigned int i;
2587 ULONG refcount;
2588 HWND window;
2589 HRESULT hr;
2591 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2592 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2593 ok(!!window, "Failed to create a window.\n");
2594 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2595 ok(!!d3d, "Failed to create a D3D object.\n");
2596 if (!(device = create_device(d3d, window, NULL)))
2598 skip("Failed to create a 3D device, skipping test.\n");
2599 goto cleanup;
2602 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
2603 ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2605 /* There are 16 pixel samplers. We should be able to access all of them */
2606 for (i = 0; i < 16; ++i)
2608 hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture);
2609 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2610 hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2611 ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture for sampler %d failed with %08x\n", i, hr);
2612 hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_SRGBTEXTURE, TRUE);
2613 ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState for sampler %d failed with %08x\n", i, hr);
2616 /* Now test all 8 textures stage states */
2617 for (i = 0; i < 8; ++i)
2619 hr = IDirect3DDevice9_SetTextureStageState(device, i, D3DTSS_COLOROP, D3DTOP_ADD);
2620 ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState for texture %d failed with %08x\n", i, hr);
2623 /* Investigations show that accessing higher samplers / textures stage
2624 * states does not return an error either. Writing to too high samplers
2625 * (approximately sampler 40) causes memory corruption in Windows, so
2626 * there is no bounds checking. */
2627 IDirect3DTexture9_Release(texture);
2628 refcount = IDirect3D9_Release(device);
2629 ok(!refcount, "Device has %u references left.\n", refcount);
2630 cleanup:
2631 IDirect3D9_Release(d3d);
2632 DestroyWindow(window);
2635 static void test_depthstenciltest(void)
2637 HRESULT hr;
2638 IDirect3DDevice9 *pDevice = NULL;
2639 D3DPRESENT_PARAMETERS d3dpp;
2640 D3DDISPLAYMODE d3ddm;
2641 IDirect3DSurface9 *pDepthStencil = NULL;
2642 IDirect3DSurface9 *pDepthStencil2 = NULL;
2643 IDirect3D9 *d3d;
2644 DWORD state;
2645 HWND hwnd;
2647 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2648 100, 100, 160, 160, NULL, NULL, NULL, NULL);
2649 ok(!!hwnd, "Failed to create a window.\n");
2650 d3d = Direct3DCreate9(D3D_SDK_VERSION);
2651 ok(!!d3d, "Failed to create a D3D object.\n");
2653 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
2654 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2655 d3dpp.Windowed = TRUE;
2656 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2657 d3dpp.BackBufferWidth = 800;
2658 d3dpp.BackBufferHeight = 600;
2659 d3dpp.BackBufferFormat = d3ddm.Format;
2660 d3dpp.EnableAutoDepthStencil = TRUE;
2661 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2663 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2664 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2665 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL), "IDirect3D9_CreateDevice failed with %08x\n", hr);
2666 if(!pDevice)
2668 skip("Failed to create a d3d device\n");
2669 goto cleanup;
2672 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2673 ok(hr == D3D_OK && pDepthStencil != NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2675 /* Try to clear */
2676 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2677 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2679 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, NULL);
2680 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2682 /* Check if the set buffer is returned on a get. WineD3D had a bug with that once, prevent it from coming back */
2683 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil2);
2684 ok(hr == D3DERR_NOTFOUND && pDepthStencil2 == NULL, "IDirect3DDevice9_GetDepthStencilSurface failed with %08x\n", hr);
2685 if(pDepthStencil2) IDirect3DSurface9_Release(pDepthStencil2);
2687 /* This left the render states untouched! */
2688 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2689 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2690 ok(state == D3DZB_TRUE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2691 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZWRITEENABLE, &state);
2692 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2693 ok(state == TRUE, "D3DRS_ZWRITEENABLE is %s\n", state ? "TRUE" : "FALSE");
2694 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILENABLE, &state);
2695 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2696 ok(state == FALSE, "D3DRS_STENCILENABLE is %s\n", state ? "TRUE" : "FALSE");
2697 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_STENCILWRITEMASK, &state);
2698 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2699 ok(state == 0xffffffff, "D3DRS_STENCILWRITEMASK is 0x%08x\n", state);
2701 /* This is supposed to fail now */
2702 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2703 ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2705 hr = IDirect3DDevice9_SetRenderState(pDevice, D3DRS_ZENABLE, D3DZB_FALSE);
2706 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
2708 hr = IDirect3DDevice9_SetDepthStencilSurface(pDevice, pDepthStencil);
2709 ok(hr == D3D_OK, "IDirect3DDevice9_SetDepthStencilSurface failed with %08x\n", hr);
2711 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2712 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2713 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2715 /* Now it works again */
2716 hr = IDirect3DDevice9_Clear(pDevice, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0, 0);
2717 ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2719 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2720 if(pDevice) IDirect3D9_Release(pDevice);
2722 /* Now see if autodepthstencil disable is honored. First, without a format set */
2723 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2724 d3dpp.Windowed = TRUE;
2725 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2726 d3dpp.BackBufferWidth = 800;
2727 d3dpp.BackBufferHeight = 600;
2728 d3dpp.BackBufferFormat = d3ddm.Format;
2729 d3dpp.EnableAutoDepthStencil = FALSE;
2730 d3dpp.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
2732 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2733 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2734 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2735 if(!pDevice)
2737 skip("Failed to create a d3d device\n");
2738 goto cleanup;
2741 pDepthStencil = NULL;
2742 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2743 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2744 if(pDepthStencil) {
2745 IDirect3DSurface9_Release(pDepthStencil);
2746 pDepthStencil = NULL;
2749 /* Check the depth test state */
2750 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2751 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2752 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2754 if(pDevice) IDirect3D9_Release(pDevice);
2756 /* Next, try EnableAutoDepthStencil FALSE with a depth stencil format set */
2757 ZeroMemory( &d3dpp, sizeof(d3dpp) );
2758 d3dpp.Windowed = TRUE;
2759 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
2760 d3dpp.BackBufferWidth = 800;
2761 d3dpp.BackBufferHeight = 600;
2762 d3dpp.BackBufferFormat = d3ddm.Format;
2763 d3dpp.EnableAutoDepthStencil = FALSE;
2764 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
2766 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */,
2767 hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
2768 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %08x\n", hr);
2769 if(!pDevice)
2771 skip("Failed to create a d3d device\n");
2772 goto cleanup;
2775 pDepthStencil = NULL;
2776 hr = IDirect3DDevice9_GetDepthStencilSurface(pDevice, &pDepthStencil);
2777 ok(hr == D3DERR_NOTFOUND && pDepthStencil == NULL, "IDirect3DDevice9_GetDepthStencilSurface returned %08x, surface = %p\n", hr, pDepthStencil);
2778 if(pDepthStencil) {
2779 IDirect3DSurface9_Release(pDepthStencil);
2780 pDepthStencil = NULL;
2783 hr = IDirect3DDevice9_GetRenderState(pDevice, D3DRS_ZENABLE, &state);
2784 ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
2785 ok(state == D3DZB_FALSE, "D3DRS_ZENABLE is %s\n", state == D3DZB_FALSE ? "D3DZB_FALSE" : (state == D3DZB_TRUE ? "D3DZB_TRUE" : "D3DZB_USEW"));
2787 cleanup:
2788 if(pDepthStencil) IDirect3DSurface9_Release(pDepthStencil);
2789 if (pDevice)
2791 UINT refcount = IDirect3D9_Release(pDevice);
2792 ok(!refcount, "Device has %u references left.\n", refcount);
2794 IDirect3D9_Release(d3d);
2795 DestroyWindow(hwnd);
2798 static void test_get_rt(void)
2800 IDirect3DSurface9 *backbuffer, *rt;
2801 IDirect3DDevice9 *device;
2802 IDirect3D9 *d3d9;
2803 D3DCAPS9 caps;
2804 HWND window;
2805 HRESULT hr;
2806 ULONG ref;
2807 UINT i;
2809 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2810 0, 0, 128, 128, 0, 0, 0, 0);
2811 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2812 ok(!!d3d9, "Failed to create a D3D object.\n");
2813 device = create_device(d3d9, window, NULL);
2814 if (!device)
2816 skip("Failed to create a D3D device, skipping tests.\n");
2817 goto done;
2820 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
2821 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
2822 ok(!!backbuffer, "Got a NULL backbuffer.\n");
2824 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2825 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2827 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
2829 rt = backbuffer;
2830 hr = IDirect3DDevice9_GetRenderTarget(device, i, &rt);
2831 ok(hr == D3DERR_NOTFOUND, "IDirect3DDevice9_GetRenderTarget returned %#x.\n", hr);
2832 ok(!rt, "Got rt %p.\n", rt);
2835 IDirect3DSurface9_Release(backbuffer);
2837 ref = IDirect3DDevice9_Release(device);
2838 ok(!ref, "The device was not properly freed: refcount %u.\n", ref);
2839 done:
2840 IDirect3D9_Release(d3d9);
2841 DestroyWindow(window);
2844 static void test_draw_primitive(void)
2846 static const struct
2848 float position[3];
2849 DWORD color;
2851 quad[] =
2853 {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
2854 {{-1.0f, 1.0f, 0.0f}, 0xffff0000},
2855 {{ 1.0f, 1.0f, 0.0f}, 0xffff0000},
2856 {{ 1.0f, -1.0f, 0.0f}, 0xffff0000},
2858 static const WORD indices[] = {0, 1, 2, 3, 0, 2};
2859 static const D3DVERTEXELEMENT9 decl_elements[] =
2861 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2862 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
2863 D3DDECL_END()
2866 IDirect3DVertexDeclaration9 *vertex_declaration;
2867 IDirect3DVertexBuffer9 *vertex_buffer;
2868 IDirect3DIndexBuffer9 *index_buffer;
2869 IDirect3DDevice9 *device;
2870 IDirect3D9 *d3d9;
2871 ULONG refcount;
2872 HWND window;
2873 HRESULT hr;
2874 void *ptr;
2876 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
2877 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2878 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
2879 ok(!!d3d9, "Failed to create a D3D object.\n");
2880 if (!(device = create_device(d3d9, window, NULL)))
2882 skip("Failed to create a D3D device.\n");
2883 IDirect3D9_Release(d3d9);
2884 DestroyWindow(window);
2885 return;
2888 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
2889 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
2891 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
2892 D3DPOOL_DEFAULT, &vertex_buffer, NULL);
2893 ok(SUCCEEDED(hr), "CreateVertexBuffer failed, hr %#x.\n", hr);
2894 hr = IDirect3DVertexBuffer9_Lock(vertex_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2895 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2896 memcpy(ptr, quad, sizeof(quad));
2897 hr = IDirect3DVertexBuffer9_Unlock(vertex_buffer);
2898 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2899 hr = IDirect3DDevice9_SetStreamSource(device, 0, vertex_buffer, 0, sizeof(*quad));
2900 ok(SUCCEEDED(hr), "SetStreamSource failed, hr %#x.\n", hr);
2902 hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16,
2903 D3DPOOL_DEFAULT, &index_buffer, NULL);
2904 ok(SUCCEEDED(hr), "CreateIndexBuffer failed, hr %#x.\n", hr);
2905 hr = IDirect3DIndexBuffer9_Lock(index_buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
2906 ok(SUCCEEDED(hr), "Lock failed, hr %#x.\n", hr);
2907 memcpy(ptr, indices, sizeof(indices));
2908 hr = IDirect3DIndexBuffer9_Unlock(index_buffer);
2909 ok(SUCCEEDED(hr), "Unlock failed, hr %#x.\n", hr);
2911 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2912 ok(SUCCEEDED(hr), "SetRenderState D3DRS_LIGHTING failed, hr %#x.\n", hr);
2914 hr = IDirect3DDevice9_BeginScene(device);
2915 ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2917 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2918 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2920 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2921 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2923 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2924 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2926 hr = IDirect3DDevice9_SetIndices(device, NULL);
2927 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2928 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2929 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2930 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2932 /* Valid index buffer, NULL vertex declaration. Should fail */
2933 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2934 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2935 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2936 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2937 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2939 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2940 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2941 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2943 hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2944 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
2946 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
2947 ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2949 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 2, quad, sizeof(*quad));
2950 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2952 /* NULL index buffer, valid vertex vertex declaration. Should succeed */
2953 hr = IDirect3DDevice9_SetIndices(device, NULL);
2954 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2955 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2956 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2957 todo_wine ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2959 /* Valid index buffer and vertex declaration. Should succeed */
2960 hr = IDirect3DDevice9_SetIndices(device, index_buffer);
2961 ok(SUCCEEDED(hr), "SetIndices failed, hr %#x.\n", hr);
2962 hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0 /* BaseVertexIndex */,
2963 0 /* MinIndex */, 4 /* NumVerts */, 0 /* StartIndex */, 2 /*PrimCount */);
2964 ok(SUCCEEDED(hr), "DrawIndexedPrimitive failed, hr %#x.\n", hr);
2966 hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4, 2,
2967 indices, D3DFMT_INDEX16, quad, sizeof(*quad));
2968 ok(SUCCEEDED(hr), "DrawIndexedPrimitiveUP failed, hr %#x.\n", hr);
2970 hr = IDirect3DDevice9_EndScene(device);
2971 ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2973 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2974 ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2976 IDirect3DVertexBuffer9_Release(vertex_buffer);
2977 IDirect3DIndexBuffer9_Release(index_buffer);
2978 IDirect3DVertexDeclaration9_Release(vertex_declaration);
2979 refcount = IDirect3DDevice9_Release(device);
2980 ok(!refcount, "Device has %u references left.\n", refcount);
2981 IDirect3D9_Release(d3d9);
2982 DestroyWindow(window);
2985 static void test_null_stream(void)
2987 IDirect3DVertexBuffer9 *buffer = NULL;
2988 IDirect3DDevice9 *device;
2989 IDirect3D9 *d3d9;
2990 ULONG refcount;
2991 HWND window;
2992 HRESULT hr;
2993 IDirect3DVertexShader9 *shader = NULL;
2994 IDirect3DVertexDeclaration9 *decl = NULL;
2995 static const DWORD shader_code[] =
2997 0xfffe0101, /* vs_1_1 */
2998 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2999 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
3000 0x0000ffff /* end */
3002 static const D3DVERTEXELEMENT9 decl_elements[] = {
3003 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3004 {1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3005 D3DDECL_END()
3008 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3009 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3010 ok(!!window, "Failed to create a window.\n");
3011 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3012 ok(!!d3d9, "Failed to create a D3D object.\n");
3013 if (!(device = create_device(d3d9, window, NULL)))
3015 skip("Failed to create a 3D device, skipping test.\n");
3016 goto cleanup;
3019 hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
3020 if(FAILED(hr)) {
3021 skip("No vertex shader support\n");
3022 goto cleanup;
3024 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3025 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed (0x%08x)\n", hr);
3026 if (FAILED(hr)) {
3027 skip("Vertex declaration handling not possible.\n");
3028 goto cleanup;
3030 hr = IDirect3DDevice9_CreateVertexBuffer(device, 12 * sizeof(float), 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
3031 ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexBuffer failed (0x%08x)\n", hr);
3032 if (FAILED(hr)) {
3033 skip("Vertex buffer handling not possible.\n");
3034 goto cleanup;
3037 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(float) * 3);
3038 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3039 hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
3040 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetStreamSource failed (0x%08x)\n", hr);
3041 hr = IDirect3DDevice9_SetVertexShader(device, shader);
3042 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed (0x%08x)\n", hr);
3043 hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3044 ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexDeclaration failed (0x%08x)\n", hr);
3046 hr = IDirect3DDevice9_BeginScene(device);
3047 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3048 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_POINTLIST, 0, 1);
3049 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3050 hr = IDirect3DDevice9_EndScene(device);
3051 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3053 IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3054 IDirect3DDevice9_SetVertexShader(device, NULL);
3055 IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3057 cleanup:
3058 if (buffer) IDirect3DVertexBuffer9_Release(buffer);
3059 if (decl) IDirect3DVertexDeclaration9_Release(decl);
3060 if (shader) IDirect3DVertexShader9_Release(shader);
3061 if (device)
3063 refcount = IDirect3DDevice9_Release(device);
3064 ok(!refcount, "Device has %u references left.\n", refcount);
3066 IDirect3D9_Release(d3d9);
3067 DestroyWindow(window);
3070 static void test_lights(void)
3072 IDirect3DDevice9 *device;
3073 IDirect3D9 *d3d9;
3074 ULONG refcount;
3075 HWND window;
3076 HRESULT hr;
3077 unsigned int i;
3078 BOOL enabled;
3079 D3DCAPS9 caps;
3081 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3082 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3083 ok(!!window, "Failed to create a window.\n");
3084 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3085 ok(!!d3d9, "Failed to create a D3D object.\n");
3086 if (!(device = create_device(d3d9, window, NULL)))
3088 skip("Failed to create a 3D device, skipping test.\n");
3089 goto cleanup;
3092 memset(&caps, 0, sizeof(caps));
3093 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3094 ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
3096 for(i = 1; i <= caps.MaxActiveLights; i++) {
3097 hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
3098 ok(hr == D3D_OK, "Enabling light %u failed with %08x\n", i, hr);
3099 hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
3100 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i, hr);
3101 ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
3104 /* TODO: Test the rendering results in this situation */
3105 hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
3106 ok(hr == D3D_OK, "Enabling one light more than supported returned %08x\n", hr);
3107 hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
3108 ok(hr == D3D_OK, "GetLightEnable on light %u failed with %08x\n", i + 1, hr);
3109 ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
3110 hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
3111 ok(hr == D3D_OK, "Disabling the additional returned %08x\n", hr);
3113 for(i = 1; i <= caps.MaxActiveLights; i++) {
3114 hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
3115 ok(hr == D3D_OK, "Disabling light %u failed with %08x\n", i, hr);
3118 refcount = IDirect3DDevice9_Release(device);
3119 ok(!refcount, "Device has %u references left.\n", refcount);
3120 cleanup:
3121 IDirect3D9_Release(d3d9);
3122 DestroyWindow(window);
3125 static void test_set_stream_source(void)
3127 IDirect3DVertexBuffer9 *vb;
3128 IDirect3DDevice9 *device;
3129 IDirect3D9 *d3d9;
3130 ULONG refcount;
3131 HWND window;
3132 HRESULT hr;
3134 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3135 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3136 ok(!!window, "Failed to create a window.\n");
3137 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3138 ok(!!d3d9, "Failed to create a D3D object.\n");
3139 if (!(device = create_device(d3d9, window, NULL)))
3141 skip("Failed to create a 3D device, skipping test.\n");
3142 goto cleanup;
3145 hr = IDirect3DDevice9_CreateVertexBuffer(device, 512, 0, 0, D3DPOOL_DEFAULT, &vb, NULL);
3146 ok(SUCCEEDED(hr), "Failed to create a vertex buffer, hr %#x.\n", hr);
3148 /* Some cards (GeForce 7400 at least) accept non-aligned offsets, others
3149 * (Radeon 9000 verified) reject them, so accept both results. Wine
3150 * currently rejects this to be able to optimize the vbo conversion, but
3151 * writes a WARN. */
3152 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, 32);
3153 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3154 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 1, 32);
3155 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3156 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 2, 32);
3157 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3158 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 3, 32);
3159 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3160 hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 4, 32);
3161 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3163 /* Try to set the NULL buffer with an offset and stride 0 */
3164 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3165 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3166 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 1, 0);
3167 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3168 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 2, 0);
3169 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3170 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 3, 0);
3171 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
3172 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 4, 0);
3173 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3175 hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3176 ok(SUCCEEDED(hr), "Failed to set the stream source, hr %#x.\n", hr);
3178 IDirect3DVertexBuffer9_Release(vb);
3179 refcount = IDirect3DDevice9_Release(device);
3180 ok(!refcount, "Device has %u references left.\n", refcount);
3181 cleanup:
3182 IDirect3D9_Release(d3d9);
3183 DestroyWindow(window);
3186 /* Direct3D9 offers 4 display formats: R5G6B5, X1R5G5B5, X8R8G8B8 and
3187 * A2R10G10B10. Next to these there are 6 different back buffer formats. Only
3188 * a fixed number of combinations are possible in fullscreen mode. In windowed
3189 * mode more combinations are allowed due to format conversion and this is
3190 * likely driver dependent. */
3191 static void test_display_formats(void)
3193 D3DDEVTYPE device_type = D3DDEVTYPE_HAL;
3194 unsigned int backbuffer, display;
3195 unsigned int windowed;
3196 IDirect3D9 *d3d9;
3197 BOOL should_pass;
3198 BOOL has_modes;
3199 HRESULT hr;
3201 static const struct
3203 const char *name;
3204 D3DFORMAT format;
3205 D3DFORMAT alpha_format;
3206 BOOL display;
3207 BOOL windowed;
3209 formats[] =
3211 {"D3DFMT_R5G6B5", D3DFMT_R5G6B5, 0, TRUE, TRUE},
3212 {"D3DFMT_X1R5G5B5", D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5, TRUE, TRUE},
3213 {"D3DFMT_A1R5G5B5", D3DFMT_A1R5G5B5, D3DFMT_A1R5G5B5, FALSE, FALSE},
3214 {"D3DFMT_X8R8G8B8", D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8, TRUE, TRUE},
3215 {"D3DFMT_A8R8G8B8", D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE, FALSE},
3216 {"D3DFMT_A2R10G10B10", D3DFMT_A2R10G10B10, 0, TRUE, FALSE},
3217 {"D3DFMT_UNKNOWN", D3DFMT_UNKNOWN, 0, FALSE, FALSE},
3220 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3221 ok(!!d3d9, "Failed to create a D3D object.\n");
3223 for (display = 0; display < ARRAY_SIZE(formats); ++display)
3225 has_modes = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, formats[display].format);
3227 for (windowed = 0; windowed <= 1; ++windowed)
3229 for (backbuffer = 0; backbuffer < ARRAY_SIZE(formats); ++backbuffer)
3231 should_pass = FALSE;
3233 if (formats[display].display && (formats[display].windowed || !windowed) && (has_modes || windowed))
3235 D3DFORMAT backbuffer_format;
3237 if (windowed && formats[backbuffer].format == D3DFMT_UNKNOWN)
3238 backbuffer_format = formats[display].format;
3239 else
3240 backbuffer_format = formats[backbuffer].format;
3242 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, device_type, formats[display].format,
3243 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, backbuffer_format);
3244 if (hr == D3D_OK)
3246 if (windowed)
3248 hr = IDirect3D9_CheckDeviceFormatConversion(d3d9, D3DADAPTER_DEFAULT, device_type,
3249 backbuffer_format, formats[display].format);
3250 should_pass = (hr == D3D_OK);
3252 else
3253 should_pass = (formats[display].format == formats[backbuffer].format
3254 || (formats[display].alpha_format
3255 && formats[display].alpha_format == formats[backbuffer].alpha_format));
3259 hr = IDirect3D9_CheckDeviceType(d3d9, D3DADAPTER_DEFAULT, device_type,
3260 formats[display].format, formats[backbuffer].format, windowed);
3261 ok(SUCCEEDED(hr) == should_pass || broken(SUCCEEDED(hr) && !has_modes) /* Win8 64-bit */,
3262 "Got unexpected hr %#x for %s / %s, windowed %#x, should_pass %#x.\n",
3263 hr, formats[display].name, formats[backbuffer].name, windowed, should_pass);
3268 IDirect3D9_Release(d3d9);
3271 static void test_scissor_size(void)
3273 struct device_desc device_desc;
3274 IDirect3D9 *d3d9_ptr;
3275 unsigned int i;
3276 static struct {
3277 int winx; int winy; int backx; int backy; DWORD flags;
3278 } scts[] = { /* scissor tests */
3279 {800, 600, 640, 480, 0},
3280 {800, 600, 640, 480, CREATE_DEVICE_FULLSCREEN},
3281 {640, 480, 800, 600, 0},
3282 {640, 480, 800, 600, CREATE_DEVICE_FULLSCREEN},
3285 d3d9_ptr = Direct3DCreate9(D3D_SDK_VERSION);
3286 ok(!!d3d9_ptr, "Failed to create a D3D object.\n");
3288 for (i = 0; i < ARRAY_SIZE(scts); i++)
3290 IDirect3DDevice9 *device_ptr = 0;
3291 HRESULT hr;
3292 HWND hwnd = 0;
3293 RECT scissorrect;
3295 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
3296 0, 0, scts[i].winx, scts[i].winy, 0, 0, 0, 0);
3298 if (scts[i].flags & CREATE_DEVICE_FULLSCREEN)
3300 scts[i].backx = registry_mode.dmPelsWidth;
3301 scts[i].backy = registry_mode.dmPelsHeight;
3304 device_desc.device_window = hwnd;
3305 device_desc.width = scts[i].backx;
3306 device_desc.height = scts[i].backy;
3307 device_desc.flags = scts[i].flags;
3308 if (!(device_ptr = create_device(d3d9_ptr, hwnd, &device_desc)))
3310 skip("Failed to create a 3D device, skipping test.\n");
3311 DestroyWindow(hwnd);
3312 goto err_out;
3315 /* Check for the default scissor rect size */
3316 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3317 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3318 ok(scissorrect.right == scts[i].backx && scissorrect.bottom == scts[i].backy
3319 && scissorrect.top == 0 && scissorrect.left == 0,
3320 "Scissorrect mismatch (%d, %d) should be (%d, %d)\n", scissorrect.right, scissorrect.bottom,
3321 scts[i].backx, scts[i].backy);
3323 /* check the scissorrect values after a reset */
3324 device_desc.width = registry_mode.dmPelsWidth;
3325 device_desc.height = registry_mode.dmPelsHeight;
3326 device_desc.flags = scts[i].flags;
3327 hr = reset_device(device_ptr, &device_desc);
3328 ok(hr == D3D_OK, "IDirect3DDevice9_Reset failed with %08x\n", hr);
3329 hr = IDirect3DDevice9_TestCooperativeLevel(device_ptr);
3330 ok(hr == D3D_OK, "IDirect3DDevice9_TestCooperativeLevel after a successful reset returned %#x\n", hr);
3332 hr = IDirect3DDevice9_GetScissorRect(device_ptr, &scissorrect);
3333 ok(hr == D3D_OK, "IDirect3DDevice9_GetScissorRect failed with: %08x\n", hr);
3334 ok(scissorrect.right == registry_mode.dmPelsWidth && scissorrect.bottom == registry_mode.dmPelsHeight
3335 && scissorrect.top == 0 && scissorrect.left == 0,
3336 "Scissorrect mismatch (%d, %d) should be (%u, %u)\n", scissorrect.right, scissorrect.bottom,
3337 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3339 if (device_ptr)
3341 ULONG ref;
3343 ref = IDirect3DDevice9_Release(device_ptr);
3344 DestroyWindow(hwnd);
3345 ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
3349 err_out:
3350 IDirect3D9_Release(d3d9_ptr);
3353 static void test_multi_device(void)
3355 IDirect3DDevice9 *device1, *device2;
3356 HWND window1, window2;
3357 IDirect3D9 *d3d9;
3358 ULONG refcount;
3360 window1 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3361 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3362 ok(!!window1, "Failed to create a window.\n");
3363 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3364 ok(!!d3d9, "Failed to create a D3D object.\n");
3365 if (!(device1 = create_device(d3d9, window1, NULL)))
3367 skip("Failed to create a 3D device, skipping test.\n");
3368 IDirect3D9_Release(d3d9);
3369 DestroyWindow(window1);
3370 return;
3372 IDirect3D9_Release(d3d9);
3374 window2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
3375 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3376 ok(!!window2, "Failed to create a window.\n");
3377 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3378 ok(!!d3d9, "Failed to create a D3D object.\n");
3379 device2 = create_device(d3d9, window2, NULL);
3380 IDirect3D9_Release(d3d9);
3382 refcount = IDirect3DDevice9_Release(device2);
3383 ok(!refcount, "Device has %u references left.\n", refcount);
3384 refcount = IDirect3DDevice9_Release(device1);
3385 ok(!refcount, "Device has %u references left.\n", refcount);
3386 DestroyWindow(window2);
3387 DestroyWindow(window1);
3390 static HWND filter_messages;
3392 enum message_window
3394 DEVICE_WINDOW,
3395 FOCUS_WINDOW,
3398 struct message
3400 UINT message;
3401 enum message_window window;
3402 BOOL check_wparam;
3403 WPARAM expect_wparam;
3404 WINDOWPOS *store_wp;
3407 static const struct message *expect_messages;
3408 static HWND device_window, focus_window;
3409 static LONG windowposchanged_received, syscommand_received, wm_size_received;
3411 struct wndproc_thread_param
3413 HWND dummy_window;
3414 HANDLE window_created;
3415 HANDLE test_finished;
3416 BOOL running_in_foreground;
3419 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
3421 if (filter_messages && filter_messages == hwnd)
3423 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
3424 todo_wine ok( 0, "Received unexpected message %#x for window %p.\n", message, hwnd);
3427 if (expect_messages)
3429 HWND w;
3431 switch (expect_messages->window)
3433 case DEVICE_WINDOW:
3434 w = device_window;
3435 break;
3437 case FOCUS_WINDOW:
3438 w = focus_window;
3439 break;
3441 default:
3442 w = NULL;
3443 break;
3446 if (hwnd == w && expect_messages->message == message)
3448 if (expect_messages->check_wparam)
3449 ok(wparam == expect_messages->expect_wparam,
3450 "Got unexpected wparam %lx for message %x, expected %lx.\n",
3451 wparam, message, expect_messages->expect_wparam);
3453 if (expect_messages->store_wp)
3454 *expect_messages->store_wp = *(WINDOWPOS *)lparam;
3456 ++expect_messages;
3460 /* KDE randomly does something with the hidden window during the
3461 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
3462 * message. A WM_WINDOWPOSCHANGED message is not generated, so
3463 * just flag WM_WINDOWPOSCHANGED as bad. */
3464 if (message == WM_WINDOWPOSCHANGED)
3465 InterlockedIncrement(&windowposchanged_received);
3466 else if (message == WM_SYSCOMMAND)
3467 InterlockedIncrement(&syscommand_received);
3468 else if (message == WM_SIZE)
3469 InterlockedIncrement(&wm_size_received);
3471 return DefWindowProcA(hwnd, message, wparam, lparam);
3474 static DWORD WINAPI wndproc_thread(void *param)
3476 struct wndproc_thread_param *p = param;
3477 DWORD res;
3478 BOOL ret;
3480 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3481 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3482 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3483 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
3485 ret = SetEvent(p->window_created);
3486 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3488 for (;;)
3490 MSG msg;
3492 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3493 res = WaitForSingleObject(p->test_finished, 100);
3494 if (res == WAIT_OBJECT_0) break;
3495 if (res != WAIT_TIMEOUT)
3497 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3498 break;
3502 DestroyWindow(p->dummy_window);
3504 return 0;
3507 static void test_wndproc(void)
3509 struct wndproc_thread_param thread_params;
3510 struct device_desc device_desc;
3511 IDirect3DDevice9 *device;
3512 WNDCLASSA wc = {0};
3513 IDirect3D9 *d3d9;
3514 HANDLE thread;
3515 LONG_PTR proc;
3516 ULONG ref;
3517 DWORD res, tid;
3518 HWND tmp;
3519 UINT i, adapter_mode_count;
3520 HRESULT hr;
3521 D3DDISPLAYMODE d3ddm;
3522 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
3523 DEVMODEW devmode;
3524 LONG change_ret, device_style;
3525 BOOL ret;
3526 WINDOWPOS windowpos;
3528 static const struct message create_messages[] =
3530 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3531 /* Do not test wparam here. If device creation succeeds,
3532 * wparam is WA_ACTIVE. If device creation fails (testbot)
3533 * wparam is set to WA_INACTIVE on some Windows versions. */
3534 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
3535 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
3536 {0, 0, FALSE, 0},
3538 static const struct message focus_loss_messages[] =
3540 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3541 * not reliable on X11 WMs. When the window focus follows the
3542 * mouse pointer the message is not sent.
3543 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3544 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3545 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3546 * not deterministic. */
3547 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3548 /* Windows sends WM_ACTIVATE to the device window, indicating that
3549 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
3550 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
3551 * leaves the device window active, breaking re-activation in the
3552 * lost device test.
3553 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
3554 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3555 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
3556 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3557 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
3558 * not deterministic. It may be sent after the focus window handling
3559 * or before. */
3560 {0, 0, FALSE, 0},
3562 static const struct message focus_loss_messages_nowc[] =
3564 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
3565 * not reliable on X11 WMs. When the window focus follows the
3566 * mouse pointer the message is not sent.
3567 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
3568 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3569 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3570 {0, 0, FALSE, 0},
3572 static const struct message reactivate_messages[] =
3574 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3575 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3576 /* optional WM_MOVE here if size changed */
3577 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3578 {0, 0, FALSE, 0},
3580 static const struct message reactivate_messages_nowc[] =
3582 /* We're activating the device window before activating the
3583 * focus window, so no ACTIVATEAPP message is sent. */
3584 {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_ACTIVE},
3585 {0, 0, FALSE, 0},
3587 static const struct message focus_loss_messages_hidden[] =
3589 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
3590 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3591 {0, 0, FALSE, 0},
3593 static const struct message focus_loss_messages_filtered[] =
3595 /* WM_ACTIVATE is delivered to the window proc because it is
3596 * generated by SetForegroundWindow before the d3d routine
3597 * starts it work. Don't check for it due to focus-follows-mouse
3598 * WMs though. */
3599 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3600 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
3601 {0, 0, FALSE, 0},
3603 static const struct message reactivate_messages_filtered[] =
3605 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, TRUE},
3606 {0, 0, FALSE, 0},
3608 static const struct message sc_restore_messages[] =
3610 /* WM_SYSCOMMAND is delivered only once, after d3d has already
3611 * processed it. Our wndproc has no way to prevent d3d from
3612 * handling the message. The second DefWindowProc call done by
3613 * our wndproc doesn't do any changes to the window because it
3614 * is already restored due to d3d's handling. */
3615 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3616 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3617 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
3618 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
3619 {0, 0, FALSE, 0},
3621 static const struct message sc_minimize_messages[] =
3623 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
3624 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3625 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3626 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3627 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
3628 {0, 0, FALSE, 0},
3630 static const struct message sc_maximize_messages[] =
3632 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
3633 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
3634 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
3635 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
3636 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
3637 {0, 0, FALSE, 0},
3639 struct message mode_change_messages[] =
3641 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3642 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3643 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3644 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3645 * differs between Wine and Windows. */
3646 /* TODO 2: Windows sends a second WM_WINDOWPOSCHANGING(SWP_NOMOVE | SWP_NOSIZE
3647 * | SWP_NOACTIVATE) in this situation, suggesting a difference in their ShowWindow
3648 * implementation. This SetWindowPos call could in theory affect the Z order. Wine's
3649 * ShowWindow does not send such a message because the window is already visible. */
3650 {0, 0, FALSE, 0},
3652 struct message mode_change_messages_hidden[] =
3654 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
3655 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3656 {WM_SIZE, DEVICE_WINDOW, FALSE, 0},
3657 {WM_SHOWWINDOW, DEVICE_WINDOW, FALSE, 0},
3658 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0, &windowpos},
3659 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
3660 /* TODO: WM_DISPLAYCHANGE is sent to the focus window too, but the order is
3661 * differs between Wine and Windows. */
3662 {0, 0, FALSE, 0},
3664 static const struct message mode_change_messages_nowc[] =
3666 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
3667 {0, 0, FALSE, 0},
3669 struct
3671 DWORD create_flags;
3672 const struct message *focus_loss_messages, *reactivate_messages;
3673 const struct message *mode_change_messages, *mode_change_messages_hidden;
3674 BOOL iconic;
3676 tests[] =
3680 focus_loss_messages,
3681 reactivate_messages,
3682 mode_change_messages,
3683 mode_change_messages_hidden,
3684 TRUE
3687 CREATE_DEVICE_NOWINDOWCHANGES,
3688 focus_loss_messages_nowc,
3689 reactivate_messages_nowc,
3690 mode_change_messages_nowc,
3691 mode_change_messages_nowc,
3692 FALSE
3696 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
3697 ok(!!d3d9, "Failed to create a D3D object.\n");
3699 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
3700 for (i = 0; i < adapter_mode_count; ++i)
3702 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
3703 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
3705 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
3706 continue;
3707 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
3708 * refuses to create a device at these sizes. */
3709 if (d3ddm.Width < 640 || d3ddm.Height < 480)
3710 continue;
3712 if (!user32_width)
3714 user32_width = d3ddm.Width;
3715 user32_height = d3ddm.Height;
3716 continue;
3719 /* Make sure the d3d mode is smaller in width or height and at most
3720 * equal in the other dimension than the mode passed to
3721 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
3722 * the ChangeDisplaySettings parameters + 12. */
3723 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
3724 continue;
3725 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
3727 d3d_width = d3ddm.Width;
3728 d3d_height = d3ddm.Height;
3729 break;
3731 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
3733 d3d_width = user32_width;
3734 d3d_height = user32_height;
3735 user32_width = d3ddm.Width;
3736 user32_height = d3ddm.Height;
3737 break;
3741 if (!d3d_width)
3743 skip("Could not find adequate modes, skipping mode tests.\n");
3744 IDirect3D9_Release(d3d9);
3745 return;
3748 wc.lpfnWndProc = test_proc;
3749 wc.lpszClassName = "d3d9_test_wndproc_wc";
3750 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3752 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3753 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3754 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3755 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3757 memset(&devmode, 0, sizeof(devmode));
3758 devmode.dmSize = sizeof(devmode);
3759 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3761 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3762 devmode.dmPelsWidth = user32_width;
3763 devmode.dmPelsHeight = user32_height;
3764 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3765 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3767 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3768 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3769 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3770 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
3771 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3772 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3774 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3775 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3777 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3778 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3779 (LONG_PTR)test_proc, proc);
3780 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3781 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3782 (LONG_PTR)test_proc, proc);
3784 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3785 device_window, focus_window, thread_params.dummy_window);
3787 tmp = GetFocus();
3788 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3789 if (thread_params.running_in_foreground)
3791 tmp = GetForegroundWindow();
3792 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3793 thread_params.dummy_window, tmp);
3795 else
3796 skip("Not running in foreground, skip foreground window test\n");
3798 flush_events();
3800 expect_messages = create_messages;
3802 device_desc.device_window = device_window;
3803 device_desc.width = d3d_width;
3804 device_desc.height = d3d_height;
3805 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
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 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3813 expect_messages->message, expect_messages->window, i);
3814 expect_messages = NULL;
3816 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
3818 tmp = GetFocus();
3819 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
3820 tmp = GetForegroundWindow();
3821 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
3823 SetForegroundWindow(focus_window);
3824 flush_events();
3826 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3827 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3828 (LONG_PTR)test_proc, proc, i);
3830 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3831 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
3832 (LONG_PTR)test_proc, i);
3834 /* Change the mode while the device is in use and then drop focus. */
3835 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
3836 devmode.dmPelsWidth = user32_width;
3837 devmode.dmPelsHeight = user32_height;
3838 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
3839 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
3841 /* Wine doesn't (yet) mark the device not reset when the mode is changed, thus the todo_wine.
3842 * But sometimes focus-follows-mouse WMs also temporarily drop window focus, which makes
3843 * mark the device lost, then not reset, causing the test to succeed for the wrong reason. */
3844 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3845 todo_wine_if (hr != D3DERR_DEVICENOTRESET)
3846 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3848 expect_messages = tests[i].focus_loss_messages;
3849 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
3850 * manually changing the focus. It generates the same messages, but the task
3851 * bar still shows the previous foreground window as active, and the window has
3852 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
3853 * the device is difficult, see below. */
3854 SetForegroundWindow(GetDesktopWindow());
3855 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3856 expect_messages->message, expect_messages->window, i);
3857 expect_messages = NULL;
3858 tmp = GetFocus();
3859 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
3860 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
3862 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3863 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
3865 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3866 ok(ret, "Failed to get display mode.\n");
3867 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3868 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3869 devmode.dmPelsWidth, devmode.dmPelsHeight);
3871 /* This is needed on native with D3DCREATE_NOWINDOWCHANGES, and it needs to be
3872 * done before the focus window is restored. This makes sense to some extent
3873 * because minimizing the window on focus loss is the application's job if this
3874 * flag is set. */
3875 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3877 ShowWindow(device_window, SW_MINIMIZE);
3878 ShowWindow(device_window, SW_RESTORE);
3880 flush_events();
3882 /* I have to minimize and restore the focus window, otherwise native d3d9 fails
3883 * device::reset with D3DERR_DEVICELOST. This does not happen when the window
3884 * restore is triggered by the user. */
3885 expect_messages = tests[i].reactivate_messages;
3886 ShowWindow(focus_window, SW_MINIMIZE);
3887 ShowWindow(focus_window, SW_RESTORE);
3888 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
3889 SetForegroundWindow(focus_window);
3890 flush_events();
3891 SetForegroundWindow(focus_window);
3892 flush_events(); /* WM_WINDOWPOSCHANGING etc arrive after SetForegroundWindow returns. */
3893 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3894 expect_messages->message, expect_messages->window, i);
3895 expect_messages = NULL;
3897 hr = IDirect3DDevice9_TestCooperativeLevel(device);
3898 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
3900 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3901 ok(ret, "Failed to get display mode.\n");
3902 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
3903 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
3904 devmode.dmPelsWidth, devmode.dmPelsHeight);
3906 hr = reset_device(device, &device_desc);
3907 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3909 /* Remove the WS_VISIBLE flag to test hidden windows. This is enough to trigger d3d's hidden
3910 * window codepath, but does not actually hide the window without a SetWindowPos(SWP_FRAMECHANGED)
3911 * call. This way we avoid focus changes and random failures on focus follows mouse WMs. */
3912 device_style = GetWindowLongA(device_window, GWL_STYLE);
3913 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
3914 flush_events();
3916 expect_messages = focus_loss_messages_hidden;
3917 windowposchanged_received = 0;
3918 SetForegroundWindow(GetDesktopWindow());
3919 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3920 expect_messages->message, expect_messages->window, i);
3921 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3922 expect_messages = NULL;
3923 flush_events();
3925 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3926 ok(ret, "Failed to get display mode.\n");
3927 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3928 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3930 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3931 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3932 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3933 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3934 flush_events();
3936 syscommand_received = 0;
3937 expect_messages = sc_restore_messages;
3938 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3939 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3940 expect_messages->message, expect_messages->window, i);
3941 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3942 expect_messages = NULL;
3943 flush_events();
3945 expect_messages = sc_minimize_messages;
3946 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3947 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3948 expect_messages->message, expect_messages->window, i);
3949 expect_messages = NULL;
3950 flush_events();
3952 expect_messages = sc_maximize_messages;
3953 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3954 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3955 expect_messages->message, expect_messages->window, i);
3956 expect_messages = NULL;
3957 flush_events();
3959 SetForegroundWindow(GetDesktopWindow());
3960 ShowWindow(device_window, SW_MINIMIZE);
3961 ShowWindow(device_window, SW_RESTORE);
3962 ShowWindow(focus_window, SW_MINIMIZE);
3963 ShowWindow(focus_window, SW_RESTORE);
3964 SetForegroundWindow(focus_window);
3965 flush_events();
3967 /* Releasing a device in lost state breaks follow-up tests on native. */
3968 hr = reset_device(device, &device_desc);
3969 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3971 filter_messages = focus_window;
3973 ref = IDirect3DDevice9_Release(device);
3974 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3976 /* Fix up the mode until Wine's device release behavior is fixed. */
3977 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3978 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3980 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3981 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3982 (LONG_PTR)test_proc, proc, i);
3984 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3985 * on native in the test below. It isn't needed anyways. Creating the third
3986 * device will show it again. */
3987 filter_messages = NULL;
3988 ShowWindow(device_window, SW_HIDE);
3989 /* Remove the maximized state from the SYSCOMMAND test while we're not
3990 * interfering with a device. */
3991 ShowWindow(focus_window, SW_SHOWNORMAL);
3992 filter_messages = focus_window;
3994 device_desc.device_window = focus_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;
4000 filter_messages = NULL;
4001 SetForegroundWindow(focus_window); /* For KDE. */
4002 flush_events();
4004 expect_messages = focus_loss_messages_filtered;
4005 windowposchanged_received = 0;
4006 SetForegroundWindow(GetDesktopWindow());
4007 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4008 expect_messages->message, expect_messages->window, i);
4009 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4010 expect_messages = NULL;
4012 /* The window is iconic even though no message was sent. */
4013 ok(!IsIconic(focus_window) == !tests[i].iconic,
4014 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
4016 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4017 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
4019 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4020 ShowWindow(focus_window, SW_MINIMIZE);
4022 syscommand_received = 0;
4023 expect_messages = sc_restore_messages;
4024 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
4025 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4026 expect_messages->message, expect_messages->window, i);
4027 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
4028 expect_messages = NULL;
4029 flush_events();
4031 /* For FVWM. */
4032 ShowWindow(focus_window, SW_RESTORE);
4033 flush_events();
4035 expect_messages = sc_minimize_messages;
4036 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
4037 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4038 expect_messages->message, expect_messages->window, i);
4039 expect_messages = NULL;
4040 flush_events();
4042 expect_messages = sc_maximize_messages;
4043 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
4044 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4045 expect_messages->message, expect_messages->window, i);
4046 expect_messages = NULL;
4047 flush_events();
4049 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
4050 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
4051 SetForegroundWindow(GetDesktopWindow());
4052 flush_events();
4053 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
4054 flush_events();
4056 expect_messages = reactivate_messages_filtered;
4057 windowposchanged_received = 0;
4058 SetForegroundWindow(focus_window);
4059 flush_events();
4060 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4061 expect_messages->message, expect_messages->window, i);
4062 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
4063 ok(!windowposchanged_received || broken(1),
4064 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4065 expect_messages = NULL;
4067 filter_messages = focus_window;
4068 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4069 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
4071 hr = reset_device(device, &device_desc);
4072 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4074 ref = IDirect3DDevice9_Release(device);
4075 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4077 device_desc.device_window = device_window;
4078 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4080 skip("Failed to create a D3D device, skipping tests.\n");
4081 goto done;
4083 filter_messages = NULL;
4084 flush_events();
4086 device_desc.width = user32_width;
4087 device_desc.height = user32_height;
4089 expect_messages = tests[i].mode_change_messages;
4090 filter_messages = focus_window;
4091 hr = reset_device(device, &device_desc);
4092 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4093 filter_messages = NULL;
4095 /* The WINDOWPOS structure passed to the first WM_WINDOWPOSCHANGING differs between windows versions.
4096 * Prior to Win10 17.03 it is consistent with a MoveWindow(0, 0, width, height) call. Since Windows
4097 * 10 17.03 it has x = 0, y = 0, width = 0, height = 0, flags = SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE
4098 * | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER (0x1837). Visually
4099 * it is clear that the window has not been resized. In previous Windows version the window is resized. */
4101 flush_events();
4102 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4103 expect_messages->message, expect_messages->window, i);
4105 /* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
4106 device_style = GetWindowLongA(device_window, GWL_STYLE);
4107 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
4109 flush_events();
4110 device_desc.width = d3d_width;
4111 device_desc.height = d3d_height;
4112 memset(&windowpos, 0, sizeof(windowpos));
4114 expect_messages = tests[i].mode_change_messages_hidden;
4115 filter_messages = focus_window;
4116 hr = reset_device(device, &device_desc);
4117 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4118 filter_messages = NULL;
4120 flush_events();
4121 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4122 expect_messages->message, expect_messages->window, i);
4124 if (!(tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES))
4126 ok(windowpos.hwnd == device_window && !windowpos.hwndInsertAfter
4127 && !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
4128 && windowpos.flags == (SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE),
4129 "Got unexpected WINDOWPOS hwnd=%p, insertAfter=%p, x=%d, y=%d, cx=%d, cy=%d, flags=%x\n",
4130 windowpos.hwnd, windowpos.hwndInsertAfter, windowpos.x, windowpos.y, windowpos.cx,
4131 windowpos.cy, windowpos.flags);
4134 device_style = GetWindowLongA(device_window, GWL_STYLE);
4135 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4137 todo_wine ok(!(device_style & WS_VISIBLE), "Expected the device window to be hidden, i=%u.\n", i);
4138 ShowWindow(device_window, SW_MINIMIZE);
4139 ShowWindow(device_window, SW_RESTORE);
4141 else
4143 ok(device_style & WS_VISIBLE, "Expected the device window to be visible, i=%u.\n", i);
4146 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
4147 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
4148 (LONG_PTR)test_proc, i);
4150 filter_messages = focus_window;
4151 ref = IDirect3DDevice9_Release(device);
4152 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4154 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4155 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4156 (LONG_PTR)DefWindowProcA, proc, i);
4158 done:
4159 filter_messages = NULL;
4160 DestroyWindow(device_window);
4161 DestroyWindow(focus_window);
4162 SetEvent(thread_params.test_finished);
4163 WaitForSingleObject(thread, INFINITE);
4164 CloseHandle(thread);
4167 IDirect3D9_Release(d3d9);
4168 CloseHandle(thread_params.test_finished);
4169 CloseHandle(thread_params.window_created);
4170 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4173 static void test_wndproc_windowed(void)
4175 struct wndproc_thread_param thread_params;
4176 struct device_desc device_desc;
4177 IDirect3DDevice9 *device;
4178 WNDCLASSA wc = {0};
4179 IDirect3D9 *d3d9;
4180 HANDLE thread;
4181 LONG_PTR proc;
4182 HRESULT hr;
4183 ULONG ref;
4184 DWORD res, tid;
4185 HWND tmp;
4187 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4188 ok(!!d3d9, "Failed to create a D3D object.\n");
4190 wc.lpfnWndProc = test_proc;
4191 wc.lpszClassName = "d3d9_test_wndproc_wc";
4192 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4194 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4195 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4196 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4197 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4199 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4200 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4201 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4202 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4203 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4204 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4205 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4206 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4208 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4209 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4211 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4212 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4213 (LONG_PTR)test_proc, proc);
4214 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4215 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4216 (LONG_PTR)test_proc, proc);
4218 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4219 device_window, focus_window, thread_params.dummy_window);
4221 tmp = GetFocus();
4222 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4223 if (thread_params.running_in_foreground)
4225 tmp = GetForegroundWindow();
4226 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4227 thread_params.dummy_window, tmp);
4229 else
4230 skip("Not running in foreground, skip foreground window test\n");
4232 filter_messages = focus_window;
4234 device_desc.device_window = device_window;
4235 device_desc.width = 640;
4236 device_desc.height = 480;
4237 device_desc.flags = 0;
4238 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4240 skip("Failed to create a D3D device, skipping tests.\n");
4241 goto done;
4244 tmp = GetFocus();
4245 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4246 tmp = GetForegroundWindow();
4247 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4248 thread_params.dummy_window, tmp);
4250 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4251 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4252 (LONG_PTR)test_proc, proc);
4254 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4255 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4256 (LONG_PTR)test_proc, proc);
4258 filter_messages = NULL;
4260 device_desc.width = registry_mode.dmPelsWidth;
4261 device_desc.height = registry_mode.dmPelsHeight;
4262 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4263 hr = reset_device(device, &device_desc);
4264 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4266 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4267 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4268 (LONG_PTR)test_proc, proc);
4270 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4271 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4273 device_desc.flags = 0;
4274 hr = reset_device(device, &device_desc);
4275 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4277 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4278 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4279 (LONG_PTR)test_proc, proc);
4281 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4282 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4283 (LONG_PTR)test_proc, proc);
4285 filter_messages = focus_window;
4287 ref = IDirect3DDevice9_Release(device);
4288 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4290 filter_messages = device_window;
4292 device_desc.device_window = focus_window;
4293 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4295 skip("Failed to create a D3D device, skipping tests.\n");
4296 goto done;
4299 filter_messages = NULL;
4301 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4302 hr = reset_device(device, &device_desc);
4303 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4305 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4306 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4307 (LONG_PTR)test_proc, proc);
4309 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4310 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4312 device_desc.flags = 0;
4313 hr = reset_device(device, &device_desc);
4314 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4316 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4317 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4318 (LONG_PTR)test_proc, proc);
4320 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4321 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4322 (LONG_PTR)test_proc, proc);
4324 filter_messages = device_window;
4326 ref = IDirect3DDevice9_Release(device);
4327 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4329 device_desc.device_window = device_window;
4330 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4332 skip("Failed to create a D3D device, skipping tests.\n");
4333 goto done;
4336 filter_messages = NULL;
4338 device_desc.device_window = device_window;
4339 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4340 hr = reset_device(device, &device_desc);
4341 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4343 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4344 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4345 (LONG_PTR)test_proc, proc);
4347 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4348 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4350 device_desc.flags = 0;
4351 hr = reset_device(device, &device_desc);
4352 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4354 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4355 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4356 (LONG_PTR)test_proc, proc);
4358 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4359 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4360 (LONG_PTR)test_proc, proc);
4362 filter_messages = device_window;
4364 ref = IDirect3DDevice9_Release(device);
4365 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4367 done:
4368 filter_messages = NULL;
4369 IDirect3D9_Release(d3d9);
4371 SetEvent(thread_params.test_finished);
4372 WaitForSingleObject(thread, INFINITE);
4373 CloseHandle(thread_params.test_finished);
4374 CloseHandle(thread_params.window_created);
4375 CloseHandle(thread);
4377 DestroyWindow(device_window);
4378 DestroyWindow(focus_window);
4379 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4382 static void test_reset_fullscreen(void)
4384 struct device_desc device_desc;
4385 D3DDISPLAYMODE d3ddm, d3ddm2;
4386 unsigned int mode_count, i;
4387 IDirect3DDevice9 *device;
4388 WNDCLASSEXA wc = {0};
4389 IDirect3D9 *d3d;
4390 HRESULT hr;
4391 ATOM atom;
4392 static const struct message messages[] =
4394 /* Windows usually sends wparam = TRUE, except on the testbot,
4395 * where it randomly sends FALSE. Ignore it. */
4396 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4397 {0, 0, FALSE, 0},
4400 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4401 ok(!!d3d, "Failed to create a D3D object.\n");
4402 expect_messages = messages;
4404 wc.cbSize = sizeof(wc);
4405 wc.lpfnWndProc = test_proc;
4406 wc.lpszClassName = "test_reset_fullscreen";
4408 atom = RegisterClassExA(&wc);
4409 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4411 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4412 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4413 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4416 * Create a device in windowed mode.
4417 * Since the device is windowed and we haven't called any methods that
4418 * could show the window (such as ShowWindow or SetWindowPos) yet,
4419 * WM_ACTIVATEAPP will not have been sent.
4421 if (!(device = create_device(d3d, device_window, NULL)))
4423 skip("Unable to create device. Skipping test.\n");
4424 goto cleanup;
4428 * Switch to fullscreen mode.
4429 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4430 * message to be sent.
4432 device_desc.width = registry_mode.dmPelsWidth;
4433 device_desc.height = registry_mode.dmPelsHeight;
4434 device_desc.device_window = device_window;
4435 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4436 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4438 flush_events();
4439 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4440 expect_messages = NULL;
4442 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
4443 mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
4444 for (i = 0; i < mode_count; ++i)
4446 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
4447 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4449 if (d3ddm2.Width != d3ddm.Width || d3ddm2.Height != d3ddm.Height)
4450 break;
4452 if (i == mode_count)
4454 skip("Could not find a suitable display mode.\n");
4455 goto cleanup;
4458 wm_size_received = 0;
4460 /* Fullscreen mode change. */
4461 device_desc.width = d3ddm2.Width;
4462 device_desc.height = d3ddm2.Height;
4463 device_desc.device_window = device_window;
4464 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4465 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4467 flush_events();
4468 ok(!wm_size_received, "Received unexpected WM_SIZE message.\n");
4470 cleanup:
4471 if (device) IDirect3DDevice9_Release(device);
4472 IDirect3D9_Release(d3d);
4473 DestroyWindow(device_window);
4474 device_window = focus_window = NULL;
4475 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4479 static inline void set_fpu_cw(WORD cw)
4481 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4482 #define D3D9_TEST_SET_FPU_CW 1
4483 __asm__ volatile ("fnclex");
4484 __asm__ volatile ("fldcw %0" : : "m" (cw));
4485 #elif defined(__i386__) && defined(_MSC_VER)
4486 #define D3D9_TEST_SET_FPU_CW 1
4487 __asm fnclex;
4488 __asm fldcw cw;
4489 #endif
4492 static inline WORD get_fpu_cw(void)
4494 WORD cw = 0;
4495 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4496 #define D3D9_TEST_GET_FPU_CW 1
4497 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4498 #elif defined(__i386__) && defined(_MSC_VER)
4499 #define D3D9_TEST_GET_FPU_CW 1
4500 __asm fnstcw cw;
4501 #endif
4502 return cw;
4505 static WORD callback_cw, callback_set_cw;
4506 static DWORD callback_tid;
4508 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4510 *out = NULL;
4511 return E_NOINTERFACE;
4514 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4516 callback_cw = get_fpu_cw();
4517 set_fpu_cw(callback_set_cw);
4518 callback_tid = GetCurrentThreadId();
4519 return 2;
4522 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4524 callback_cw = get_fpu_cw();
4525 set_fpu_cw(callback_set_cw);
4526 callback_tid = GetCurrentThreadId();
4527 return 1;
4530 static const IUnknownVtbl dummy_object_vtbl =
4532 dummy_object_QueryInterface,
4533 dummy_object_AddRef,
4534 dummy_object_Release,
4537 static const GUID d3d9_private_data_test_guid =
4539 0xfdb37466,
4540 0x428f,
4541 0x4edf,
4542 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4545 static void test_fpu_setup(void)
4547 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4548 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
4549 IUnknown dummy_object = {&dummy_object_vtbl};
4550 struct device_desc device_desc;
4551 IDirect3DSurface9 *surface;
4552 IDirect3DDevice9 *device;
4553 WORD cw, expected_cw;
4554 HWND window = NULL;
4555 IDirect3D9 *d3d9;
4556 HRESULT hr;
4558 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4559 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4560 ok(!!window, "Failed to create a window.\n");
4561 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4562 ok(!!d3d9, "Failed to create a D3D object.\n");
4564 device_desc.device_window = window;
4565 device_desc.width = 640;
4566 device_desc.height = 480;
4567 device_desc.flags = 0;
4569 set_fpu_cw(0xf60);
4570 cw = get_fpu_cw();
4571 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4573 if (!(device = create_device(d3d9, window, &device_desc)))
4575 skip("Failed to create a 3D device, skipping test.\n");
4576 set_fpu_cw(0x37f);
4577 goto done;
4580 expected_cw = is_64bit ? 0xf60 : 0x7f;
4582 cw = get_fpu_cw();
4583 todo_wine_if(is_64bit)
4584 ok(cw == expected_cw, "cw is %#x, expected %#x.\n", cw, expected_cw);
4586 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4587 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4589 callback_set_cw = 0xf60;
4590 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4591 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4592 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4593 todo_wine_if(is_64bit)
4594 ok(callback_cw == expected_cw, "Callback cw is %#x, expected %#x.\n", callback_cw, expected_cw);
4595 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4596 cw = get_fpu_cw();
4597 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4599 callback_cw = 0;
4600 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4601 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4602 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4603 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4604 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4606 callback_set_cw = 0x7f;
4607 set_fpu_cw(0x7f);
4609 IDirect3DSurface9_Release(surface);
4611 callback_cw = 0;
4612 IDirect3DDevice9_Release(device);
4613 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4614 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4616 cw = get_fpu_cw();
4617 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4618 set_fpu_cw(0xf60);
4619 cw = get_fpu_cw();
4620 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4622 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4623 device = create_device(d3d9, window, &device_desc);
4624 ok(device != NULL, "CreateDevice failed.\n");
4626 cw = get_fpu_cw();
4627 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4629 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4630 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4632 callback_cw = 0;
4633 callback_set_cw = 0x37f;
4634 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4635 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4636 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4637 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4638 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4639 cw = get_fpu_cw();
4640 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4642 IDirect3DSurface9_Release(surface);
4644 callback_cw = 0;
4645 IDirect3DDevice9_Release(device);
4646 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4647 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4649 done:
4650 IDirect3D9_Release(d3d9);
4651 DestroyWindow(window);
4652 #endif
4655 static void test_window_style(void)
4657 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4658 LONG device_style, device_exstyle;
4659 LONG focus_style, focus_exstyle;
4660 struct device_desc device_desc;
4661 LONG style, expected_style;
4662 IDirect3DDevice9 *device;
4663 IDirect3D9 *d3d9;
4664 HRESULT hr;
4665 ULONG ref;
4666 BOOL ret;
4667 static const struct
4669 DWORD device_flags;
4670 LONG style, focus_loss_style, exstyle;
4672 tests[] =
4674 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4675 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4677 unsigned int i;
4679 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4680 ok(!!d3d9, "Failed to create a D3D object.\n");
4681 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4683 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4685 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4686 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4687 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4688 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4690 device_style = GetWindowLongA(device_window, GWL_STYLE);
4691 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4692 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4693 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4695 GetWindowRect(focus_window, &focus_rect);
4696 GetWindowRect(device_window, &device_rect);
4698 device_desc.device_window = device_window;
4699 device_desc.width = registry_mode.dmPelsWidth;
4700 device_desc.height = registry_mode.dmPelsHeight;
4701 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4702 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4704 skip("Failed to create a D3D device, skipping tests.\n");
4705 DestroyWindow(device_window);
4706 DestroyWindow(focus_window);
4707 break;
4710 style = GetWindowLongA(device_window, GWL_STYLE);
4711 expected_style = device_style | tests[i].style;
4712 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4713 expected_style, style, i);
4714 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4715 expected_style = device_exstyle | tests[i].exstyle;
4716 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4717 expected_style, style, i);
4719 style = GetWindowLongA(focus_window, GWL_STYLE);
4720 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4721 focus_style, style, i);
4722 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4723 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4724 focus_exstyle, style, i);
4726 GetWindowRect(device_window, &r);
4727 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4728 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4729 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4730 else
4731 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4732 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4733 GetClientRect(device_window, &r2);
4734 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4735 GetWindowRect(focus_window, &r);
4736 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4737 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4739 device_desc.flags = 0;
4740 hr = reset_device(device, &device_desc);
4741 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4743 style = GetWindowLongA(device_window, GWL_STYLE);
4744 expected_style = device_style | tests[i].style;
4745 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4746 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4747 expected_style, style, i);
4748 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4749 expected_style = device_exstyle | tests[i].exstyle;
4750 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4751 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4752 expected_style, style, i);
4754 style = GetWindowLongA(focus_window, GWL_STYLE);
4755 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4756 focus_style, style, i);
4757 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4758 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4759 focus_exstyle, style, i);
4761 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4762 hr = reset_device(device, &device_desc);
4763 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4764 ret = SetForegroundWindow(GetDesktopWindow());
4765 ok(ret, "Failed to set foreground window.\n");
4767 style = GetWindowLongA(device_window, GWL_STYLE);
4768 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4769 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4770 expected_style, style);
4771 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4772 expected_style = device_exstyle | tests[i].exstyle;
4773 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4774 expected_style, style);
4776 style = GetWindowLongA(focus_window, GWL_STYLE);
4777 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4778 focus_style, style);
4779 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4780 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4781 focus_exstyle, style);
4783 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4784 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4785 * like a good idea to reset it first. */
4786 ShowWindow(focus_window, SW_MINIMIZE);
4787 ShowWindow(focus_window, SW_RESTORE);
4788 ret = SetForegroundWindow(focus_window);
4789 ok(ret, "Failed to set foreground window.\n");
4790 flush_events();
4791 hr = reset_device(device, &device_desc);
4792 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4794 ref = IDirect3DDevice9_Release(device);
4795 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4797 DestroyWindow(device_window);
4798 DestroyWindow(focus_window);
4800 IDirect3D9_Release(d3d9);
4803 static const POINT *expect_pos;
4805 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4807 if (message == WM_MOUSEMOVE)
4809 if (expect_pos && expect_pos->x && expect_pos->y)
4811 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4813 ClientToScreen(window, &p);
4814 if (expect_pos->x == p.x && expect_pos->y == p.y)
4815 ++expect_pos;
4819 return DefWindowProcA(window, message, wparam, lparam);
4822 static void test_cursor_pos(void)
4824 IDirect3DSurface9 *cursor;
4825 IDirect3DDevice9 *device;
4826 WNDCLASSA wc = {0};
4827 IDirect3D9 *d3d9;
4828 UINT refcount;
4829 HWND window;
4830 HRESULT hr;
4831 BOOL ret;
4833 /* Note that we don't check for movement we're not supposed to receive.
4834 * That's because it's hard to distinguish from the user accidentally
4835 * moving the mouse. */
4836 static const POINT points[] =
4838 {50, 50},
4839 {75, 75},
4840 {100, 100},
4841 {125, 125},
4842 {150, 150},
4843 {125, 125},
4844 {150, 150},
4845 {150, 150},
4846 {0, 0},
4849 wc.lpfnWndProc = test_cursor_proc;
4850 wc.lpszClassName = "d3d9_test_cursor_wc";
4851 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4852 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_POPUP | WS_SYSMENU,
4853 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4854 ShowWindow(window, SW_SHOW);
4855 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4856 ok(!!d3d9, "Failed to create a D3D object.\n");
4858 device = create_device(d3d9, window, NULL);
4859 if (!device)
4861 skip("Failed to create a D3D device, skipping tests.\n");
4862 goto done;
4865 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4866 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4867 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4868 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4869 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4870 IDirect3DSurface9_Release(cursor);
4871 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4872 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4874 flush_events();
4875 expect_pos = points;
4877 ret = SetCursorPos(50, 50);
4878 ok(ret, "Failed to set cursor position.\n");
4879 flush_events();
4881 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4882 flush_events();
4883 /* SetCursorPosition() eats duplicates. */
4884 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4885 flush_events();
4887 ret = SetCursorPos(100, 100);
4888 ok(ret, "Failed to set cursor position.\n");
4889 flush_events();
4890 /* Even if the position was set with SetCursorPos(). */
4891 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4892 flush_events();
4894 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4895 flush_events();
4896 ret = SetCursorPos(150, 150);
4897 ok(ret, "Failed to set cursor position.\n");
4898 flush_events();
4899 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4900 flush_events();
4902 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4903 flush_events();
4904 /* SetCursorPos() doesn't. */
4905 ret = SetCursorPos(150, 150);
4906 ok(ret, "Failed to set cursor position.\n");
4907 flush_events();
4909 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4910 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4912 refcount = IDirect3DDevice9_Release(device);
4913 ok(!refcount, "Device has %u references left.\n", refcount);
4914 done:
4915 DestroyWindow(window);
4916 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4917 IDirect3D9_Release(d3d9);
4920 static void test_mode_change(void)
4922 RECT d3d_rect, focus_rect, r;
4923 struct device_desc device_desc;
4924 IDirect3DSurface9 *backbuffer;
4925 IDirect3DDevice9 *device;
4926 D3DSURFACE_DESC desc;
4927 IDirect3D9 *d3d9;
4928 DEVMODEW devmode;
4929 ULONG refcount;
4930 UINT adapter_mode_count, i;
4931 HRESULT hr;
4932 DWORD ret;
4933 LONG change_ret;
4934 D3DDISPLAYMODE d3ddm;
4935 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4937 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4938 ok(!!d3d9, "Failed to create a D3D object.\n");
4940 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4941 for (i = 0; i < adapter_mode_count; ++i)
4943 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4944 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4946 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4947 continue;
4948 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4949 * refuses to create a device at these sizes. */
4950 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4951 continue;
4953 if (!user32_width)
4955 user32_width = d3ddm.Width;
4956 user32_height = d3ddm.Height;
4957 continue;
4960 /* Make sure the d3d mode is smaller in width or height and at most
4961 * equal in the other dimension than the mode passed to
4962 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4963 * the ChangeDisplaySettings parameters + 12. */
4964 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4965 continue;
4966 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4968 d3d_width = d3ddm.Width;
4969 d3d_height = d3ddm.Height;
4970 break;
4972 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4974 d3d_width = user32_width;
4975 d3d_height = user32_height;
4976 user32_width = d3ddm.Width;
4977 user32_height = d3ddm.Height;
4978 break;
4982 if (!d3d_width)
4984 skip("Could not find adequate modes, skipping mode tests.\n");
4985 IDirect3D9_Release(d3d9);
4986 return;
4989 memset(&devmode, 0, sizeof(devmode));
4990 devmode.dmSize = sizeof(devmode);
4991 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4992 devmode.dmPelsWidth = user32_width;
4993 devmode.dmPelsHeight = user32_height;
4994 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4995 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4997 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4998 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4999 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5000 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
5002 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
5003 GetWindowRect(focus_window, &focus_rect);
5005 device_desc.device_window = device_window;
5006 device_desc.width = d3d_width;
5007 device_desc.height = d3d_height;
5008 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5009 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5011 skip("Failed to create a D3D device, skipping tests.\n");
5012 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5013 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5014 goto done;
5017 devmode.dmPelsWidth = user32_width;
5018 devmode.dmPelsHeight = user32_height;
5019 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5020 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5022 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5023 ok(ret, "Failed to get display mode.\n");
5024 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
5025 "Expected resolution %ux%u, got %ux%u.\n",
5026 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
5028 GetWindowRect(device_window, &r);
5029 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
5030 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
5031 GetWindowRect(focus_window, &r);
5032 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
5033 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
5035 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
5036 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
5037 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
5038 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
5039 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
5040 desc.Width, d3d_width);
5041 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
5042 desc.Height, d3d_height);
5043 IDirect3DSurface9_Release(backbuffer);
5045 refcount = IDirect3DDevice9_Release(device);
5046 ok(!refcount, "Device has %u references left.\n", refcount);
5048 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5049 ok(ret, "Failed to get display mode.\n");
5050 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5051 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5052 "Expected resolution %ux%u, got %ux%u.\n",
5053 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5055 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5056 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5058 /* The mode restore also happens when the device was created at the original screen size. */
5060 device_desc.device_window = device_window;
5061 device_desc.width = registry_mode.dmPelsWidth;
5062 device_desc.height = registry_mode.dmPelsHeight;
5063 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5064 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
5066 devmode.dmPelsWidth = user32_width;
5067 devmode.dmPelsHeight = user32_height;
5068 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5069 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5071 refcount = IDirect3DDevice9_Release(device);
5072 ok(!refcount, "Device has %u references left.\n", refcount);
5074 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5075 ok(ret, "Failed to get display mode.\n");
5076 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5077 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5078 "Expected resolution %ux%u, got %ux%u.\n",
5079 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5081 done:
5082 DestroyWindow(device_window);
5083 DestroyWindow(focus_window);
5084 IDirect3D9_Release(d3d9);
5087 static void test_device_window_reset(void)
5089 RECT fullscreen_rect, device_rect, r;
5090 struct device_desc device_desc;
5091 IDirect3DDevice9 *device;
5092 WNDCLASSA wc = {0};
5093 IDirect3D9 *d3d9;
5094 LONG_PTR proc;
5095 HRESULT hr;
5096 ULONG ref;
5098 wc.lpfnWndProc = test_proc;
5099 wc.lpszClassName = "d3d9_test_wndproc_wc";
5100 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5102 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5103 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
5104 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5105 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
5106 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5107 ok(!!d3d9, "Failed to create a D3D object.\n");
5109 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
5110 GetWindowRect(device_window, &device_rect);
5112 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5113 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5114 (LONG_PTR)test_proc, proc);
5115 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5116 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5117 (LONG_PTR)test_proc, proc);
5119 device_desc.device_window = NULL;
5120 device_desc.width = registry_mode.dmPelsWidth;
5121 device_desc.height = registry_mode.dmPelsHeight;
5122 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5123 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5125 skip("Failed to create a D3D device, skipping tests.\n");
5126 goto done;
5129 GetWindowRect(focus_window, &r);
5130 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5131 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5132 GetWindowRect(device_window, &r);
5133 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
5134 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
5136 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5137 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5138 (LONG_PTR)test_proc, proc);
5139 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5140 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5142 device_desc.device_window = device_window;
5143 hr = reset_device(device, &device_desc);
5144 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5146 GetWindowRect(focus_window, &r);
5147 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5148 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5149 GetWindowRect(device_window, &r);
5150 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5151 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5153 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5154 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5155 (LONG_PTR)test_proc, proc);
5156 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5157 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5159 ref = IDirect3DDevice9_Release(device);
5160 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5162 done:
5163 IDirect3D9_Release(d3d9);
5164 DestroyWindow(device_window);
5165 DestroyWindow(focus_window);
5166 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
5169 static void test_reset_resources(void)
5171 IDirect3DSurface9 *surface, *rt;
5172 IDirect3DTexture9 *texture;
5173 IDirect3DDevice9 *device;
5174 IDirect3D9 *d3d9;
5175 unsigned int i;
5176 D3DCAPS9 caps;
5177 HWND window;
5178 HRESULT hr;
5179 ULONG ref;
5181 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5182 0, 0, 640, 480, 0, 0, 0, 0);
5183 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5184 ok(!!d3d9, "Failed to create a D3D object.\n");
5186 if (!(device = create_device(d3d9, window, NULL)))
5188 skip("Failed to create a D3D device, skipping tests.\n");
5189 goto done;
5192 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5193 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5195 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5196 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5197 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5198 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5199 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5200 IDirect3DSurface9_Release(surface);
5202 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5204 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5205 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5206 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5207 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5208 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5209 IDirect3DTexture9_Release(texture);
5210 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5211 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5212 IDirect3DSurface9_Release(surface);
5215 hr = reset_device(device, NULL);
5216 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5218 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5219 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5220 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5221 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5222 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5223 IDirect3DSurface9_Release(surface);
5224 IDirect3DSurface9_Release(rt);
5226 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5228 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5229 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5232 ref = IDirect3DDevice9_Release(device);
5233 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5235 done:
5236 IDirect3D9_Release(d3d9);
5237 DestroyWindow(window);
5240 static void test_set_rt_vp_scissor(void)
5242 IDirect3DStateBlock9 *stateblock;
5243 IDirect3DDevice9 *device;
5244 IDirect3DSurface9 *rt;
5245 IDirect3D9 *d3d9;
5246 D3DVIEWPORT9 vp;
5247 UINT refcount;
5248 HWND window;
5249 HRESULT hr;
5250 RECT rect;
5252 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5253 0, 0, 640, 480, 0, 0, 0, 0);
5254 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5255 ok(!!d3d9, "Failed to create a D3D object.\n");
5256 if (!(device = create_device(d3d9, window, NULL)))
5258 skip("Failed to create a D3D device, skipping tests.\n");
5259 DestroyWindow(window);
5260 return;
5263 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5264 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5265 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5267 hr = IDirect3DDevice9_GetViewport(device, &vp);
5268 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5269 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5270 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5271 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5272 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5273 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5274 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5276 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5277 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5278 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5279 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5281 hr = IDirect3DDevice9_BeginStateBlock(device);
5282 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5284 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5285 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5287 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5288 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5289 IDirect3DStateBlock9_Release(stateblock);
5291 hr = IDirect3DDevice9_GetViewport(device, &vp);
5292 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5293 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5294 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5295 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5296 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5297 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5298 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5300 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5301 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5302 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5303 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5305 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5306 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5308 vp.X = 10;
5309 vp.Y = 20;
5310 vp.Width = 30;
5311 vp.Height = 40;
5312 vp.MinZ = 0.25f;
5313 vp.MaxZ = 0.75f;
5314 hr = IDirect3DDevice9_SetViewport(device, &vp);
5315 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5317 SetRect(&rect, 50, 60, 70, 80);
5318 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5319 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5321 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5322 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5324 hr = IDirect3DDevice9_GetViewport(device, &vp);
5325 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5326 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5327 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5328 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5329 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5330 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5331 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5333 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5334 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5335 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5336 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5338 IDirect3DSurface9_Release(rt);
5339 refcount = IDirect3DDevice9_Release(device);
5340 ok(!refcount, "Device has %u references left.\n", refcount);
5341 IDirect3D9_Release(d3d9);
5342 DestroyWindow(window);
5345 static void test_volume_get_container(void)
5347 IDirect3DVolumeTexture9 *texture = NULL;
5348 IDirect3DVolume9 *volume = NULL;
5349 IDirect3DDevice9 *device;
5350 IUnknown *container;
5351 IDirect3D9 *d3d9;
5352 ULONG refcount;
5353 D3DCAPS9 caps;
5354 HWND window;
5355 HRESULT hr;
5357 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
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 if (!(device = create_device(d3d9, window, NULL)))
5363 skip("Failed to create a D3D device, skipping tests.\n");
5364 IDirect3D9_Release(d3d9);
5365 DestroyWindow(window);
5366 return;
5369 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5370 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5371 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5373 skip("No volume texture support, skipping tests.\n");
5374 IDirect3DDevice9_Release(device);
5375 IDirect3D9_Release(d3d9);
5376 DestroyWindow(window);
5377 return;
5380 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5381 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5382 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5383 ok(!!texture, "Got unexpected texture %p.\n", texture);
5385 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5386 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5387 ok(!!volume, "Got unexpected volume %p.\n", volume);
5389 /* These should work... */
5390 container = NULL;
5391 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5392 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5393 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5394 IUnknown_Release(container);
5396 container = NULL;
5397 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5398 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5399 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5400 IUnknown_Release(container);
5402 container = NULL;
5403 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5404 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5405 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5406 IUnknown_Release(container);
5408 container = NULL;
5409 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5410 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5411 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5412 IUnknown_Release(container);
5414 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5415 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5416 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5417 ok(!container, "Got unexpected container %p.\n", container);
5419 IDirect3DVolume9_Release(volume);
5420 IDirect3DVolumeTexture9_Release(texture);
5421 refcount = IDirect3DDevice9_Release(device);
5422 ok(!refcount, "Device has %u references left.\n", refcount);
5423 IDirect3D9_Release(d3d9);
5424 DestroyWindow(window);
5427 static void test_volume_resource(void)
5429 IDirect3DVolumeTexture9 *texture;
5430 IDirect3DResource9 *resource;
5431 IDirect3DVolume9 *volume;
5432 IDirect3DDevice9 *device;
5433 IDirect3D9 *d3d9;
5434 ULONG refcount;
5435 D3DCAPS9 caps;
5436 HWND window;
5437 HRESULT hr;
5439 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5440 0, 0, 640, 480, 0, 0, 0, 0);
5441 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5442 ok(!!d3d9, "Failed to create a D3D object.\n");
5443 if (!(device = create_device(d3d9, window, NULL)))
5445 skip("Failed to create a D3D device, skipping tests.\n");
5446 IDirect3D9_Release(d3d9);
5447 DestroyWindow(window);
5448 return;
5451 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5452 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5453 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5455 skip("No volume texture support, skipping tests.\n");
5456 IDirect3DDevice9_Release(device);
5457 IDirect3D9_Release(d3d9);
5458 DestroyWindow(window);
5459 return;
5462 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5463 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5464 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5465 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5466 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5467 IDirect3DVolumeTexture9_Release(texture);
5469 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5470 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5472 IDirect3DVolume9_Release(volume);
5473 refcount = IDirect3DDevice9_Release(device);
5474 ok(!refcount, "Device has %u references left.\n", refcount);
5475 IDirect3D9_Release(d3d9);
5476 DestroyWindow(window);
5479 static void test_vb_lock_flags(void)
5481 static const struct
5483 DWORD flags;
5484 const char *debug_string;
5485 HRESULT win7_result;
5487 test_data[] =
5489 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5490 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5491 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5492 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5493 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5494 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5495 /* Completely bogus flags aren't an error. */
5496 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5498 IDirect3DVertexBuffer9 *buffer;
5499 IDirect3DDevice9 *device;
5500 IDirect3D9 *d3d9;
5501 unsigned int i;
5502 ULONG refcount;
5503 HWND window;
5504 HRESULT hr;
5505 void *data;
5507 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5508 0, 0, 640, 480, 0, 0, 0, 0);
5509 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5510 ok(!!d3d9, "Failed to create a D3D object.\n");
5511 if (!(device = create_device(d3d9, window, NULL)))
5513 skip("Failed to create a D3D device, skipping tests.\n");
5514 IDirect3D9_Release(d3d9);
5515 DestroyWindow(window);
5516 return;
5519 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5520 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5522 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5524 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5525 /* Windows XP always returns D3D_OK even with flags that don't make
5526 * sense. Windows 7 returns an error. At least one game (Shaiya)
5527 * depends on the Windows XP result, so mark the Windows 7 behavior as
5528 * broken. */
5529 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5530 hr, test_data[i].debug_string);
5531 if (SUCCEEDED(hr))
5533 ok(!!data, "Got unexpected data %p.\n", data);
5534 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5535 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5539 IDirect3DVertexBuffer9_Release(buffer);
5540 refcount = IDirect3DDevice9_Release(device);
5541 ok(!refcount, "Device has %u references left.\n", refcount);
5542 IDirect3D9_Release(d3d9);
5543 DestroyWindow(window);
5546 static const char *debug_d3dpool(D3DPOOL pool)
5548 switch (pool)
5550 case D3DPOOL_DEFAULT:
5551 return "D3DPOOL_DEFAULT";
5552 case D3DPOOL_SYSTEMMEM:
5553 return "D3DPOOL_SYSTEMMEM";
5554 case D3DPOOL_SCRATCH:
5555 return "D3DPOOL_SCRATCH";
5556 case D3DPOOL_MANAGED:
5557 return "D3DPOOL_MANAGED";
5558 default:
5559 return "unknown pool";
5563 static void test_vertex_buffer_alignment(void)
5565 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5566 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5567 IDirect3DVertexBuffer9 *buffer = NULL;
5568 const unsigned int align = 16;
5569 IDirect3DDevice9 *device;
5570 unsigned int i, j;
5571 IDirect3D9 *d3d9;
5572 ULONG refcount;
5573 HWND window;
5574 HRESULT hr;
5575 void *data;
5577 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5578 0, 0, 640, 480, 0, 0, 0, 0);
5579 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5580 ok(!!d3d9, "Failed to create a D3D object.\n");
5581 if (!(device = create_device(d3d9, window, NULL)))
5583 skip("Failed to create a D3D device, skipping tests.\n");
5584 IDirect3D9_Release(d3d9);
5585 DestroyWindow(window);
5586 return;
5589 for (i = 0; i < ARRAY_SIZE(sizes); ++i)
5591 for (j = 0; j < ARRAY_SIZE(pools); ++j)
5593 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5594 if (pools[j] == D3DPOOL_SCRATCH)
5595 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5596 else
5597 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5598 debug_d3dpool(pools[j]), sizes[i], hr);
5599 if (FAILED(hr))
5600 continue;
5602 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5603 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5604 ok(!((DWORD_PTR)data & (align - 1)),
5605 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5606 data, align, sizes[i], debug_d3dpool(pools[j]));
5607 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5608 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5609 IDirect3DVertexBuffer9_Release(buffer);
5613 refcount = IDirect3DDevice9_Release(device);
5614 ok(!refcount, "Device has %u references left.\n", refcount);
5615 IDirect3D9_Release(d3d9);
5616 DestroyWindow(window);
5619 static void test_query_support(void)
5621 static const D3DQUERYTYPE queries[] =
5623 D3DQUERYTYPE_VCACHE,
5624 D3DQUERYTYPE_RESOURCEMANAGER,
5625 D3DQUERYTYPE_VERTEXSTATS,
5626 D3DQUERYTYPE_EVENT,
5627 D3DQUERYTYPE_OCCLUSION,
5628 D3DQUERYTYPE_TIMESTAMP,
5629 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5630 D3DQUERYTYPE_TIMESTAMPFREQ,
5631 D3DQUERYTYPE_PIPELINETIMINGS,
5632 D3DQUERYTYPE_INTERFACETIMINGS,
5633 D3DQUERYTYPE_VERTEXTIMINGS,
5634 D3DQUERYTYPE_PIXELTIMINGS,
5635 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5636 D3DQUERYTYPE_CACHEUTILIZATION,
5638 IDirect3DQuery9 *query = NULL;
5639 IDirect3DDevice9 *device;
5640 IDirect3D9 *d3d9;
5641 unsigned int i;
5642 ULONG refcount;
5643 BOOL supported;
5644 HWND window;
5645 HRESULT hr;
5647 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5648 0, 0, 640, 480, 0, 0, 0, 0);
5649 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5650 ok(!!d3d9, "Failed to create a D3D object.\n");
5651 if (!(device = create_device(d3d9, window, NULL)))
5653 skip("Failed to create a D3D device, skipping tests.\n");
5654 IDirect3D9_Release(d3d9);
5655 DestroyWindow(window);
5656 return;
5659 for (i = 0; i < ARRAY_SIZE(queries); ++i)
5661 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5662 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5664 supported = hr == D3D_OK;
5666 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5667 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5669 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5670 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5672 if (query)
5674 IDirect3DQuery9_Release(query);
5675 query = NULL;
5679 for (i = 0; i < 40; ++i)
5681 /* Windows 10 17.09 (build 16299.19) added an undocumented query with an enum value of 0x16 (=22).
5682 * It returns D3D_OK when asking for support and E_FAIL when trying to actually create it. */
5683 if ((D3DQUERYTYPE_VCACHE <= i && i <= D3DQUERYTYPE_MEMORYPRESSURE) || i == 0x16)
5684 continue;
5686 hr = IDirect3DDevice9_CreateQuery(device, i, NULL);
5687 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5689 query = (IDirect3DQuery9 *)0xdeadbeef;
5690 hr = IDirect3DDevice9_CreateQuery(device, i, &query);
5691 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5692 ok(query == (IDirect3DQuery9 *)0xdeadbeef, "Got unexpected query %p.\n", query);
5695 refcount = IDirect3DDevice9_Release(device);
5696 ok(!refcount, "Device has %u references left.\n", refcount);
5697 IDirect3D9_Release(d3d9);
5698 DestroyWindow(window);
5701 static void test_occlusion_query(void)
5703 static const float quad[] =
5705 -1.0f, -1.0f, 0.0f,
5706 -1.0f, 1.0f, 0.0f,
5707 1.0f, 1.0f, 0.0f,
5708 1.0f, -1.0f, 0.0f,
5710 unsigned int data_size, i, count;
5711 struct device_desc device_desc;
5712 IDirect3DQuery9 *query = NULL;
5713 IDirect3DDevice9 *device;
5714 IDirect3DSurface9 *rt;
5715 IDirect3D9 *d3d9;
5716 D3DVIEWPORT9 vp;
5717 ULONG refcount;
5718 D3DCAPS9 caps;
5719 HWND window;
5720 HRESULT hr;
5721 union
5723 WORD word[4];
5724 DWORD dword[2];
5725 UINT64 uint;
5726 } data, expected;
5727 BOOL broken_occlusion = FALSE;
5728 expected.uint = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5730 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5731 0, 0, 640, 480, 0, 0, 0, 0);
5732 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5733 ok(!!d3d9, "Failed to create a D3D object.\n");
5734 device_desc.device_window = window;
5735 device_desc.width = registry_mode.dmPelsWidth;
5736 device_desc.height = registry_mode.dmPelsHeight;
5737 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5738 if (!(device = create_device(d3d9, window, &device_desc)))
5740 skip("Failed to create a D3D device, skipping tests.\n");
5741 IDirect3D9_Release(d3d9);
5742 DestroyWindow(window);
5743 return;
5746 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5747 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5748 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5749 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5750 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5751 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5753 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5754 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5755 if (!query)
5757 skip("Occlusion queries are not supported, skipping tests.\n");
5758 IDirect3DDevice9_Release(device);
5759 IDirect3D9_Release(d3d9);
5760 DestroyWindow(window);
5761 return;
5764 data_size = IDirect3DQuery9_GetDataSize(query);
5765 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5767 memset(&data, 0xff, sizeof(data));
5768 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5769 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5770 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5771 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5772 ok(data.dword[0] == 0xdddddddd && data.dword[1] == 0xffffffff,
5773 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5775 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5776 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5777 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5778 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5779 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5780 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5782 data.dword[0] = 0x12345678;
5783 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5784 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5785 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5786 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5787 if (hr == D3D_OK)
5788 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5790 hr = IDirect3DDevice9_BeginScene(device);
5791 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5792 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5793 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5794 hr = IDirect3DDevice9_EndScene(device);
5795 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5797 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5798 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5799 for (i = 0; i < 500; ++i)
5801 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5802 break;
5803 Sleep(10);
5805 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5807 memset(&data, 0xff, sizeof(data));
5808 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5809 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5810 ok(data.dword[0] == expected.dword[0] || broken(!data.dword[0]),
5811 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5812 if (!data.dword[0])
5814 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5815 broken_occlusion = TRUE;
5818 memset(&data, 0xff, sizeof(data));
5819 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5820 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5821 if (!broken_occlusion)
5822 ok(data.word[0] == expected.word[0],
5823 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5824 ok(data.word[1] == 0xffff,
5825 "Data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5827 memset(&data, 0xf0, sizeof(data));
5828 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5829 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5830 if (!broken_occlusion)
5831 ok(data.dword[0] == expected.dword[0],
5832 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5833 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5834 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5835 on AMD and Nvidia respectively). */
5836 if (0)
5838 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5839 data.dword[1]);
5842 memset(&data, 0xff, sizeof(data));
5843 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5844 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5845 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5847 /* This crashes on Windows. */
5848 if (0)
5850 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5851 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5854 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5855 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5856 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5857 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5858 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5859 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5861 if (broken_occlusion)
5862 goto done;
5864 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5865 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5867 vp.X = 0;
5868 vp.Y = 0;
5869 vp.Width = min(caps.MaxTextureWidth, 8192);
5870 vp.Height = min(caps.MaxTextureHeight, 8192);
5871 vp.MinZ = 0.0f;
5872 vp.MaxZ = 1.0f;
5873 hr = IDirect3DDevice9_SetViewport(device, &vp);
5874 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5876 hr = IDirect3DDevice9_CreateRenderTarget(device, vp.Width, vp.Height,
5877 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5878 if (FAILED(hr))
5880 skip("Failed to create render target (width %u, height %u), hr %#x.\n", vp.Width, vp.Height, hr);
5881 goto done;
5883 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5884 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5885 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5886 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
5887 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5889 expected.uint = vp.Width * vp.Height;
5890 count = ((((UINT64)~0u) + 1) / expected.uint) + 1;
5891 expected.uint *= count;
5893 trace("Expects 0x%08x%08x samples.\n", expected.dword[1], expected.dword[0]);
5895 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5896 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5897 hr = IDirect3DDevice9_BeginScene(device);
5898 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5899 for (i = 0; i < count; i++)
5901 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5902 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5904 hr = IDirect3DDevice9_EndScene(device);
5905 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5906 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5907 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5909 for (i = 0; i < 500; ++i)
5911 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5912 break;
5913 Sleep(10);
5915 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5917 memset(&data, 0xff, sizeof(data));
5918 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5919 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5920 ok((data.dword[0] == expected.dword[0] && data.dword[1] == expected.dword[1])
5921 || (data.dword[0] == 0xffffffff && !data.dword[1])
5922 || broken(data.dword[0] < 0xffffffff && !data.dword[1]),
5923 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5925 IDirect3DSurface9_Release(rt);
5927 done:
5928 IDirect3DQuery9_Release(query);
5929 refcount = IDirect3DDevice9_Release(device);
5930 ok(!refcount, "Device has %u references left.\n", refcount);
5931 IDirect3D9_Release(d3d9);
5932 DestroyWindow(window);
5935 static void test_timestamp_query(void)
5937 static const float quad[] =
5939 -1.0f, -1.0f, 0.0f,
5940 -1.0f, 1.0f, 0.0f,
5941 1.0f, 1.0f, 0.0f,
5942 1.0f, -1.0f, 0.0f,
5944 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5945 unsigned int data_size, i;
5946 IDirect3DDevice9 *device;
5947 IDirect3D9 *d3d9;
5948 ULONG refcount;
5949 HWND window;
5950 HRESULT hr;
5951 DWORD timestamp[2], freq[2];
5952 WORD disjoint[2];
5954 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5955 0, 0, 640, 480, 0, 0, 0, 0);
5956 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5957 ok(!!d3d9, "Failed to create a D3D object.\n");
5958 if (!(device = create_device(d3d9, window, NULL)))
5960 skip("Failed to create a D3D device, skipping tests.\n");
5961 IDirect3D9_Release(d3d9);
5962 DestroyWindow(window);
5963 return;
5966 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5967 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5968 if (FAILED(hr))
5970 skip("Timestamp queries are not supported, skipping tests.\n");
5971 IDirect3DDevice9_Release(device);
5972 IDirect3D9_Release(d3d9);
5973 DestroyWindow(window);
5974 return;
5976 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5977 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5979 memset(freq, 0xff, sizeof(freq));
5980 hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH);
5981 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5982 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5983 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5984 ok(freq[0] == 0xdddddddd && freq[1] == 0xffffffff,
5985 "Got unexpected query result 0x%08x%08x.\n", freq[1], freq[0]);
5987 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5988 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5989 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5990 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5992 memset(disjoint, 0xff, sizeof(disjoint));
5993 hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH);
5994 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5995 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5996 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5997 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xffff,
5998 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
5999 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(DWORD), D3DGETDATA_FLUSH);
6000 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6001 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xdddd,
6002 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
6004 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
6005 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6006 data_size = IDirect3DQuery9_GetDataSize(query);
6007 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
6009 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
6010 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6011 for (i = 0; i < 500; ++i)
6013 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6014 break;
6015 Sleep(10);
6017 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6019 memset(freq, 0xff, sizeof(freq));
6020 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
6021 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6022 ok(freq[1] == 0xffffffff,
6023 "Freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
6024 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
6025 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6026 ok(freq[1] != 0xffffffff, "High bytes of freq were not modified (0x%.8x).\n",
6027 freq[1]);
6029 memset(timestamp, 0xff, sizeof(timestamp));
6030 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
6031 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6032 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6033 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6034 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xffffffff,
6035 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6036 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6037 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6038 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xdddddddd,
6039 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6041 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
6042 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6043 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
6044 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6045 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
6046 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6048 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6049 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6051 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6052 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
6053 hr = IDirect3DDevice9_BeginScene(device);
6054 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6055 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6056 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6057 hr = IDirect3DDevice9_EndScene(device);
6058 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6060 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6061 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6062 for (i = 0; i < 500; ++i)
6064 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6065 break;
6066 Sleep(10);
6068 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6070 memset(timestamp, 0xff, sizeof(timestamp));
6071 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6072 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6073 ok(timestamp[1] == 0xffffffff,
6074 "Timestamp was modified outside of the expected size (0x%.8x).\n",
6075 timestamp[1]);
6077 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
6078 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6079 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6080 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6081 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6082 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6084 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
6085 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6086 for (i = 0; i < 500; ++i)
6088 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6089 break;
6090 Sleep(10);
6092 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6094 memset(disjoint, 0xff, sizeof(disjoint));
6095 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
6096 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6097 ok(disjoint[1] == 0xffff,
6098 "Disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
6099 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
6100 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6101 ok(disjoint[1] != 0xffff, "High bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
6103 /* It's not strictly necessary for the TIMESTAMP query to be inside
6104 * a TIMESTAMP_DISJOINT query. */
6105 hr = IDirect3DDevice9_BeginScene(device);
6106 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6107 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6108 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6109 hr = IDirect3DDevice9_EndScene(device);
6110 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6112 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6113 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6114 for (i = 0; i < 500; ++i)
6116 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6117 break;
6118 Sleep(10);
6120 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6121 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6122 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6124 IDirect3DQuery9_Release(query);
6125 IDirect3DQuery9_Release(disjoint_query);
6126 IDirect3DQuery9_Release(freq_query);
6127 refcount = IDirect3DDevice9_Release(device);
6128 ok(!refcount, "Device has %u references left.\n", refcount);
6129 IDirect3D9_Release(d3d9);
6130 DestroyWindow(window);
6133 static void test_get_set_vertex_shader(void)
6135 IDirect3DVertexShader9 *current_shader = NULL;
6136 IDirect3DVertexShader9 *shader = NULL;
6137 const IDirect3DVertexShader9Vtbl *shader_vtbl;
6138 IDirect3DDevice9 *device;
6139 ULONG refcount, i;
6140 IDirect3D9 *d3d;
6141 D3DCAPS9 caps;
6142 HWND window;
6143 HRESULT hr;
6145 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6146 0, 0, 640, 480, 0, 0, 0, 0);
6147 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6148 ok(!!d3d, "Failed to create a D3D object.\n");
6149 if (!(device = create_device(d3d, window, NULL)))
6151 skip("Failed to create a D3D device, skipping tests.\n");
6152 IDirect3D9_Release(d3d);
6153 DestroyWindow(window);
6154 return;
6157 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6158 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6159 if (!(caps.VertexShaderVersion & 0xffff))
6161 skip("No vertex shader support, skipping tests.\n");
6162 IDirect3DDevice9_Release(device);
6163 IDirect3D9_Release(d3d);
6164 DestroyWindow(window);
6165 return;
6168 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
6169 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6170 ok(!!shader, "Got unexpected shader %p.\n", shader);
6172 /* SetVertexShader() should not touch the shader's refcount. */
6173 i = get_refcount((IUnknown *)shader);
6174 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6175 refcount = get_refcount((IUnknown *)shader);
6176 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6177 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6179 /* GetVertexShader() should increase the shader's refcount by one. */
6180 i = refcount + 1;
6181 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
6182 refcount = get_refcount((IUnknown *)shader);
6183 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
6184 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6185 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6186 IDirect3DVertexShader9_Release(current_shader);
6188 /* SetVertexShader() with a bogus shader vtbl */
6189 shader_vtbl = shader->lpVtbl;
6190 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
6191 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6192 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6193 shader->lpVtbl = NULL;
6194 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6195 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6196 shader->lpVtbl = shader_vtbl;
6198 IDirect3DVertexShader9_Release(shader);
6199 refcount = IDirect3DDevice9_Release(device);
6200 ok(!refcount, "Device has %u references left.\n", refcount);
6201 IDirect3D9_Release(d3d);
6202 DestroyWindow(window);
6205 static void test_vertex_shader_constant(void)
6207 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};
6208 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6209 IDirect3DDevice9 *device;
6210 struct device_desc desc;
6211 DWORD consts_swvp;
6212 IDirect3D9 *d3d;
6213 ULONG refcount;
6214 D3DCAPS9 caps;
6215 DWORD consts;
6216 HWND window;
6217 HRESULT hr;
6219 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6220 0, 0, 640, 480, 0, 0, 0, 0);
6221 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6222 ok(!!d3d, "Failed to create a D3D object.\n");
6223 if (!(device = create_device(d3d, window, NULL)))
6225 skip("Failed to create a D3D device, skipping tests.\n");
6226 IDirect3D9_Release(d3d);
6227 DestroyWindow(window);
6228 return;
6231 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6232 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6233 if (!(caps.VertexShaderVersion & 0xffff))
6235 skip("No vertex shader support, skipping tests.\n");
6236 IDirect3DDevice9_Release(device);
6237 IDirect3D9_Release(d3d);
6238 DestroyWindow(window);
6239 return;
6241 consts = caps.MaxVertexShaderConst;
6243 /* A simple check that the stuff works at all. */
6244 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
6245 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6247 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
6248 * consts from MAX - 1. */
6249 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
6250 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6251 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6252 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6253 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6254 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6255 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6256 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6258 /* Constant -1. */
6259 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
6260 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6262 refcount = IDirect3DDevice9_Release(device);
6263 ok(!refcount, "Device has %u references left.\n", refcount);
6265 desc.device_window = window;
6266 desc.width = 640;
6267 desc.height = 480;
6268 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6270 if (!(device = create_device(d3d, window, &desc)))
6272 skip("Failed to create a D3D device, skipping tests.\n");
6273 IDirect3D9_Release(d3d);
6274 DestroyWindow(window);
6275 return;
6277 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6278 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6279 consts_swvp = caps.MaxVertexShaderConst;
6280 todo_wine
6281 ok(consts_swvp == 8192, "Unexpected consts_swvp %u.\n", consts_swvp);
6283 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6284 todo_wine
6285 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6286 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6287 todo_wine
6288 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6289 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6290 todo_wine
6291 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6292 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6293 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6294 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp, c, 1);
6295 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6297 refcount = IDirect3DDevice9_Release(device);
6298 ok(!refcount, "Device has %u references left.\n", refcount);
6300 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6301 if (!(device = create_device(d3d, window, &desc)))
6303 skip("Failed to create a D3D device, skipping tests.\n");
6304 IDirect3D9_Release(d3d);
6305 DestroyWindow(window);
6306 return;
6308 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6309 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6310 ok(consts == caps.MaxVertexShaderConst, "Unexpected caps.MaxVertexShaderConst %u, consts %u.\n",
6311 caps.MaxVertexShaderConst, consts);
6313 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6314 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6315 todo_wine
6316 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6317 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6318 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6320 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 1);
6322 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6323 todo_wine
6324 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6325 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6326 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6328 refcount = IDirect3DDevice9_Release(device);
6329 ok(!refcount, "Device has %u references left.\n", refcount);
6331 IDirect3D9_Release(d3d);
6332 DestroyWindow(window);
6335 static void test_get_set_pixel_shader(void)
6337 IDirect3DPixelShader9 *current_shader = NULL;
6338 IDirect3DPixelShader9 *shader = NULL;
6339 const IDirect3DPixelShader9Vtbl *shader_vtbl;
6340 IDirect3DDevice9 *device;
6341 ULONG refcount, i;
6342 IDirect3D9 *d3d;
6343 D3DCAPS9 caps;
6344 HWND window;
6345 HRESULT hr;
6347 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6348 0, 0, 640, 480, 0, 0, 0, 0);
6349 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6350 ok(!!d3d, "Failed to create a D3D object.\n");
6351 if (!(device = create_device(d3d, window, NULL)))
6353 skip("Failed to create a D3D device, skipping tests.\n");
6354 IDirect3D9_Release(d3d);
6355 DestroyWindow(window);
6356 return;
6359 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6360 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6361 if (!(caps.PixelShaderVersion & 0xffff))
6363 skip("No pixel shader support, skipping tests.\n");
6364 IDirect3DDevice9_Release(device);
6365 IDirect3D9_Release(d3d);
6366 DestroyWindow(window);
6367 return;
6370 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
6371 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6372 ok(!!shader, "Got unexpected shader %p.\n", shader);
6374 /* SetPixelShader() should not touch the shader's refcount. */
6375 i = get_refcount((IUnknown *)shader);
6376 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6377 refcount = get_refcount((IUnknown *)shader);
6378 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6379 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6381 /* GetPixelShader() should increase the shader's refcount by one. */
6382 i = refcount + 1;
6383 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6384 refcount = get_refcount((IUnknown *)shader);
6385 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6386 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6387 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6388 IDirect3DPixelShader9_Release(current_shader);
6390 /* SetPixelShader() with a bogus shader vtbl */
6391 shader_vtbl = shader->lpVtbl;
6392 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6393 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6394 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6395 shader->lpVtbl = NULL;
6396 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6397 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6398 shader->lpVtbl = shader_vtbl;
6400 IDirect3DPixelShader9_Release(shader);
6401 refcount = IDirect3DDevice9_Release(device);
6402 ok(!refcount, "Device has %u references left.\n", refcount);
6403 IDirect3D9_Release(d3d);
6404 DestroyWindow(window);
6407 static void test_pixel_shader_constant(void)
6409 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};
6410 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6411 IDirect3DDevice9 *device;
6412 DWORD consts = 0;
6413 IDirect3D9 *d3d;
6414 ULONG refcount;
6415 D3DCAPS9 caps;
6416 HWND window;
6417 HRESULT hr;
6419 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6420 0, 0, 640, 480, 0, 0, 0, 0);
6421 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6422 ok(!!d3d, "Failed to create a D3D object.\n");
6423 if (!(device = create_device(d3d, window, NULL)))
6425 skip("Failed to create a D3D device, skipping tests.\n");
6426 IDirect3D9_Release(d3d);
6427 DestroyWindow(window);
6428 return;
6431 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6432 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6433 if (!(caps.PixelShaderVersion & 0xffff))
6435 skip("No pixel shader support, skipping tests.\n");
6436 IDirect3DDevice9_Release(device);
6437 IDirect3D9_Release(d3d);
6438 DestroyWindow(window);
6439 return;
6442 /* A simple check that the stuff works at all. */
6443 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6444 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6446 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6447 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6448 consts = consts - 1;
6449 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6451 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6452 * pointless given the way the constant limit was determined. */
6453 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6454 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6456 /* Constant -1. */
6457 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6458 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6460 refcount = IDirect3DDevice9_Release(device);
6461 ok(!refcount, "Device has %u references left.\n", refcount);
6462 IDirect3D9_Release(d3d);
6463 DestroyWindow(window);
6466 static void test_unsupported_shaders(void)
6468 static const DWORD vs_3_0[] =
6470 0xfffe0300, /* vs_3_0 */
6471 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6472 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6473 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6474 0x0000ffff, /* end */
6477 #if 0
6478 float4 main(const float4 color : COLOR) : SV_TARGET
6480 float4 o;
6482 o = color;
6484 return o;
6486 #endif
6487 static const DWORD ps_4_0[] =
6489 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6490 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6491 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6492 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6493 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6494 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6495 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6496 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6497 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6498 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6499 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6500 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6501 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6502 0x00000000, 0x00000000, 0x00000000,
6504 #if 0
6505 vs_1_1
6506 dcl_position v0
6507 def c255, 1.0, 1.0, 1.0, 1.0
6508 add r0, v0, c255
6509 mov oPos, r0
6510 #endif
6511 static const DWORD vs_1_255[] =
6513 0xfffe0101,
6514 0x0000001f, 0x80000000, 0x900f0000,
6515 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6516 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6517 0x00000001, 0xc00f0000, 0x80e40000,
6518 0x0000ffff
6520 #if 0
6521 vs_1_1
6522 dcl_position v0
6523 def c256, 1.0, 1.0, 1.0, 1.0
6524 add r0, v0, c256
6525 mov oPos, r0
6526 #endif
6527 static const DWORD vs_1_256[] =
6529 0xfffe0101,
6530 0x0000001f, 0x80000000, 0x900f0000,
6531 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6532 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6533 0x00000001, 0xc00f0000, 0x80e40000,
6534 0x0000ffff
6536 #if 0
6537 vs_3_0
6538 dcl_position v0
6539 dcl_position o0
6540 def c256, 1.0, 1.0, 1.0, 1.0
6541 add r0, v0, c256
6542 mov o0, r0
6543 #endif
6544 static const DWORD vs_3_256[] =
6546 0xfffe0300,
6547 0x0200001f, 0x80000000, 0x900f0000,
6548 0x0200001f, 0x80000000, 0xe00f0000,
6549 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6550 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6551 0x02000001, 0xe00f0000, 0x80e40000,
6552 0x0000ffff
6554 #if 0
6555 /* This shader source generates syntax errors with the native shader assembler
6556 * due to the constant register index values.
6557 * The bytecode was modified by hand to use the intended values. */
6558 vs_3_0
6559 dcl_position v0
6560 dcl_position o0
6561 defi i16, 1, 1, 1, 1
6562 rep i16
6563 add r0, r0, v0
6564 endrep
6565 mov o0, r0
6566 #endif
6567 static const DWORD vs_3_i16[] =
6569 0xfffe0300,
6570 0x0200001f, 0x80000000, 0x900f0000,
6571 0x0200001f, 0x80000000, 0xe00f0000,
6572 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6573 0x01000026, 0xf0e40010,
6574 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6575 0x00000027,
6576 0x02000001, 0xe00f0000, 0x80e40000,
6577 0x0000ffff
6579 #if 0
6580 /* This shader source generates syntax errors with the native shader assembler
6581 * due to the constant register index values.
6582 * The bytecode was modified by hand to use the intended values. */
6583 vs_3_0
6584 dcl_position v0
6585 dcl_position o0
6586 defb b16, true
6587 mov r0, v0
6588 if b16
6589 add r0, r0, v0
6590 endif
6591 mov o0, r0
6592 #endif
6593 static const DWORD vs_3_b16[] =
6595 0xfffe0300,
6596 0x0200001f, 0x80000000, 0x900f0000,
6597 0x0200001f, 0x80000000, 0xe00f0000,
6598 0x0200002f, 0xe00f0810, 0x00000001,
6599 0x02000001, 0x800f0000, 0x90e40000,
6600 0x01000028, 0xe0e40810,
6601 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6602 0x0000002b,
6603 0x02000001, 0xe00f0000, 0x80e40000,
6604 0x0000ffff
6606 #if 0
6607 /* This shader source generates syntax errors with the native shader assembler
6608 * due to the constant register index values.
6609 * The bytecode was modified by hand to use the intended values. */
6610 ps_1_1
6611 def c8, 1.0, 1.0, 1.0, 1.0
6612 add r0, v0, c8
6613 #endif
6614 static const DWORD ps_1_8[] =
6616 0xffff0101,
6617 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6618 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6619 0x0000ffff
6621 #if 0
6622 /* This shader source generates syntax errors with the native shader assembler
6623 * due to the constant register index values.
6624 * The bytecode was modified by hand to use the intended values. */
6625 ps_2_0
6626 def c32, 1.0, 1.0, 1.0, 1.0
6627 add oC0, v0, c32
6628 #endif
6629 static const DWORD ps_2_32[] =
6631 0xffff0200,
6632 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6633 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6634 0x0000ffff
6636 #if 0
6637 /* This shader source generates syntax errors with the native shader assembler
6638 * due to the constant register index values.
6639 * The bytecode was modified by hand to use the intended values. */
6640 ps_3_0
6641 dcl_color0 v0
6642 def c224, 1.0, 1.0, 1.0, 1.0
6643 add oC0, v0, c224
6644 #endif
6645 static const DWORD ps_3_224[] =
6647 0xffff0300,
6648 0x0200001f, 0x8000000a, 0x900f0000,
6649 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6650 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6651 0x0000ffff
6653 #if 0
6654 /* This shader source generates syntax errors with the native shader assembler
6655 * due to the constant register index values.
6656 * The bytecode was modified by hand to use the intended values. */
6657 ps_2_0
6658 defb b0, true
6659 defi i0, 1, 1, 1, 1
6660 rep i0
6661 if b0
6662 add r0, r0, v0
6663 endif
6664 endrep
6665 mov oC0, r0
6666 #endif
6667 static const DWORD ps_2_0_boolint[] =
6669 0xffff0200,
6670 0x0200002f, 0xe00f0800, 0x00000001,
6671 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6672 0x01000026, 0xf0e40000,
6673 0x01000028, 0xe0e40800,
6674 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6675 0x0000002b,
6676 0x00000027,
6677 0x02000001, 0x800f0800, 0x80e40000,
6678 0x0000ffff
6681 IDirect3DVertexShader9 *vs = NULL;
6682 IDirect3DPixelShader9 *ps = NULL;
6683 IDirect3DDevice9 *device;
6684 struct device_desc desc;
6685 IDirect3D9 * d3d;
6686 ULONG refcount;
6687 D3DCAPS9 caps;
6688 HWND window;
6689 HRESULT hr;
6691 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6692 0, 0, 640, 480, 0, 0, 0, 0);
6693 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6694 ok(!!d3d, "Failed to create a D3D object.\n");
6695 if (!(device = create_device(d3d, window, NULL)))
6697 skip("Failed to create a D3D device, skipping tests.\n");
6698 IDirect3D9_Release(d3d);
6699 DestroyWindow(window);
6700 return;
6703 /* These should always fail, regardless of supported shader version. */
6704 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6705 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6706 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6707 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6708 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6709 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6711 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6712 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6713 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6715 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6716 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6717 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6719 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6720 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6722 else
6724 skip("GPU supports SM2+, skipping SM1 test.\n");
6727 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6729 else
6731 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6733 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6734 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6735 IDirect3DVertexShader9_Release(vs);
6736 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6737 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6738 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6739 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6740 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6741 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6742 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6743 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6746 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6748 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6749 goto cleanup;
6751 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6752 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6753 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6754 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6755 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6756 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6757 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6758 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6759 if (ps)
6760 IDirect3DPixelShader9_Release(ps);
6762 refcount = IDirect3DDevice9_Release(device);
6763 ok(!refcount, "Device has %u references left.\n", refcount);
6765 desc.device_window = window;
6766 desc.width = 640;
6767 desc.height = 480;
6768 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6770 if (!(device = create_device(d3d, window, &desc)))
6772 skip("Failed to create a D3D device, skipping tests.\n");
6773 IDirect3D9_Release(d3d);
6774 DestroyWindow(window);
6775 return;
6778 vs = NULL;
6779 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6780 todo_wine
6781 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6782 if (vs)
6783 IDirect3DVertexShader9_Release(vs);
6784 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6785 todo_wine
6786 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6787 if (vs)
6788 IDirect3DVertexShader9_Release(vs);
6790 refcount = IDirect3DDevice9_Release(device);
6791 ok(!refcount, "Device has %u references left.\n", refcount);
6793 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6794 if (!(device = create_device(d3d, window, &desc)))
6796 skip("Failed to create a D3D device, skipping tests.\n");
6797 IDirect3D9_Release(d3d);
6798 DestroyWindow(window);
6799 return;
6801 hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6802 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6804 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6805 todo_wine
6806 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6807 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6808 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6809 if (vs)
6810 IDirect3DVertexShader9_Release(vs);
6812 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6813 todo_wine
6814 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6815 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6816 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6817 if (vs)
6818 IDirect3DVertexShader9_Release(vs);
6820 cleanup:
6821 refcount = IDirect3DDevice9_Release(device);
6822 ok(!refcount, "Device has %u references left.\n", refcount);
6823 IDirect3D9_Release(d3d);
6824 DestroyWindow(window);
6827 /* Test the default texture stage state values */
6828 static void test_texture_stage_states(void)
6830 IDirect3DDevice9 *device;
6831 IDirect3D9 *d3d;
6832 unsigned int i;
6833 ULONG refcount;
6834 D3DCAPS9 caps;
6835 DWORD value;
6836 HWND window;
6837 HRESULT hr;
6839 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6840 0, 0, 640, 480, 0, 0, 0, 0);
6841 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6842 ok(!!d3d, "Failed to create a D3D object.\n");
6843 if (!(device = create_device(d3d, window, NULL)))
6845 skip("Failed to create a D3D device, skipping tests.\n");
6846 IDirect3D9_Release(d3d);
6847 DestroyWindow(window);
6848 return;
6851 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6852 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6854 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6856 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6857 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6858 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6859 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6860 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6861 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6862 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6863 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6864 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6865 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6866 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6867 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6868 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6869 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6870 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6871 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6872 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6873 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6874 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6875 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6876 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6877 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6878 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6879 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6880 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6881 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6882 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6883 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6884 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6885 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6886 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6887 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6888 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6889 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6890 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6891 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6892 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6893 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6894 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6895 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6896 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6897 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6898 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6899 ok(value == D3DTTFF_DISABLE,
6900 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6901 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6902 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6903 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6904 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6905 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6906 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6907 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6908 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6909 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6910 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6911 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6912 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6915 refcount = IDirect3DDevice9_Release(device);
6916 ok(!refcount, "Device has %u references left.\n", refcount);
6917 IDirect3D9_Release(d3d);
6918 DestroyWindow(window);
6921 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6923 IDirect3DCubeTexture9 *texture;
6924 IDirect3D9 *d3d;
6925 HRESULT hr;
6927 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6928 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6929 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6930 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6931 IDirect3D9_Release(d3d);
6932 if (hr != D3D_OK)
6934 skip("No cube mipmap generation support, skipping tests.\n");
6935 return;
6938 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6939 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6940 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6941 IDirect3DCubeTexture9_Release(texture);
6943 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6944 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6945 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6946 IDirect3DCubeTexture9_Release(texture);
6949 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6951 IDirect3DCubeTexture9 *texture;
6952 IDirect3DSurface9 *surface;
6953 D3DSURFACE_DESC desc;
6954 DWORD levels;
6955 HRESULT hr;
6956 D3DCAPS9 caps;
6958 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6959 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6960 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6961 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6963 skip("Failed to create cube texture, skipping tests.\n");
6964 return;
6967 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6968 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6969 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6970 else
6971 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6973 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6974 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6975 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6976 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6977 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6978 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6980 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6981 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6982 IDirect3DSurface9_Release(surface);
6983 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6984 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6985 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6986 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6988 IDirect3DCubeTexture9_Release(texture);
6991 static void test_cube_textures(void)
6993 IDirect3DCubeTexture9 *texture;
6994 IDirect3DDevice9 *device;
6995 IDirect3D9 *d3d;
6996 ULONG refcount;
6997 D3DCAPS9 caps;
6998 HWND window;
6999 HRESULT hr;
7001 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7002 0, 0, 640, 480, 0, 0, 0, 0);
7003 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7004 ok(!!d3d, "Failed to create a D3D object.\n");
7005 if (!(device = create_device(d3d, window, NULL)))
7007 skip("Failed to create a D3D device, skipping tests.\n");
7008 IDirect3D9_Release(d3d);
7009 DestroyWindow(window);
7010 return;
7013 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7014 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7016 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7018 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7019 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
7020 IDirect3DCubeTexture9_Release(texture);
7021 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7022 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
7023 IDirect3DCubeTexture9_Release(texture);
7024 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7025 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
7026 IDirect3DCubeTexture9_Release(texture);
7028 else
7030 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7031 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
7032 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7033 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
7034 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7035 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
7037 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
7038 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
7039 IDirect3DCubeTexture9_Release(texture);
7041 test_cube_texture_mipmap_gen(device);
7042 test_cube_texture_levels(device);
7044 refcount = IDirect3DDevice9_Release(device);
7045 ok(!refcount, "Device has %u references left.\n", refcount);
7046 IDirect3D9_Release(d3d);
7047 DestroyWindow(window);
7050 static void test_mipmap_gen(void)
7052 static const D3DFORMAT formats[] =
7054 D3DFMT_A8R8G8B8,
7055 D3DFMT_X8R8G8B8,
7056 D3DFMT_A1R5G5B5,
7057 D3DFMT_A4R4G4B4,
7058 D3DFMT_A8,
7059 D3DFMT_L8,
7060 D3DFMT_A8L8,
7061 D3DFMT_V8U8,
7062 D3DFMT_DXT5,
7064 D3DTEXTUREFILTERTYPE filter_type;
7065 IDirect3DTexture9 *texture;
7066 IDirect3DSurface9 *surface;
7067 IDirect3DDevice9 *device;
7068 unsigned int i, count;
7069 D3DSURFACE_DESC desc;
7070 D3DLOCKED_RECT lr;
7071 IDirect3D9 *d3d;
7072 BOOL renderable;
7073 ULONG refcount;
7074 DWORD levels;
7075 HWND window;
7076 HRESULT hr;
7078 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7079 ok(!!d3d, "Failed to create a D3D object.\n");
7081 for (i = 0; i < ARRAY_SIZE(formats); ++i)
7083 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7084 0, D3DRTYPE_TEXTURE, formats[i]);
7085 if (FAILED(hr))
7087 skip("Skipping unsupported format %#x.\n", formats[i]);
7088 continue;
7090 renderable = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7091 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, formats[i]));
7092 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7093 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, formats[i]);
7094 ok((hr == D3D_OK && renderable) || hr == D3DOK_NOAUTOGEN,
7095 "Got unexpected hr %#x for %srenderable format %#x.\n",
7096 hr, renderable ? "" : "non", formats[i]);
7099 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7100 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK)
7102 skip("No mipmap generation support, skipping tests.\n");
7103 IDirect3D9_Release(d3d);
7104 return;
7107 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7108 0, 0, 640, 480, 0, 0, 0, 0);
7109 if (!(device = create_device(d3d, window, NULL)))
7111 skip("Failed to create a D3D device, skipping tests.\n");
7112 IDirect3D9_Release(d3d);
7113 DestroyWindow(window);
7114 return;
7117 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
7118 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7119 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7120 IDirect3DTexture9_Release(texture);
7122 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7123 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7124 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7126 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7127 ok(filter_type == D3DTEXF_LINEAR, "Got unexpected filter_type %#x.\n", filter_type);
7128 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
7129 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7130 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
7131 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7132 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7133 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
7134 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
7135 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7137 levels = IDirect3DTexture9_GetLevelCount(texture);
7138 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7140 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
7142 surface = NULL;
7143 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
7144 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7145 if (surface)
7146 IDirect3DSurface9_Release(surface);
7148 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
7149 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7151 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
7152 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7153 if (SUCCEEDED(hr))
7155 hr = IDirect3DTexture9_UnlockRect(texture, i);
7156 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7159 IDirect3DTexture9_Release(texture);
7161 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
7162 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7163 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7164 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
7165 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7166 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7168 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
7169 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7170 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7171 levels = IDirect3DTexture9_GetLevelCount(texture);
7172 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7173 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7174 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7175 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7176 IDirect3DTexture9_Release(texture);
7178 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7179 D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, 0);
7180 ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr);
7182 for (i = 0; i < ARRAY_SIZE(formats); ++i)
7184 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7185 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, formats[i]);
7186 if (SUCCEEDED(hr))
7188 /* i.e. there is no difference between the D3D_OK and the
7189 * D3DOK_NOAUTOGEN cases. */
7190 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7191 formats[i], D3DPOOL_DEFAULT, &texture, 0);
7192 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7193 count = IDirect3DTexture9_GetLevelCount(texture);
7194 ok(count == 1, "Unexpected level count %u.\n", count);
7195 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7196 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7197 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7198 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7199 ok(filter_type == D3DTEXF_LINEAR, "Got unexpected filter_type %#x.\n", filter_type);
7200 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
7201 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7202 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7203 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
7204 IDirect3DTexture9_Release(texture);
7208 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
7209 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_WRAPANDMIP, D3DRTYPE_TEXTURE, D3DFMT_D16);
7210 if (hr == D3D_OK)
7212 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7213 D3DFMT_D16, D3DPOOL_DEFAULT, &texture, 0);
7214 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7215 count = IDirect3DTexture9_GetLevelCount(texture);
7216 ok(count == 7, "Unexpected level count %u.\n", count);
7217 IDirect3DTexture9_Release(texture);
7219 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
7220 D3DFMT_X8R8G8B8, D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_D16);
7221 ok(hr == D3DOK_NOAUTOGEN, "Unexpected hr %#x.\n", hr);
7222 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7223 D3DFMT_D16, D3DPOOL_DEFAULT, &texture, 0);
7224 ok(hr == D3D_OK, "Unexpected hr %#x.\n", hr);
7225 count = IDirect3DTexture9_GetLevelCount(texture);
7226 ok(count == 1, "Unexpected level count %u.\n", count);
7227 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc);
7228 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7229 ok(desc.Usage == D3DUSAGE_AUTOGENMIPMAP, "Got unexpected usage %#x.\n", desc.Usage);
7230 IDirect3DTexture9_Release(texture);
7232 else
7234 skip("Mipmapping not supported for D3DFMT_D16, skipping test.\n");
7237 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7238 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&texture, 0);
7239 ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr);
7241 refcount = IDirect3DDevice9_Release(device);
7242 ok(!refcount, "Device has %u references left.\n", refcount);
7243 IDirect3D9_Release(d3d);
7244 DestroyWindow(window);
7247 static void test_filter(void)
7249 static const struct
7251 DWORD magfilter, minfilter, mipfilter;
7252 BOOL has_texture;
7253 HRESULT result;
7255 tests[] =
7257 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7258 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7259 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7260 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
7261 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
7263 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7264 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7265 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
7266 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
7268 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7269 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7270 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
7271 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
7272 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
7274 IDirect3DTexture9 *texture;
7275 IDirect3DDevice9 *device;
7276 IDirect3D9 *d3d;
7277 unsigned int i;
7278 ULONG refcount;
7279 DWORD passes;
7280 HWND window;
7281 HRESULT hr;
7283 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7284 ok(!!d3d, "Failed to create a D3D object.\n");
7286 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7287 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7289 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
7290 IDirect3D9_Release(d3d);
7291 return;
7294 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7295 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7297 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
7298 IDirect3D9_Release(d3d);
7299 return;
7302 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7303 0, 0, 640, 480, 0, 0, 0, 0);
7304 if (!(device = create_device(d3d, window, NULL)))
7306 skip("Failed to create a D3D device, skipping tests.\n");
7307 IDirect3D9_Release(d3d);
7308 DestroyWindow(window);
7309 return;
7312 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
7313 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
7314 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7316 /* Needed for ValidateDevice(). */
7317 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7318 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
7320 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7322 if (tests[i].has_texture)
7324 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
7325 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7327 else
7329 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7330 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7333 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
7334 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7335 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
7336 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7337 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
7338 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7340 passes = 0xdeadbeef;
7341 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
7342 ok(hr == tests[i].result,
7343 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
7344 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
7345 tests[i].mipfilter, tests[i].has_texture);
7346 if (SUCCEEDED(hr))
7347 ok(!!passes, "Got unexpected passes %#x.\n", passes);
7348 else
7349 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
7352 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7353 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7354 IDirect3DTexture9_Release(texture);
7356 refcount = IDirect3DDevice9_Release(device);
7357 ok(!refcount, "Device has %u references left.\n", refcount);
7358 IDirect3D9_Release(d3d);
7359 DestroyWindow(window);
7362 static void test_get_set_texture(void)
7364 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
7365 IDirect3DBaseTexture9 *texture;
7366 IDirect3DDevice9 *device;
7367 IDirect3D9 *d3d;
7368 ULONG refcount;
7369 HWND window;
7370 HRESULT hr;
7372 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7373 0, 0, 640, 480, 0, 0, 0, 0);
7374 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7375 ok(!!d3d, "Failed to create a D3D object.\n");
7376 if (!(device = create_device(d3d, window, NULL)))
7378 skip("Failed to create a D3D device, skipping tests.\n");
7379 IDirect3D9_Release(d3d);
7380 DestroyWindow(window);
7381 return;
7384 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
7385 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7386 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7387 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
7388 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7389 ok(!texture, "Got unexpected texture %p.\n", texture);
7391 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
7392 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
7393 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7394 texture_vtbl = texture->lpVtbl;
7395 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
7396 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7397 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7398 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7399 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7400 texture->lpVtbl = NULL;
7401 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7402 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7403 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7404 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7405 texture->lpVtbl = texture_vtbl;
7406 IDirect3DBaseTexture9_Release(texture);
7408 refcount = IDirect3DDevice9_Release(device);
7409 ok(!refcount, "Device has %u references left.\n", refcount);
7410 IDirect3D9_Release(d3d);
7411 DestroyWindow(window);
7414 static void test_lod(void)
7416 IDirect3DTexture9 *texture;
7417 IDirect3DDevice9 *device;
7418 IDirect3D9 *d3d;
7419 ULONG refcount;
7420 HWND window;
7421 HRESULT hr;
7422 DWORD ret;
7424 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7425 0, 0, 640, 480, 0, 0, 0, 0);
7426 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7427 ok(!!d3d, "Failed to create a D3D object.\n");
7428 if (!(device = create_device(d3d, window, NULL)))
7430 skip("Failed to create a D3D device, skipping tests.\n");
7431 IDirect3D9_Release(d3d);
7432 DestroyWindow(window);
7433 return;
7436 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
7437 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7438 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7440 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
7441 * return a HRESULT, so it can't return a normal error. Instead, the call
7442 * is simply ignored. */
7443 ret = IDirect3DTexture9_SetLOD(texture, 0);
7444 ok(!ret, "Got unexpected ret %u.\n", ret);
7445 ret = IDirect3DTexture9_SetLOD(texture, 1);
7446 ok(!ret, "Got unexpected ret %u.\n", ret);
7447 ret = IDirect3DTexture9_SetLOD(texture, 2);
7448 ok(!ret, "Got unexpected ret %u.\n", ret);
7449 ret = IDirect3DTexture9_GetLOD(texture);
7450 ok(!ret, "Got unexpected ret %u.\n", ret);
7452 IDirect3DTexture9_Release(texture);
7453 refcount = IDirect3DDevice9_Release(device);
7454 ok(!refcount, "Device has %u references left.\n", refcount);
7455 IDirect3D9_Release(d3d);
7456 DestroyWindow(window);
7459 static void test_surface_get_container(void)
7461 IDirect3DTexture9 *texture = NULL;
7462 IDirect3DSurface9 *surface = NULL;
7463 IDirect3DDevice9 *device;
7464 IUnknown *container;
7465 IDirect3D9 *d3d;
7466 ULONG refcount;
7467 HWND window;
7468 HRESULT hr;
7470 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7471 0, 0, 640, 480, 0, 0, 0, 0);
7472 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7473 ok(!!d3d, "Failed to create a D3D object.\n");
7474 if (!(device = create_device(d3d, window, NULL)))
7476 skip("Failed to create a D3D device, skipping tests.\n");
7477 IDirect3D9_Release(d3d);
7478 DestroyWindow(window);
7479 return;
7482 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
7483 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7484 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7485 ok(!!texture, "Got unexpected texture %p.\n", texture);
7487 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7488 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7489 ok(!!surface, "Got unexpected surface %p.\n", surface);
7491 /* These should work... */
7492 container = NULL;
7493 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
7494 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7495 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7496 IUnknown_Release(container);
7498 container = NULL;
7499 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
7500 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7501 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7502 IUnknown_Release(container);
7504 container = NULL;
7505 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
7506 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7507 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7508 IUnknown_Release(container);
7510 container = NULL;
7511 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
7512 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7513 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7514 IUnknown_Release(container);
7516 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
7517 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
7518 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7519 ok(!container, "Got unexpected container %p.\n", container);
7521 IDirect3DSurface9_Release(surface);
7522 IDirect3DTexture9_Release(texture);
7523 refcount = IDirect3DDevice9_Release(device);
7524 ok(!refcount, "Device has %u references left.\n", refcount);
7525 IDirect3D9_Release(d3d);
7526 DestroyWindow(window);
7529 static void test_surface_alignment(void)
7531 IDirect3DSurface9 *surface;
7532 IDirect3DDevice9 *device;
7533 D3DLOCKED_RECT lr;
7534 unsigned int i, j;
7535 IDirect3D9 *d3d;
7536 ULONG refcount;
7537 HWND window;
7538 HRESULT hr;
7540 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7541 0, 0, 640, 480, 0, 0, 0, 0);
7542 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7543 ok(!!d3d, "Failed to create a D3D object.\n");
7544 if (!(device = create_device(d3d, window, NULL)))
7546 skip("Failed to create a D3D device, skipping tests.\n");
7547 IDirect3D9_Release(d3d);
7548 DestroyWindow(window);
7549 return;
7552 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7553 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7554 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7555 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7557 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7558 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7559 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7560 /* Some applications also depend on the exact pitch, rather than just the
7561 * alignment. */
7562 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7563 hr = IDirect3DSurface9_UnlockRect(surface);
7564 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7565 IDirect3DSurface9_Release(surface);
7567 for (i = 0; i < 5; ++i)
7569 IDirect3DTexture9 *texture;
7570 unsigned int level_count;
7571 D3DSURFACE_DESC desc;
7572 int expected_pitch;
7574 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7575 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7576 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7577 if (FAILED(hr))
7579 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7580 continue;
7583 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7584 for (j = 0; j < level_count; ++j)
7586 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7587 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7588 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7589 hr = IDirect3DTexture9_UnlockRect(texture, j);
7590 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7592 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7593 if (i > 0)
7594 expected_pitch <<= 1;
7595 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7596 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7598 IDirect3DTexture9_Release(texture);
7601 refcount = IDirect3DDevice9_Release(device);
7602 ok(!refcount, "Device has %u references left.\n", refcount);
7603 IDirect3D9_Release(d3d);
7604 DestroyWindow(window);
7607 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7608 * different from regular formats. This test verifies we return the correct
7609 * memory offsets. */
7610 static void test_lockrect_offset(void)
7612 static const struct
7614 D3DFORMAT format;
7615 const char *name;
7616 unsigned int block_width;
7617 unsigned int block_height;
7618 unsigned int block_size;
7620 dxt_formats[] =
7622 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7623 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7624 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7625 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7626 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7627 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7628 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7630 unsigned int expected_offset, offset, i;
7631 const RECT rect = {60, 60, 68, 68};
7632 IDirect3DSurface9 *surface;
7633 D3DLOCKED_RECT locked_rect;
7634 IDirect3DDevice9 *device;
7635 int expected_pitch;
7636 IDirect3D9 *d3d;
7637 ULONG refcount;
7638 HWND window;
7639 BYTE *base;
7640 HRESULT hr;
7642 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7643 0, 0, 640, 480, 0, 0, 0, 0);
7644 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7645 ok(!!d3d, "Failed to create a D3D object.\n");
7646 if (!(device = create_device(d3d, window, NULL)))
7648 skip("Failed to create a D3D device, skipping tests.\n");
7649 IDirect3D9_Release(d3d);
7650 DestroyWindow(window);
7651 return;
7654 for (i = 0; i < ARRAY_SIZE(dxt_formats); ++i)
7656 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7657 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7659 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7660 continue;
7663 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7664 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7665 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7667 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7668 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7670 base = locked_rect.pBits;
7671 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7672 * dxt_formats[i].block_size;
7673 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7674 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7676 hr = IDirect3DSurface9_UnlockRect(surface);
7677 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7679 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7680 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7682 offset = (BYTE *)locked_rect.pBits - base;
7683 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7684 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7685 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7686 offset, dxt_formats[i].name, expected_offset);
7688 hr = IDirect3DSurface9_UnlockRect(surface);
7689 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7691 IDirect3DSurface9_Release(surface);
7694 refcount = IDirect3DDevice9_Release(device);
7695 ok(!refcount, "Device has %u references left.\n", refcount);
7696 IDirect3D9_Release(d3d);
7697 DestroyWindow(window);
7700 static void test_lockrect_invalid(void)
7702 static const struct
7704 RECT rect;
7705 HRESULT win7_result;
7707 test_data[] =
7709 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7710 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7711 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7712 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7713 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7714 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7715 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7716 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7717 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7718 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7719 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7720 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7721 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7723 static const RECT test_rect_2 = {0, 0, 8, 8};
7724 IDirect3DSurface9 *surface = NULL;
7725 D3DLOCKED_RECT locked_rect;
7726 IDirect3DDevice9 *device;
7727 IDirect3DTexture9 *texture;
7728 IDirect3DCubeTexture9 *cube_texture;
7729 HRESULT hr, expected_hr;
7730 unsigned int i, r;
7731 IDirect3D9 *d3d;
7732 ULONG refcount;
7733 HWND window;
7734 BYTE *base;
7735 static const struct
7737 D3DRESOURCETYPE type;
7738 D3DPOOL pool;
7739 const char *name;
7741 resources[] =
7743 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7744 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7745 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7746 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7747 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7748 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7749 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7752 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7753 0, 0, 640, 480, 0, 0, 0, 0);
7754 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7755 ok(!!d3d, "Failed to create a D3D object.\n");
7756 if (!(device = create_device(d3d, window, NULL)))
7758 skip("Failed to create a D3D device, skipping tests.\n");
7759 IDirect3D9_Release(d3d);
7760 DestroyWindow(window);
7761 return;
7764 for (r = 0; r < ARRAY_SIZE(resources); ++r)
7766 texture = NULL;
7767 cube_texture = NULL;
7768 switch (resources[r].type)
7770 case D3DRTYPE_SURFACE:
7771 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7772 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7773 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7774 hr, resources[r].name);
7775 break;
7777 case D3DRTYPE_TEXTURE:
7778 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7779 resources[r].pool, &texture, NULL);
7780 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7781 hr, resources[r].name);
7782 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7783 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7784 hr, resources[r].name);
7785 break;
7787 case D3DRTYPE_CUBETEXTURE:
7788 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7789 resources[r].pool, &cube_texture, NULL);
7790 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7791 hr, resources[r].name);
7792 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7793 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7794 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7795 hr, resources[r].name);
7796 break;
7798 default:
7799 break;
7802 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7803 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7804 base = locked_rect.pBits;
7805 hr = IDirect3DSurface9_UnlockRect(surface);
7806 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7807 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
7808 hr = IDirect3DSurface9_UnlockRect(surface);
7809 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
7811 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7813 unsigned int offset, expected_offset;
7814 const RECT *rect = &test_data[i].rect;
7816 locked_rect.pBits = (BYTE *)0xdeadbeef;
7817 locked_rect.Pitch = 0xdeadbeef;
7819 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7820 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7821 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7822 * one broken. */
7823 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7824 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7825 wine_dbgstr_rect(rect), hr, resources[r].name);
7826 if (FAILED(hr))
7827 continue;
7829 offset = (BYTE *)locked_rect.pBits - base;
7830 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7831 ok(offset == expected_offset,
7832 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7833 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7835 hr = IDirect3DSurface9_UnlockRect(surface);
7836 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7838 if (texture)
7840 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7841 ok(SUCCEEDED(hr),
7842 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7843 wine_dbgstr_rect(rect), hr, resources[r].name);
7844 if (FAILED(hr))
7845 continue;
7847 offset = (BYTE *)locked_rect.pBits - base;
7848 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7849 ok(offset == expected_offset,
7850 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7851 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7853 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7854 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7856 if (cube_texture)
7858 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7859 &locked_rect, rect, 0);
7860 ok(SUCCEEDED(hr),
7861 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7862 wine_dbgstr_rect(rect), hr, resources[r].name);
7863 if (FAILED(hr))
7864 continue;
7866 offset = (BYTE *)locked_rect.pBits - base;
7867 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7868 ok(offset == expected_offset,
7869 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7870 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7872 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7873 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7877 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7878 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7879 locked_rect.pBits = (BYTE *)0xdeadbeef;
7880 locked_rect.Pitch = 1;
7881 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7882 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7883 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7884 locked_rect.pBits, resources[r].name);
7885 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7886 locked_rect.Pitch, resources[r].name);
7887 hr = IDirect3DSurface9_UnlockRect(surface);
7888 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7890 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7891 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7892 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7893 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7894 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7895 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7896 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7897 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7898 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7899 hr = IDirect3DSurface9_UnlockRect(surface);
7900 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7902 IDirect3DSurface9_Release(surface);
7904 if (texture)
7906 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7907 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7908 hr, resources[r].name);
7909 locked_rect.pBits = (BYTE *)0xdeadbeef;
7910 locked_rect.Pitch = 1;
7911 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7912 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7913 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7914 locked_rect.pBits, resources[r].name);
7915 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7916 locked_rect.Pitch, resources[r].name);
7917 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7918 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7919 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7920 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7921 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7922 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7924 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7925 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7926 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7927 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7928 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7929 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7930 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7931 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7932 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7933 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7934 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7936 IDirect3DTexture9_Release(texture);
7938 if (cube_texture)
7940 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7941 &locked_rect, NULL, 0);
7942 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7943 hr, resources[r].name);
7944 locked_rect.pBits = (BYTE *)0xdeadbeef;
7945 locked_rect.Pitch = 1;
7946 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7947 &locked_rect, NULL, 0);
7948 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7949 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7950 locked_rect.pBits, resources[r].name);
7951 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7952 locked_rect.Pitch, resources[r].name);
7953 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7954 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7955 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7956 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7957 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7958 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7960 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7961 &locked_rect, &test_data[0].rect, 0);
7962 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7963 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7964 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7965 &locked_rect, &test_data[0].rect, 0);
7966 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7967 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7968 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7969 &locked_rect, &test_rect_2, 0);
7970 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7971 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7972 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7973 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7975 IDirect3DCubeTexture9_Release(cube_texture);
7979 refcount = IDirect3DDevice9_Release(device);
7980 ok(!refcount, "Device has %u references left.\n", refcount);
7981 IDirect3D9_Release(d3d);
7982 DestroyWindow(window);
7985 static void test_private_data(void)
7987 ULONG refcount, expected_refcount;
7988 IDirect3DTexture9 *texture;
7989 IDirect3DSurface9 *surface, *surface2;
7990 IDirect3DDevice9 *device;
7991 IDirect3D9 *d3d;
7992 IUnknown *ptr;
7993 HWND window;
7994 HRESULT hr;
7995 DWORD size;
7996 DWORD data[4] = {1, 2, 3, 4};
7997 static const GUID d3d9_private_data_test_guid2 =
7999 0x2e5afac2,
8000 0x87b5,
8001 0x4c10,
8002 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
8005 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8006 0, 0, 640, 480, 0, 0, 0, 0);
8007 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8008 ok(!!d3d, "Failed to create a D3D object.\n");
8009 if (!(device = create_device(d3d, window, NULL)))
8011 skip("Failed to create a D3D device, skipping tests.\n");
8012 IDirect3D9_Release(d3d);
8013 DestroyWindow(window);
8014 return;
8017 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
8018 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8019 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8021 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8022 device, 0, D3DSPD_IUNKNOWN);
8023 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8024 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8025 device, 5, D3DSPD_IUNKNOWN);
8026 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8027 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8028 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
8029 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8031 /* A failing SetPrivateData call does not clear the old data with the same tag. */
8032 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
8033 sizeof(device), D3DSPD_IUNKNOWN);
8034 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8035 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
8036 sizeof(device) * 2, D3DSPD_IUNKNOWN);
8037 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8038 size = sizeof(ptr);
8039 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8040 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8041 IUnknown_Release(ptr);
8042 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8043 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8045 refcount = get_refcount((IUnknown *)device);
8046 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8047 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8048 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8049 expected_refcount = refcount + 1;
8050 refcount = get_refcount((IUnknown *)device);
8051 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8052 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8053 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8054 expected_refcount = refcount - 1;
8055 refcount = get_refcount((IUnknown *)device);
8056 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8058 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8059 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8060 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8061 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8062 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8063 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8064 refcount = get_refcount((IUnknown *)device);
8065 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8067 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
8068 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8069 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8070 size = 2 * sizeof(ptr);
8071 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8072 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8073 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8074 expected_refcount = refcount + 2;
8075 refcount = get_refcount((IUnknown *)device);
8076 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8077 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
8078 IUnknown_Release(ptr);
8079 expected_refcount--;
8081 ptr = (IUnknown *)0xdeadbeef;
8082 size = 1;
8083 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8084 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8085 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8086 size = 2 * sizeof(ptr);
8087 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8088 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8089 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8090 refcount = get_refcount((IUnknown *)device);
8091 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8092 size = 1;
8093 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8094 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8095 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8096 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8097 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
8098 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8099 size = 0xdeadbabe;
8100 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
8101 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8102 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8103 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
8104 /* GetPrivateData with size = NULL causes an access violation on Windows if the
8105 * requested data exists. */
8107 /* Destroying the surface frees the held reference. */
8108 IDirect3DSurface9_Release(surface);
8109 expected_refcount = refcount - 2;
8110 refcount = get_refcount((IUnknown *)device);
8111 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8113 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
8114 &texture, NULL);
8115 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8116 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8117 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
8118 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
8119 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
8121 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8122 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8124 memset(data, 0, sizeof(data));
8125 size = sizeof(data);
8126 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
8127 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8128 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
8129 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8130 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
8131 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
8133 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
8134 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8136 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8137 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8138 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
8139 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8141 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8142 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8144 IDirect3DSurface9_Release(surface2);
8145 IDirect3DSurface9_Release(surface);
8146 IDirect3DTexture9_Release(texture);
8148 refcount = IDirect3DDevice9_Release(device);
8149 ok(!refcount, "Device has %u references left.\n", refcount);
8150 IDirect3D9_Release(d3d);
8151 DestroyWindow(window);
8154 static void test_getdc(void)
8156 static const struct
8158 const char *name;
8159 D3DFORMAT format;
8160 unsigned int bit_count;
8161 DWORD mask_r, mask_g, mask_b;
8162 BOOL getdc_supported;
8164 testdata[] =
8166 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8167 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8168 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
8169 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8170 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8171 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
8172 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8173 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8174 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8175 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8176 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8177 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8178 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8179 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8180 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8181 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
8182 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8183 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8184 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8185 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8187 IDirect3DSurface9 *surface, *surface2;
8188 IDirect3DCubeTexture9 *cube_texture;
8189 struct device_desc device_desc;
8190 IDirect3DTexture9 *texture;
8191 IDirect3DDevice9 *device;
8192 D3DLOCKED_RECT map_desc;
8193 IDirect3D9 *d3d;
8194 unsigned int i;
8195 ULONG refcount;
8196 HWND window;
8197 HDC dc, dc2;
8198 HRESULT hr;
8200 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8201 0, 0, 640, 480, 0, 0, 0, 0);
8202 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8203 ok(!!d3d, "Failed to create a D3D object.\n");
8204 if (!(device = create_device(d3d, window, NULL)))
8206 skip("Failed to create a D3D device, skipping tests.\n");
8207 IDirect3D9_Release(d3d);
8208 DestroyWindow(window);
8209 return;
8212 for (i = 0; i < ARRAY_SIZE(testdata); ++i)
8214 texture = NULL;
8215 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8216 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
8217 if (FAILED(hr))
8219 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
8220 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
8221 if (FAILED(hr))
8223 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8224 continue;
8226 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8227 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8230 dc = (void *)0x1234;
8231 hr = IDirect3DSurface9_GetDC(surface, &dc);
8232 if (testdata[i].getdc_supported)
8233 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8234 else
8235 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8237 if (SUCCEEDED(hr))
8239 unsigned int width_bytes;
8240 DIBSECTION dib;
8241 HBITMAP bitmap;
8242 DWORD type;
8243 int size;
8245 type = GetObjectType(dc);
8246 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8247 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8248 type = GetObjectType(bitmap);
8249 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8251 size = GetObjectA(bitmap, sizeof(dib), &dib);
8252 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
8253 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
8254 dib.dsBm.bmType, testdata[i].name);
8255 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
8256 dib.dsBm.bmWidth, testdata[i].name);
8257 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
8258 dib.dsBm.bmHeight, testdata[i].name);
8259 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
8260 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
8261 dib.dsBm.bmWidthBytes, testdata[i].name);
8262 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
8263 dib.dsBm.bmPlanes, testdata[i].name);
8264 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
8265 "Got unexpected bit count %d for format %s.\n",
8266 dib.dsBm.bmBitsPixel, testdata[i].name);
8267 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
8268 dib.dsBm.bmBits, testdata[i].name);
8270 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
8271 dib.dsBmih.biSize, testdata[i].name);
8272 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
8273 dib.dsBmih.biHeight, testdata[i].name);
8274 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
8275 dib.dsBmih.biHeight, testdata[i].name);
8276 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
8277 dib.dsBmih.biPlanes, testdata[i].name);
8278 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
8279 dib.dsBmih.biBitCount, testdata[i].name);
8280 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
8281 "Got unexpected compression %#x for format %s.\n",
8282 dib.dsBmih.biCompression, testdata[i].name);
8283 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
8284 dib.dsBmih.biSizeImage, testdata[i].name);
8285 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
8286 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
8287 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
8288 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
8289 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
8290 dib.dsBmih.biClrUsed, testdata[i].name);
8291 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
8292 dib.dsBmih.biClrImportant, testdata[i].name);
8294 if (dib.dsBmih.biCompression == BI_BITFIELDS)
8296 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
8297 && dib.dsBitfields[2] == testdata[i].mask_b,
8298 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8299 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8301 else
8303 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
8304 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8305 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8307 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
8308 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
8310 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8311 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
8313 else
8315 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
8318 IDirect3DSurface9_Release(surface);
8319 if (texture)
8320 IDirect3DTexture9_Release(texture);
8322 if (!testdata[i].getdc_supported)
8323 continue;
8325 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
8326 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
8328 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8329 continue;
8332 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
8333 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8334 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
8335 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8337 hr = IDirect3DSurface9_GetDC(surface, &dc);
8338 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8339 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8340 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8341 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8342 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8343 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8344 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8346 hr = IDirect3DSurface9_GetDC(surface, &dc);
8347 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8348 dc2 = (void *)0x1234;
8349 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8350 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8351 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
8352 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8353 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8354 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8355 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8357 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8358 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8359 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8360 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8361 hr = IDirect3DSurface9_UnlockRect(surface);
8362 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8363 hr = IDirect3DSurface9_UnlockRect(surface);
8364 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8366 hr = IDirect3DSurface9_GetDC(surface, &dc);
8367 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8368 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8369 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8370 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8371 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8373 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8374 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8375 hr = IDirect3DSurface9_GetDC(surface, &dc);
8376 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8377 hr = IDirect3DSurface9_UnlockRect(surface);
8378 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8380 hr = IDirect3DSurface9_GetDC(surface, &dc);
8381 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8382 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
8383 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8384 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
8385 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8386 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8387 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8389 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8390 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8391 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8392 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8393 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
8394 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8395 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8396 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8398 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8399 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8400 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8401 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8402 hr = IDirect3DSurface9_UnlockRect(surface2);
8403 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8404 hr = IDirect3DSurface9_UnlockRect(surface);
8405 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8407 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8408 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8409 hr = IDirect3DSurface9_GetDC(surface, &dc);
8410 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8411 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8412 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8413 hr = IDirect3DSurface9_UnlockRect(surface);
8414 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8416 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8417 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8418 hr = IDirect3DSurface9_GetDC(surface, &dc);
8419 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8420 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8421 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8422 hr = IDirect3DSurface9_UnlockRect(surface2);
8423 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8425 hr = IDirect3DSurface9_GetDC(surface, &dc);
8426 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8427 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8428 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8429 hr = IDirect3DSurface9_UnlockRect(surface2);
8430 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8431 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8432 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8434 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8435 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8436 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8437 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8438 hr = IDirect3DSurface9_UnlockRect(surface);
8439 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8440 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8441 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8443 hr = IDirect3DSurface9_UnlockRect(surface);
8444 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8445 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8446 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8447 hr = IDirect3DSurface9_UnlockRect(surface);
8448 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8449 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8450 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8451 hr = IDirect3DSurface9_UnlockRect(surface);
8452 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8454 hr = IDirect3DSurface9_UnlockRect(surface2);
8455 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8456 hr = IDirect3DSurface9_GetDC(surface, &dc);
8457 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8458 hr = IDirect3DSurface9_UnlockRect(surface2);
8459 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8460 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8461 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8462 hr = IDirect3DSurface9_UnlockRect(surface2);
8463 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8465 IDirect3DSurface9_Release(surface2);
8466 IDirect3DSurface9_Release(surface);
8467 IDirect3DCubeTexture9_Release(cube_texture);
8470 refcount = IDirect3DDevice9_Release(device);
8471 ok(!refcount, "Device has %u references left.\n", refcount);
8473 /* Backbuffer created with D3DFMT_UNKNOWN format. */
8474 device_desc.width = 640;
8475 device_desc.height = 480;
8476 device_desc.device_window = window;
8477 device_desc.flags = CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT | CREATE_DEVICE_LOCKABLE_BACKBUFFER;
8479 device = create_device(d3d, window, &device_desc);
8480 ok(!!device, "Failed to create device.\n");
8482 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8483 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
8485 dc = NULL;
8486 hr = IDirect3DSurface9_GetDC(surface, &dc);
8487 ok(!!dc, "Unexpected DC returned.\n");
8488 ok(SUCCEEDED(hr), "Failed to get backbuffer DC, hr %#x.\n", hr);
8489 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8490 ok(SUCCEEDED(hr), "Failed to release backbuffer DC, hr %#x.\n", hr);
8492 IDirect3DSurface9_Release(surface);
8494 refcount = IDirect3DDevice9_Release(device);
8495 ok(!refcount, "Device has %u references left.\n", refcount);
8497 IDirect3D9_Release(d3d);
8498 DestroyWindow(window);
8501 static void test_surface_dimensions(void)
8503 IDirect3DSurface9 *surface;
8504 IDirect3DDevice9 *device;
8505 IDirect3D9 *d3d;
8506 ULONG refcount;
8507 HWND window;
8508 HRESULT hr;
8510 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8511 0, 0, 640, 480, 0, 0, 0, 0);
8512 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8513 ok(!!d3d, "Failed to create a D3D object.\n");
8514 if (!(device = create_device(d3d, window, NULL)))
8516 skip("Failed to create a D3D device, skipping tests.\n");
8517 IDirect3D9_Release(d3d);
8518 DestroyWindow(window);
8519 return;
8522 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8523 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8524 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8525 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8526 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8527 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8529 refcount = IDirect3DDevice9_Release(device);
8530 ok(!refcount, "Device has %u references left.\n", refcount);
8531 IDirect3D9_Release(d3d);
8532 DestroyWindow(window);
8535 static void test_surface_format_null(void)
8537 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8538 IDirect3DTexture9 *texture;
8539 IDirect3DSurface9 *surface;
8540 IDirect3DSurface9 *rt, *ds;
8541 D3DLOCKED_RECT locked_rect;
8542 IDirect3DDevice9 *device;
8543 D3DSURFACE_DESC desc;
8544 IDirect3D9 *d3d;
8545 ULONG refcount;
8546 HWND window;
8547 HRESULT hr;
8549 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8550 ok(!!d3d, "Failed to create a D3D object.\n");
8552 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8553 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8554 if (hr != D3D_OK)
8556 skip("No D3DFMT_NULL support, skipping test.\n");
8557 IDirect3D9_Release(d3d);
8558 return;
8561 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8562 0, 0, 640, 480, 0, 0, 0, 0);
8563 if (!(device = create_device(d3d, window, NULL)))
8565 skip("Failed to create a D3D device, skipping tests.\n");
8566 IDirect3D9_Release(d3d);
8567 DestroyWindow(window);
8568 return;
8571 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8572 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8573 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8575 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8576 D3DFMT_NULL, D3DFMT_D24S8);
8577 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8579 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8580 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8581 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8583 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8584 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8586 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8587 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8589 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8590 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8592 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8593 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8595 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8596 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8598 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8599 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8601 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8602 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8604 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8605 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8607 IDirect3DSurface9_Release(rt);
8608 IDirect3DSurface9_Release(ds);
8610 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8611 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8612 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8613 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8615 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8616 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8617 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8618 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8620 hr = IDirect3DSurface9_UnlockRect(surface);
8621 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8623 IDirect3DSurface9_Release(surface);
8625 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8626 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8627 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8628 IDirect3DTexture9_Release(texture);
8630 refcount = IDirect3DDevice9_Release(device);
8631 ok(!refcount, "Device has %u references left.\n", refcount);
8632 IDirect3D9_Release(d3d);
8633 DestroyWindow(window);
8636 static void test_surface_double_unlock(void)
8638 static const D3DPOOL pools[] =
8640 D3DPOOL_DEFAULT,
8641 D3DPOOL_SCRATCH,
8642 D3DPOOL_SYSTEMMEM,
8644 IDirect3DSurface9 *surface;
8645 IDirect3DDevice9 *device;
8646 D3DLOCKED_RECT lr;
8647 IDirect3D9 *d3d;
8648 unsigned int i;
8649 ULONG refcount;
8650 HWND window;
8651 HRESULT hr;
8653 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8654 0, 0, 640, 480, 0, 0, 0, 0);
8655 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8656 ok(!!d3d, "Failed to create a D3D object.\n");
8657 if (!(device = create_device(d3d, window, NULL)))
8659 skip("Failed to create a D3D device, skipping tests.\n");
8660 IDirect3D9_Release(d3d);
8661 DestroyWindow(window);
8662 return;
8665 for (i = 0; i < ARRAY_SIZE(pools); ++i)
8667 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8668 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8669 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8671 hr = IDirect3DSurface9_UnlockRect(surface);
8672 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8673 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8674 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8675 hr = IDirect3DSurface9_UnlockRect(surface);
8676 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8677 hr = IDirect3DSurface9_UnlockRect(surface);
8678 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8680 IDirect3DSurface9_Release(surface);
8683 refcount = IDirect3DDevice9_Release(device);
8684 ok(!refcount, "Device has %u references left.\n", refcount);
8685 IDirect3D9_Release(d3d);
8686 DestroyWindow(window);
8689 static void test_surface_blocks(void)
8691 static const struct
8693 D3DFORMAT fmt;
8694 const char *name;
8695 unsigned int block_width;
8696 unsigned int block_height;
8697 BOOL broken;
8698 BOOL create_size_checked, core_fmt;
8700 formats[] =
8702 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8703 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8704 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8705 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8706 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8707 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8708 * which doesn't match the format spec. On newer Nvidia cards
8709 * they have the correct 4x4 block size */
8710 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8711 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8712 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8713 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8715 static const struct
8717 D3DPOOL pool;
8718 const char *name;
8719 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8720 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8721 BOOL success;
8723 pools[] =
8725 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8726 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8727 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8728 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8730 static struct
8732 D3DRESOURCETYPE rtype;
8733 const char *type_name;
8734 D3DPOOL pool;
8735 const char *pool_name;
8736 BOOL need_driver_support, need_runtime_support;
8738 create_tests[] =
8740 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8741 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8742 /* Managed offscreen plain surfaces are not supported */
8743 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8745 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8746 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8747 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8748 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8750 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8751 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8752 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8753 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8755 IDirect3DTexture9 *texture;
8756 IDirect3DCubeTexture9 *cube_texture;
8757 IDirect3DSurface9 *surface;
8758 D3DLOCKED_RECT locked_rect;
8759 IDirect3DDevice9 *device;
8760 unsigned int i, j, k, w, h;
8761 BOOL surface_only;
8762 IDirect3D9 *d3d;
8763 ULONG refcount;
8764 HWND window;
8765 HRESULT hr;
8766 RECT rect;
8767 BOOL tex_pow2, cube_pow2;
8768 D3DCAPS9 caps;
8769 static const RECT invalid[] =
8771 {60, 60, 60, 68}, /* 0 height */
8772 {60, 60, 68, 60}, /* 0 width */
8773 {68, 60, 60, 68}, /* left > right */
8774 {60, 68, 68, 60}, /* top > bottom */
8775 {-8, 60, 0, 68}, /* left < surface */
8776 {60, -8, 68, 0}, /* top < surface */
8777 {-16, 60, -8, 68}, /* right < surface */
8778 {60, -16, 68, -8}, /* bottom < surface */
8779 {60, 60, 136, 68}, /* right > surface */
8780 {60, 60, 68, 136}, /* bottom > surface */
8781 {136, 60, 144, 68}, /* left > surface */
8782 {60, 136, 68, 144}, /* top > surface */
8785 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8786 0, 0, 640, 480, 0, 0, 0, 0);
8787 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8788 ok(!!d3d, "Failed to create a D3D object.\n");
8789 if (!(device = create_device(d3d, window, NULL)))
8791 skip("Failed to create a D3D device, skipping tests.\n");
8792 IDirect3D9_Release(d3d);
8793 DestroyWindow(window);
8794 return;
8797 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8798 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8799 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8800 if (tex_pow2)
8801 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8802 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8804 for (i = 0; i < ARRAY_SIZE(formats); ++i)
8806 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8808 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8809 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8810 tex_support = SUCCEEDED(hr);
8811 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8812 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8813 cube_support = SUCCEEDED(hr);
8814 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8815 0, D3DRTYPE_SURFACE, formats[i].fmt);
8816 surface_support = SUCCEEDED(hr);
8818 /* Scratch pool in general allows texture creation even if the driver does
8819 * not support the format. If the format is an extension format that is not
8820 * known to the runtime, like ATI2N, some driver support is required for
8821 * this to work.
8823 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8824 * about ATI2N. I cannot check this because all my Vista+ machines support
8825 * ATI2N in hardware, but none of my WinXP machines do. */
8826 format_known = tex_support || cube_support || surface_support;
8828 for (w = 1; w <= 8; w++)
8830 for (h = 1; h <= 8; h++)
8832 BOOL block_aligned = TRUE;
8833 BOOL size_is_pow2;
8835 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8836 block_aligned = FALSE;
8838 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8840 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
8842 BOOL support, pow2;
8843 HRESULT expect_hr;
8844 BOOL may_succeed = FALSE;
8845 IUnknown **check_null;
8847 if (!formats[i].core_fmt)
8849 /* AMD warns against creating ATI2N textures smaller than
8850 * the block size because the runtime cannot calculate the
8851 * correct texture size. Generalize this for all extension
8852 * formats. */
8853 if (w < formats[i].block_width || h < formats[i].block_height)
8854 continue;
8857 texture = (IDirect3DTexture9 *)0xdeadbeef;
8858 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8859 surface = (IDirect3DSurface9 *)0xdeadbeef;
8861 switch (create_tests[j].rtype)
8863 case D3DRTYPE_TEXTURE:
8864 check_null = (IUnknown **)&texture;
8865 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8866 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8867 support = tex_support;
8868 pow2 = tex_pow2;
8869 break;
8871 case D3DRTYPE_CUBETEXTURE:
8872 if (w != h)
8873 continue;
8874 check_null = (IUnknown **)&cube_texture;
8875 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8876 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8877 support = cube_support;
8878 pow2 = cube_pow2;
8879 break;
8881 case D3DRTYPE_SURFACE:
8882 check_null = (IUnknown **)&surface;
8883 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8884 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8885 support = surface_support;
8886 pow2 = FALSE;
8887 break;
8889 default:
8890 check_null = NULL;
8891 pow2 = FALSE;
8892 support = FALSE;
8893 break;
8896 if (create_tests[j].need_driver_support && !support)
8897 expect_hr = D3DERR_INVALIDCALL;
8898 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8899 expect_hr = D3DERR_INVALIDCALL;
8900 else if (formats[i].create_size_checked && !block_aligned)
8901 expect_hr = D3DERR_INVALIDCALL;
8902 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8903 expect_hr = D3DERR_INVALIDCALL;
8904 else
8905 expect_hr = D3D_OK;
8907 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8908 * does not support it. Accept scratch creation of extension formats on
8909 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8910 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8911 * support it. */
8912 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8913 may_succeed = TRUE;
8915 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8916 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8917 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8918 if (FAILED(hr))
8919 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8920 else
8921 IUnknown_Release(*check_null);
8926 surface_only = FALSE;
8927 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8928 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8929 dynamic_tex_support = SUCCEEDED(hr);
8930 if (!dynamic_tex_support)
8932 if (!surface_support)
8934 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8935 continue;
8937 surface_only = TRUE;
8940 for (j = 0; j < ARRAY_SIZE(pools); ++j)
8942 switch (pools[j].pool)
8944 case D3DPOOL_SYSTEMMEM:
8945 case D3DPOOL_MANAGED:
8946 if (surface_only)
8947 continue;
8948 /* Fall through */
8949 case D3DPOOL_DEFAULT:
8950 if (surface_only)
8952 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8953 formats[i].fmt, pools[j].pool, &surface, NULL);
8954 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8956 else
8958 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8959 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8960 formats[i].fmt, pools[j].pool, &texture, NULL);
8961 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8962 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8963 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8964 IDirect3DTexture9_Release(texture);
8966 break;
8968 case D3DPOOL_SCRATCH:
8969 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8970 formats[i].fmt, pools[j].pool, &surface, NULL);
8971 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8972 break;
8974 default:
8975 break;
8978 if (formats[i].block_width > 1)
8980 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8981 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8982 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8983 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8984 SUCCEEDED(hr) ? "succeeded" : "failed",
8985 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8986 if (SUCCEEDED(hr))
8988 hr = IDirect3DSurface9_UnlockRect(surface);
8989 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8992 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8993 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8994 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8995 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8996 SUCCEEDED(hr) ? "succeeded" : "failed",
8997 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8998 if (SUCCEEDED(hr))
9000 hr = IDirect3DSurface9_UnlockRect(surface);
9001 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9005 if (formats[i].block_height > 1)
9007 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
9008 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9009 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9010 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9011 SUCCEEDED(hr) ? "succeeded" : "failed",
9012 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9013 if (SUCCEEDED(hr))
9015 hr = IDirect3DSurface9_UnlockRect(surface);
9016 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9019 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
9020 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9021 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
9022 "Partial block lock %s, expected %s, format %s, pool %s.\n",
9023 SUCCEEDED(hr) ? "succeeded" : "failed",
9024 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
9025 if (SUCCEEDED(hr))
9027 hr = IDirect3DSurface9_UnlockRect(surface);
9028 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9032 for (k = 0; k < ARRAY_SIZE(invalid); ++k)
9034 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
9035 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
9036 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
9037 formats[i].name, pools[j].name, k);
9038 if (SUCCEEDED(hr))
9040 hr = IDirect3DSurface9_UnlockRect(surface);
9041 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9045 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
9046 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
9047 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
9048 hr = IDirect3DSurface9_UnlockRect(surface);
9049 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
9051 IDirect3DSurface9_Release(surface);
9054 if (!dynamic_tex_support)
9056 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
9057 continue;
9060 if (formats[i].block_width == 1 && formats[i].block_height == 1)
9061 continue;
9062 if (!formats[i].core_fmt)
9063 continue;
9065 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
9066 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
9067 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
9069 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
9070 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9071 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9072 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9074 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
9075 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
9076 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9077 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9078 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9079 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9081 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
9082 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9083 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9084 if (SUCCEEDED(hr))
9085 IDirect3DTexture9_UnlockRect(texture, 1);
9087 IDirect3DTexture9_Release(texture);
9090 refcount = IDirect3DDevice9_Release(device);
9091 ok(!refcount, "Device has %u references left.\n", refcount);
9092 IDirect3D9_Release(d3d);
9093 DestroyWindow(window);
9096 static void test_set_palette(void)
9098 IDirect3DDevice9 *device;
9099 IDirect3D9 *d3d9;
9100 UINT refcount;
9101 HWND window;
9102 HRESULT hr;
9103 PALETTEENTRY pal[256];
9104 unsigned int i;
9105 D3DCAPS9 caps;
9107 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9108 0, 0, 640, 480, 0, 0, 0, 0);
9109 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9110 ok(!!d3d9, "Failed to create a D3D object.\n");
9111 if (!(device = create_device(d3d9, window, NULL)))
9113 skip("Failed to create a D3D device, skipping tests.\n");
9114 DestroyWindow(window);
9115 return;
9118 for (i = 0; i < ARRAY_SIZE(pal); i++)
9120 pal[i].peRed = i;
9121 pal[i].peGreen = i;
9122 pal[i].peBlue = i;
9123 pal[i].peFlags = 0xff;
9125 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9126 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9128 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9129 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9130 for (i = 0; i < ARRAY_SIZE(pal); i++)
9132 pal[i].peRed = i;
9133 pal[i].peGreen = i;
9134 pal[i].peBlue = i;
9135 pal[i].peFlags = i;
9137 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
9139 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9140 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9142 else
9144 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9145 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
9148 refcount = IDirect3DDevice9_Release(device);
9149 ok(!refcount, "Device has %u references left.\n", refcount);
9150 IDirect3D9_Release(d3d9);
9151 DestroyWindow(window);
9154 static void test_swvp_buffer(void)
9156 IDirect3DDevice9 *device;
9157 IDirect3D9 *d3d9;
9158 UINT refcount;
9159 HWND window;
9160 HRESULT hr;
9161 unsigned int i;
9162 IDirect3DVertexBuffer9 *buffer;
9163 static const unsigned int bufsize = 1024;
9164 D3DVERTEXBUFFER_DESC desc;
9165 struct device_desc device_desc;
9166 struct
9168 float x, y, z;
9169 } *ptr, *ptr2;
9171 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9172 0, 0, 640, 480, 0, 0, 0, 0);
9173 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9174 ok(!!d3d9, "Failed to create a D3D object.\n");
9176 device_desc.device_window = window;
9177 device_desc.width = 640;
9178 device_desc.height = 480;
9179 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
9180 if (!(device = create_device(d3d9, window, &device_desc)))
9182 skip("Failed to create a D3D device, skipping tests.\n");
9183 DestroyWindow(window);
9184 IDirect3D9_Release(d3d9);
9185 return;
9188 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
9189 D3DPOOL_DEFAULT, &buffer, NULL);
9190 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9191 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9192 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9193 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
9194 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
9195 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
9197 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9198 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9199 for (i = 0; i < bufsize; i++)
9201 ptr[i].x = i * 1.0f;
9202 ptr[i].y = i * 2.0f;
9203 ptr[i].z = i * 3.0f;
9205 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9206 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9208 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9209 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9210 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9211 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9212 hr = IDirect3DDevice9_BeginScene(device);
9213 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9214 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9215 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9216 hr = IDirect3DDevice9_EndScene(device);
9217 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9219 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9220 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9221 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
9222 for (i = 0; i < bufsize; i++)
9224 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9226 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
9227 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9228 break;
9231 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9232 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9234 IDirect3DVertexBuffer9_Release(buffer);
9235 refcount = IDirect3DDevice9_Release(device);
9236 ok(!refcount, "Device has %u references left.\n", refcount);
9237 IDirect3D9_Release(d3d9);
9238 DestroyWindow(window);
9241 static void test_managed_buffer(void)
9243 static const unsigned int vertex_count = 1024;
9244 IDirect3DVertexBuffer9 *buffer;
9245 D3DVERTEXBUFFER_DESC desc;
9246 IDirect3DDevice9 *device;
9247 struct vec3 *ptr, *ptr2;
9248 IDirect3D9 *d3d9;
9249 unsigned int i;
9250 UINT refcount;
9251 HWND window;
9252 HRESULT hr;
9254 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9255 0, 0, 640, 480, 0, 0, 0, 0);
9256 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9257 ok(!!d3d9, "Failed to create a D3D object.\n");
9258 if (!(device = create_device(d3d9, window, NULL)))
9260 skip("Failed to create a D3D device, skipping tests.\n");
9261 IDirect3D9_Release(d3d9);
9262 DestroyWindow(window);
9263 return;
9266 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
9267 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
9268 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9269 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9270 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9271 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
9272 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
9274 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9275 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9276 for (i = 0; i < vertex_count; ++i)
9278 ptr[i].x = i * 1.0f;
9279 ptr[i].y = i * 2.0f;
9280 ptr[i].z = i * 3.0f;
9282 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9283 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9285 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9286 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9287 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9288 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9289 hr = IDirect3DDevice9_BeginScene(device);
9290 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9291 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9292 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9293 hr = IDirect3DDevice9_EndScene(device);
9294 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9296 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9297 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9298 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
9299 for (i = 0; i < vertex_count; ++i)
9301 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9303 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
9304 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9305 break;
9308 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9309 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9311 IDirect3DVertexBuffer9_Release(buffer);
9312 refcount = IDirect3DDevice9_Release(device);
9313 ok(!refcount, "Device has %u references left.\n", refcount);
9314 IDirect3D9_Release(d3d9);
9315 DestroyWindow(window);
9318 static void test_npot_textures(void)
9320 IDirect3DDevice9 *device = NULL;
9321 IDirect3D9 *d3d9;
9322 ULONG refcount;
9323 HWND window = NULL;
9324 HRESULT hr;
9325 D3DCAPS9 caps;
9326 IDirect3DTexture9 *texture;
9327 IDirect3DCubeTexture9 *cube_texture;
9328 IDirect3DVolumeTexture9 *volume_texture;
9329 struct
9331 D3DPOOL pool;
9332 const char *pool_name;
9333 HRESULT hr;
9335 pools[] =
9337 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
9338 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
9339 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
9340 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
9342 unsigned int i, levels;
9343 BOOL tex_pow2, cube_pow2, vol_pow2;
9345 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9346 0, 0, 640, 480, 0, 0, 0, 0);
9347 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9348 ok(!!d3d9, "Failed to create a D3D object.\n");
9349 if (!(device = create_device(d3d9, window, NULL)))
9351 skip("Failed to create a D3D device, skipping tests.\n");
9352 goto done;
9355 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9356 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9357 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
9358 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
9359 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9360 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
9361 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
9363 for (i = 0; i < ARRAY_SIZE(pools); i++)
9365 for (levels = 0; levels <= 2; levels++)
9367 HRESULT expected;
9369 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
9370 pools[i].pool, &texture, NULL);
9371 if (!tex_pow2)
9373 expected = D3D_OK;
9375 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
9377 if (levels == 1)
9378 expected = D3D_OK;
9379 else
9380 expected = pools[i].hr;
9382 else
9384 expected = pools[i].hr;
9386 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
9387 pools[i].pool_name, levels, hr, expected);
9389 if (SUCCEEDED(hr))
9390 IDirect3DTexture9_Release(texture);
9393 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9394 &cube_texture, NULL);
9395 if (tex_pow2)
9397 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9398 pools[i].pool_name, hr, pools[i].hr);
9400 else
9402 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9403 pools[i].pool_name, hr, D3D_OK);
9406 if (SUCCEEDED(hr))
9407 IDirect3DCubeTexture9_Release(cube_texture);
9409 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9410 &volume_texture, NULL);
9411 if (tex_pow2)
9413 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9414 pools[i].pool_name, hr, pools[i].hr);
9416 else
9418 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9419 pools[i].pool_name, hr, D3D_OK);
9422 if (SUCCEEDED(hr))
9423 IDirect3DVolumeTexture9_Release(volume_texture);
9426 done:
9427 if (device)
9429 refcount = IDirect3DDevice9_Release(device);
9430 ok(!refcount, "Device has %u references left.\n", refcount);
9432 IDirect3D9_Release(d3d9);
9433 DestroyWindow(window);
9437 static void test_vidmem_accounting(void)
9439 IDirect3DDevice9 *device;
9440 IDirect3D9 *d3d9;
9441 ULONG refcount;
9442 HWND window;
9443 HRESULT hr = D3D_OK;
9444 IDirect3DTexture9 *textures[20];
9445 unsigned int i;
9446 UINT vidmem_start, vidmem_end, diff;
9448 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9449 0, 0, 640, 480, 0, 0, 0, 0);
9450 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9451 ok(!!d3d9, "Failed to create a D3D object.\n");
9452 if (!(device = create_device(d3d9, window, NULL)))
9454 skip("Failed to create a D3D device, skipping tests.\n");
9455 IDirect3D9_Release(d3d9);
9456 DestroyWindow(window);
9457 return;
9460 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
9461 memset(textures, 0, sizeof(textures));
9462 for (i = 0; i < ARRAY_SIZE(textures); i++)
9464 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9465 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9466 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9467 * E_FAIL is returned on address space or system memory exhaustion */
9468 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9469 "Failed to create texture, hr %#x.\n", hr);
9471 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9473 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9474 diff = vidmem_start - vidmem_end;
9475 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9476 2 * i, diff / 1024 / 1024);
9478 for (i = 0; i < ARRAY_SIZE(textures); i++)
9480 if (textures[i])
9481 IDirect3DTexture9_Release(textures[i]);
9484 refcount = IDirect3DDevice9_Release(device);
9485 ok(!refcount, "Device has %u references left.\n", refcount);
9486 IDirect3D9_Release(d3d9);
9487 DestroyWindow(window);
9490 static void test_volume_locking(void)
9492 IDirect3DDevice9 *device;
9493 IDirect3D9 *d3d9;
9494 HWND window;
9495 HRESULT hr;
9496 IDirect3DVolumeTexture9 *texture;
9497 unsigned int i;
9498 D3DLOCKED_BOX locked_box;
9499 ULONG refcount;
9500 D3DCAPS9 caps;
9501 static const struct
9503 D3DPOOL pool;
9504 DWORD usage;
9505 HRESULT create_hr, lock_hr;
9507 tests[] =
9509 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9510 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9511 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9512 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9513 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9514 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9515 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9516 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9519 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9520 0, 0, 640, 480, 0, 0, 0, 0);
9521 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9522 ok(!!d3d9, "Failed to create a D3D object.\n");
9523 if (!(device = create_device(d3d9, window, NULL)))
9525 skip("Failed to create a D3D device, skipping tests.\n");
9526 IDirect3D9_Release(d3d9);
9527 DestroyWindow(window);
9528 return;
9531 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9532 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9533 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9535 skip("Volume textures not supported, skipping test.\n");
9536 goto out;
9539 for (i = 0; i < ARRAY_SIZE(tests); i++)
9541 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9542 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9543 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9544 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9545 if (FAILED(hr))
9546 continue;
9548 locked_box.pBits = (void *)0xdeadbeef;
9549 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9550 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9551 if (SUCCEEDED(hr))
9553 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9554 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9556 else
9558 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9560 IDirect3DVolumeTexture9_Release(texture);
9563 out:
9564 refcount = IDirect3DDevice9_Release(device);
9565 ok(!refcount, "Device has %u references left.\n", refcount);
9566 IDirect3D9_Release(d3d9);
9567 DestroyWindow(window);
9570 static void test_update_volumetexture(void)
9572 IDirect3DDevice9 *device;
9573 IDirect3D9 *d3d9;
9574 HWND window;
9575 HRESULT hr;
9576 IDirect3DVolumeTexture9 *src, *dst;
9577 unsigned int i;
9578 D3DLOCKED_BOX locked_box;
9579 ULONG refcount;
9580 D3DCAPS9 caps;
9581 static const struct
9583 D3DPOOL src_pool, dst_pool;
9584 HRESULT hr;
9586 tests[] =
9588 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9589 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9590 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9591 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9593 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9594 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9595 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9596 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9598 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9599 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9600 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9601 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9603 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9604 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9605 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9606 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9608 static const struct
9610 UINT src_size, dst_size;
9611 UINT src_lvl, dst_lvl;
9612 D3DFORMAT src_fmt, dst_fmt;
9614 tests2[] =
9616 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9617 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9618 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9619 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9620 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9621 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9622 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9623 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9626 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9627 0, 0, 640, 480, 0, 0, 0, 0);
9628 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9629 ok(!!d3d9, "Failed to create a D3D object.\n");
9630 if (!(device = create_device(d3d9, window, NULL)))
9632 skip("Failed to create a D3D device, skipping tests.\n");
9633 IDirect3D9_Release(d3d9);
9634 DestroyWindow(window);
9635 return;
9638 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9639 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9640 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9642 skip("Volume textures not supported, skipping test.\n");
9643 goto out;
9646 for (i = 0; i < ARRAY_SIZE(tests); i++)
9648 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9649 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9651 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9652 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9653 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9654 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9655 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9656 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9658 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9659 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9660 *((DWORD *)locked_box.pBits) = 0x11223344;
9661 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9662 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9664 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9665 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9666 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9668 if (SUCCEEDED(hr))
9670 DWORD content = *((DWORD *)locked_box.pBits);
9671 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9672 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9673 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9674 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9675 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9677 IDirect3DVolumeTexture9_Release(src);
9678 IDirect3DVolumeTexture9_Release(dst);
9681 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9683 skip("Mipmapped volume maps not supported.\n");
9684 goto out;
9687 for (i = 0; i < ARRAY_SIZE(tests2); i++)
9689 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9690 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9691 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9692 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9693 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9694 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9695 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9696 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9698 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9699 todo_wine_if (FAILED(hr))
9700 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9702 IDirect3DVolumeTexture9_Release(src);
9703 IDirect3DVolumeTexture9_Release(dst);
9706 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9707 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9708 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9709 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9710 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9712 * I'm not adding tests for this behavior until an application needs it. */
9714 out:
9715 refcount = IDirect3DDevice9_Release(device);
9716 ok(!refcount, "Device has %u references left.\n", refcount);
9717 IDirect3D9_Release(d3d9);
9718 DestroyWindow(window);
9721 static void test_create_rt_ds_fail(void)
9723 IDirect3DDevice9 *device;
9724 HWND window;
9725 HRESULT hr;
9726 ULONG refcount;
9727 IDirect3D9 *d3d9;
9728 IDirect3DSurface9 *surface;
9730 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9731 0, 0, 640, 480, 0, 0, 0, 0);
9732 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9733 ok(!!d3d9, "Failed to create a D3D object.\n");
9734 if (!(device = create_device(d3d9, window, NULL)))
9736 skip("Failed to create a D3D device, skipping tests.\n");
9737 IDirect3D9_Release(d3d9);
9738 DestroyWindow(window);
9739 return;
9742 /* Output pointer == NULL segfaults on Windows. */
9744 surface = (IDirect3DSurface9 *)0xdeadbeef;
9745 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9746 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9747 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9748 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9749 if (SUCCEEDED(hr))
9750 IDirect3DSurface9_Release(surface);
9752 surface = (IDirect3DSurface9 *)0xdeadbeef;
9753 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9754 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9755 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9756 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9757 if (SUCCEEDED(hr))
9758 IDirect3DSurface9_Release(surface);
9760 refcount = IDirect3DDevice9_Release(device);
9761 ok(!refcount, "Device has %u references left.\n", refcount);
9762 IDirect3D9_Release(d3d9);
9763 DestroyWindow(window);
9766 static void test_volume_blocks(void)
9768 IDirect3DDevice9 *device;
9769 IDirect3D9 *d3d9;
9770 UINT refcount;
9771 HWND window;
9772 HRESULT hr;
9773 D3DCAPS9 caps;
9774 IDirect3DVolumeTexture9 *texture;
9775 unsigned int w, h, d, i, j;
9776 static const struct
9778 D3DFORMAT fmt;
9779 const char *name;
9780 unsigned int block_width;
9781 unsigned int block_height;
9782 unsigned int block_depth;
9783 unsigned int block_size;
9784 unsigned int broken;
9785 BOOL create_size_checked, core_fmt;
9787 formats[] =
9789 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9790 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9791 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9792 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9793 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9794 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9795 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9796 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9797 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9798 * which doesn't match the format spec. On newer Nvidia cards
9799 * it has the correct 4x4 block size.
9800 * ATI1N volume textures are only supported by AMD GPUs right
9801 * now and locking offsets seem just wrong. */
9802 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9803 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9804 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9805 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9807 static const struct
9809 D3DPOOL pool;
9810 const char *name;
9811 BOOL need_driver_support, need_runtime_support;
9813 create_tests[] =
9815 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9816 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9817 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9818 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9820 static const struct
9822 unsigned int x, y, z, x2, y2, z2;
9824 offset_tests[] =
9826 {0, 0, 0, 8, 8, 8},
9827 {0, 0, 3, 8, 8, 8},
9828 {0, 4, 0, 8, 8, 8},
9829 {0, 4, 3, 8, 8, 8},
9830 {4, 0, 0, 8, 8, 8},
9831 {4, 0, 3, 8, 8, 8},
9832 {4, 4, 0, 8, 8, 8},
9833 {4, 4, 3, 8, 8, 8},
9835 D3DBOX box;
9836 D3DLOCKED_BOX locked_box;
9837 BYTE *base;
9838 INT expected_row_pitch, expected_slice_pitch;
9839 BOOL support;
9840 BOOL pow2;
9841 unsigned int offset, expected_offset;
9843 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9844 0, 0, 640, 480, 0, 0, 0, 0);
9845 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9846 ok(!!d3d9, "Failed to create a D3D object.\n");
9847 if (!(device = create_device(d3d9, window, NULL)))
9849 skip("Failed to create a D3D device, skipping tests.\n");
9850 IDirect3D9_Release(d3d9);
9851 DestroyWindow(window);
9852 return;
9854 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9855 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9856 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9858 for (i = 0; i < ARRAY_SIZE(formats); i++)
9860 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9861 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9862 support = SUCCEEDED(hr);
9864 /* Test creation restrictions */
9865 for (w = 1; w <= 8; w++)
9867 for (h = 1; h <= 8; h++)
9869 for (d = 1; d <= 8; d++)
9871 HRESULT expect_hr;
9872 BOOL size_is_pow2;
9873 BOOL block_aligned = TRUE;
9875 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9876 block_aligned = FALSE;
9878 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9880 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
9882 BOOL may_succeed = FALSE;
9884 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9885 expect_hr = D3DERR_INVALIDCALL;
9886 else if (formats[i].create_size_checked && !block_aligned)
9887 expect_hr = D3DERR_INVALIDCALL;
9888 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9889 expect_hr = D3DERR_INVALIDCALL;
9890 else if (create_tests[j].need_driver_support && !support)
9891 expect_hr = D3DERR_INVALIDCALL;
9892 else
9893 expect_hr = D3D_OK;
9895 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9896 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9897 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9899 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9900 * does not support it. Accept scratch creation of extension formats on
9901 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9902 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9903 * support it. */
9904 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9905 may_succeed = TRUE;
9907 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9908 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9909 hr, formats[i].name, create_tests[j].name, w, h, d);
9911 if (FAILED(hr))
9912 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9913 else
9914 IDirect3DVolumeTexture9_Release(texture);
9920 if (!support && !formats[i].core_fmt)
9921 continue;
9923 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9924 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9925 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9927 /* Test lockrect offset */
9928 for (j = 0; j < ARRAY_SIZE(offset_tests); j++)
9930 unsigned int bytes_per_pixel;
9931 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9933 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9934 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9936 base = locked_box.pBits;
9937 if (formats[i].broken == 1)
9939 expected_row_pitch = bytes_per_pixel * 24;
9941 else if (formats[i].broken == 2)
9943 expected_row_pitch = 24;
9945 else
9947 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9948 * formats[i].block_size;
9950 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9951 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9953 if (formats[i].broken)
9955 expected_slice_pitch = expected_row_pitch * 8;
9957 else
9959 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9960 * expected_row_pitch;
9962 ok(locked_box.SlicePitch == expected_slice_pitch,
9963 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9964 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9966 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9967 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9969 box.Left = offset_tests[j].x;
9970 box.Top = offset_tests[j].y;
9971 box.Front = offset_tests[j].z;
9972 box.Right = offset_tests[j].x2;
9973 box.Bottom = offset_tests[j].y2;
9974 box.Back = offset_tests[j].z2;
9975 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9976 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9978 offset = (BYTE *)locked_box.pBits - base;
9979 if (formats[i].broken == 1)
9981 expected_offset = box.Front * expected_slice_pitch
9982 + box.Top * expected_row_pitch
9983 + box.Left * bytes_per_pixel;
9985 else if (formats[i].broken == 2)
9987 expected_offset = box.Front * expected_slice_pitch
9988 + box.Top * expected_row_pitch
9989 + box.Left;
9991 else
9993 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9994 + (box.Top / formats[i].block_height) * expected_row_pitch
9995 + (box.Left / formats[i].block_width) * formats[i].block_size;
9997 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9998 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
10000 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10001 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10004 /* Test partial block locks */
10005 box.Front = 0;
10006 box.Back = 1;
10007 if (formats[i].block_width > 1)
10009 box.Left = formats[i].block_width >> 1;
10010 box.Top = 0;
10011 box.Right = formats[i].block_width;
10012 box.Bottom = formats[i].block_height;
10013 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10014 ok(FAILED(hr) || broken(formats[i].broken),
10015 "Partial block lock succeeded, expected failure, format %s.\n",
10016 formats[i].name);
10017 if (SUCCEEDED(hr))
10019 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10020 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10023 box.Left = 0;
10024 box.Top = 0;
10025 box.Right = formats[i].block_width >> 1;
10026 box.Bottom = formats[i].block_height;
10027 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10028 ok(FAILED(hr) || broken(formats[i].broken),
10029 "Partial block lock succeeded, expected failure, format %s.\n",
10030 formats[i].name);
10031 if (SUCCEEDED(hr))
10033 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10034 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10038 if (formats[i].block_height > 1)
10040 box.Left = 0;
10041 box.Top = formats[i].block_height >> 1;
10042 box.Right = formats[i].block_width;
10043 box.Bottom = formats[i].block_height;
10044 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10045 ok(FAILED(hr) || broken(formats[i].broken),
10046 "Partial block lock succeeded, expected failure, format %s.\n",
10047 formats[i].name);
10048 if (SUCCEEDED(hr))
10050 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10051 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10054 box.Left = 0;
10055 box.Top = 0;
10056 box.Right = formats[i].block_width;
10057 box.Bottom = formats[i].block_height >> 1;
10058 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10059 ok(FAILED(hr) || broken(formats[i].broken),
10060 "Partial block lock succeeded, expected failure, format %s.\n",
10061 formats[i].name);
10062 if (SUCCEEDED(hr))
10064 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10065 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10069 /* Test full block lock */
10070 box.Left = 0;
10071 box.Top = 0;
10072 box.Right = formats[i].block_width;
10073 box.Bottom = formats[i].block_height;
10074 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10075 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10076 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10077 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10079 IDirect3DVolumeTexture9_Release(texture);
10081 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
10082 * does not allocate surfaces smaller than the blocksize properly. */
10083 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
10085 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
10086 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
10087 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10089 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
10090 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10091 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10092 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10094 box.Left = box.Top = box.Front = 0;
10095 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
10096 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
10097 box.Back = 1;
10098 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10099 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10100 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10101 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10103 box.Right = formats[i].block_width;
10104 box.Bottom = formats[i].block_height;
10105 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10106 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10107 if (SUCCEEDED(hr))
10108 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10110 IDirect3DVolumeTexture9_Release(texture);
10114 refcount = IDirect3DDevice9_Release(device);
10115 ok(!refcount, "Device has %u references left.\n", refcount);
10116 IDirect3D9_Release(d3d9);
10117 DestroyWindow(window);
10120 static void test_lockbox_invalid(void)
10122 static const struct
10124 D3DBOX box;
10125 HRESULT result;
10127 test_data[] =
10129 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
10130 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
10131 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
10132 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
10133 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
10134 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
10135 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
10136 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
10137 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
10138 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
10139 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
10140 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
10141 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
10142 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
10144 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
10145 IDirect3DVolumeTexture9 *texture = NULL;
10146 D3DLOCKED_BOX locked_box;
10147 IDirect3DDevice9 *device;
10148 IDirect3D9 *d3d;
10149 unsigned int i;
10150 ULONG refcount;
10151 HWND window;
10152 BYTE *base;
10153 HRESULT hr;
10155 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10156 0, 0, 640, 480, 0, 0, 0, 0);
10157 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10158 ok(!!d3d, "Failed to create a D3D object.\n");
10159 if (!(device = create_device(d3d, window, NULL)))
10161 skip("Failed to create a D3D device, skipping tests.\n");
10162 IDirect3D9_Release(d3d);
10163 DestroyWindow(window);
10164 return;
10167 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
10168 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
10169 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10170 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10171 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10172 base = locked_box.pBits;
10173 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10174 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10176 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10178 unsigned int offset, expected_offset;
10179 const D3DBOX *box = &test_data[i].box;
10181 locked_box.pBits = (BYTE *)0xdeadbeef;
10182 locked_box.RowPitch = 0xdeadbeef;
10183 locked_box.SlicePitch = 0xdeadbeef;
10185 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
10186 /* Unlike surfaces, volumes properly check the box even in Windows XP */
10187 ok(hr == test_data[i].result,
10188 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
10189 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
10190 test_data[i].result);
10191 if (FAILED(hr))
10192 continue;
10194 offset = (BYTE *)locked_box.pBits - base;
10195 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
10196 ok(offset == expected_offset,
10197 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
10198 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
10200 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10201 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10204 /* locked_box = NULL throws an exception on Windows */
10205 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10206 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10207 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10208 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10209 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10210 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10211 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10212 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10214 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10215 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10216 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10217 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10218 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10219 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10220 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10221 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10222 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
10223 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10224 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
10225 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
10226 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10227 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10229 IDirect3DVolumeTexture9_Release(texture);
10230 refcount = IDirect3DDevice9_Release(device);
10231 ok(!refcount, "Device has %u references left.\n", refcount);
10232 IDirect3D9_Release(d3d);
10233 DestroyWindow(window);
10236 static void test_shared_handle(void)
10238 IDirect3DDevice9 *device;
10239 IDirect3D9 *d3d;
10240 ULONG refcount;
10241 HWND window;
10242 HRESULT hr;
10243 /* Native d3d9ex refuses to create a shared texture if the texture pointer
10244 * is not initialized to NULL. Make sure this doesn't cause issues here. */
10245 IDirect3DTexture9 *texture = NULL;
10246 IDirect3DSurface9 *surface = NULL;
10247 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
10248 IDirect3DIndexBuffer9 *index_buffer = NULL;
10249 HANDLE handle = NULL;
10250 void *mem;
10251 D3DCAPS9 caps;
10253 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10254 0, 0, 640, 480, 0, 0, 0, 0);
10255 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10256 ok(!!d3d, "Failed to create a D3D object.\n");
10257 if (!(device = create_device(d3d, window, NULL)))
10259 skip("Failed to create a D3D device, skipping tests.\n");
10260 IDirect3D9_Release(d3d);
10261 DestroyWindow(window);
10262 return;
10265 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10266 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10267 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
10269 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
10270 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
10271 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10272 D3DPOOL_DEFAULT, &texture, &handle);
10273 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10274 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10275 D3DPOOL_SYSTEMMEM, &texture, &mem);
10276 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10278 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10279 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
10280 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10281 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10282 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
10283 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10285 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10286 &vertex_buffer, &handle);
10287 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10288 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10289 &vertex_buffer, &mem);
10290 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
10292 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10293 &index_buffer, &handle);
10294 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10295 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10296 &index_buffer, &mem);
10297 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10299 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10301 IDirect3DCubeTexture9 *cube_texture = NULL;
10302 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10303 D3DPOOL_DEFAULT, &cube_texture, &handle);
10304 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10305 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10306 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
10307 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10310 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
10312 IDirect3DVolumeTexture9 *volume_texture = NULL;
10313 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10314 D3DPOOL_DEFAULT, &volume_texture, &handle);
10315 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10316 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10317 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
10318 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10321 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
10322 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10323 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10325 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
10326 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10327 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10329 HeapFree(GetProcessHeap(), 0, mem);
10330 refcount = IDirect3DDevice9_Release(device);
10331 ok(!refcount, "Device has %u references left.\n", refcount);
10332 IDirect3D9_Release(d3d);
10333 DestroyWindow(window);
10336 static void test_pixel_format(void)
10338 HWND hwnd, hwnd2 = NULL;
10339 HDC hdc, hdc2 = NULL;
10340 HMODULE gl = NULL;
10341 int format, test_format;
10342 PIXELFORMATDESCRIPTOR pfd;
10343 IDirect3D9 *d3d9 = NULL;
10344 IDirect3DDevice9 *device = NULL;
10345 HRESULT hr;
10346 static const float point[3] = {0.0, 0.0, 0.0};
10348 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10349 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10350 if (!hwnd)
10352 skip("Failed to create window\n");
10353 return;
10356 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10357 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10359 hdc = GetDC(hwnd);
10360 if (!hdc)
10362 skip("Failed to get DC\n");
10363 goto cleanup;
10366 if (hwnd2)
10367 hdc2 = GetDC(hwnd2);
10369 gl = LoadLibraryA("opengl32.dll");
10370 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
10372 format = GetPixelFormat(hdc);
10373 ok(format == 0, "new window has pixel format %d\n", format);
10375 ZeroMemory(&pfd, sizeof(pfd));
10376 pfd.nSize = sizeof(pfd);
10377 pfd.nVersion = 1;
10378 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
10379 pfd.iPixelType = PFD_TYPE_RGBA;
10380 pfd.iLayerType = PFD_MAIN_PLANE;
10381 format = ChoosePixelFormat(hdc, &pfd);
10382 if (format <= 0)
10384 skip("no pixel format available\n");
10385 goto cleanup;
10388 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
10390 skip("failed to set pixel format\n");
10391 goto cleanup;
10394 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
10396 skip("failed to set pixel format on second window\n");
10397 if (hdc2)
10399 ReleaseDC(hwnd2, hdc2);
10400 hdc2 = NULL;
10404 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
10405 ok(!!d3d9, "Failed to create a D3D object.\n");
10407 test_format = GetPixelFormat(hdc);
10408 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10410 if (!(device = create_device(d3d9, hwnd, NULL)))
10412 skip("Failed to create device\n");
10413 goto cleanup;
10416 test_format = GetPixelFormat(hdc);
10417 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10419 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10420 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10422 test_format = GetPixelFormat(hdc);
10423 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10425 hr = IDirect3DDevice9_BeginScene(device);
10426 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
10428 test_format = GetPixelFormat(hdc);
10429 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10431 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
10432 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10434 test_format = GetPixelFormat(hdc);
10435 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10437 hr = IDirect3DDevice9_EndScene(device);
10438 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
10440 test_format = GetPixelFormat(hdc);
10441 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10443 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10444 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10446 test_format = GetPixelFormat(hdc);
10447 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10449 if (hdc2)
10451 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
10452 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10454 test_format = GetPixelFormat(hdc);
10455 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10457 test_format = GetPixelFormat(hdc2);
10458 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
10461 cleanup:
10462 if (device)
10464 UINT refcount = IDirect3DDevice9_Release(device);
10465 ok(!refcount, "Device has %u references left.\n", refcount);
10467 if (d3d9) IDirect3D9_Release(d3d9);
10468 if (gl) FreeLibrary(gl);
10469 if (hdc) ReleaseDC(hwnd, hdc);
10470 if (hdc2) ReleaseDC(hwnd2, hdc2);
10471 if (hwnd) DestroyWindow(hwnd);
10472 if (hwnd2) DestroyWindow(hwnd2);
10475 static void test_begin_end_state_block(void)
10477 IDirect3DStateBlock9 *stateblock;
10478 IDirect3DDevice9 *device;
10479 IDirect3D9 *d3d;
10480 ULONG refcount;
10481 HWND window;
10482 HRESULT hr;
10484 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10485 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10486 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10487 ok(!!d3d, "Failed to create a D3D object.\n");
10488 if (!(device = create_device(d3d, window, NULL)))
10490 skip("Failed to create a D3D device, skipping tests.\n");
10491 IDirect3D9_Release(d3d);
10492 DestroyWindow(window);
10493 return;
10496 /* Should succeed. */
10497 hr = IDirect3DDevice9_BeginStateBlock(device);
10498 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10500 /* Calling BeginStateBlock() while recording should return
10501 * D3DERR_INVALIDCALL. */
10502 hr = IDirect3DDevice9_BeginStateBlock(device);
10503 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10505 /* Should succeed. */
10506 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10507 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10508 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10509 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10510 "Got unexpected stateblock %p.\n", stateblock);
10511 IDirect3DStateBlock9_Release(stateblock);
10513 /* Calling EndStateBlock() while not recording should return
10514 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10515 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10516 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10517 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10518 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10519 "Got unexpected stateblock %p.\n", stateblock);
10521 refcount = IDirect3DDevice9_Release(device);
10522 ok(!refcount, "Device has %u references left.\n", refcount);
10523 IDirect3D9_Release(d3d);
10524 DestroyWindow(window);
10527 static void test_shader_constant_apply(void)
10529 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10530 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10531 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10532 IDirect3DStateBlock9 *stateblock;
10533 DWORD vs_version, ps_version;
10534 IDirect3DDevice9 *device;
10535 IDirect3D9 *d3d;
10536 ULONG refcount;
10537 D3DCAPS9 caps;
10538 float ret[4];
10539 HWND window;
10540 HRESULT hr;
10542 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10543 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10544 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10545 ok(!!d3d, "Failed to create a D3D object.\n");
10546 if (!(device = create_device(d3d, window, NULL)))
10548 skip("Failed to create a D3D device, skipping tests.\n");
10549 IDirect3D9_Release(d3d);
10550 DestroyWindow(window);
10551 return;
10554 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10555 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10556 vs_version = caps.VertexShaderVersion & 0xffff;
10557 ps_version = caps.PixelShaderVersion & 0xffff;
10559 if (vs_version)
10561 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10562 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10563 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10564 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10566 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10567 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10568 ok(!memcmp(ret, initial, sizeof(initial)),
10569 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10570 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10571 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10572 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10573 ok(!memcmp(ret, initial, sizeof(initial)),
10574 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10575 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10577 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10578 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10580 if (ps_version)
10582 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10583 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10584 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10585 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10587 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10588 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10589 ok(!memcmp(ret, initial, sizeof(initial)),
10590 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10591 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10592 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10593 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10594 ok(!memcmp(ret, initial, sizeof(initial)),
10595 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10596 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10598 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10599 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10602 hr = IDirect3DDevice9_BeginStateBlock(device);
10603 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10605 if (vs_version)
10607 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10608 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10610 if (ps_version)
10612 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10613 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10616 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10617 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10619 if (vs_version)
10621 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10622 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10623 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10624 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10625 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10626 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10627 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10628 ok(!memcmp(ret, initial, sizeof(initial)),
10629 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10630 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10632 if (ps_version)
10634 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10635 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10636 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10637 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10638 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10639 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10640 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10641 ok(!memcmp(ret, initial, sizeof(initial)),
10642 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10643 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10646 /* Apply doesn't overwrite constants that aren't explicitly set on the
10647 * source stateblock. */
10648 hr = IDirect3DStateBlock9_Apply(stateblock);
10649 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10651 if (vs_version)
10653 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10654 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10655 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10656 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10657 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10658 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10659 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10660 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10661 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10662 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10664 if (ps_version)
10666 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10667 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10668 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10669 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10670 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10671 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10672 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10673 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10674 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10675 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10678 IDirect3DStateBlock9_Release(stateblock);
10679 refcount = IDirect3DDevice9_Release(device);
10680 ok(!refcount, "Device has %u references left.\n", refcount);
10681 IDirect3D9_Release(d3d);
10682 DestroyWindow(window);
10685 static void test_vdecl_apply(void)
10687 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10688 IDirect3DStateBlock9 *stateblock;
10689 IDirect3DDevice9 *device;
10690 IDirect3D9 *d3d;
10691 ULONG refcount;
10692 HWND window;
10693 HRESULT hr;
10695 static const D3DVERTEXELEMENT9 decl1[] =
10697 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10698 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10699 D3DDECL_END(),
10702 static const D3DVERTEXELEMENT9 decl2[] =
10704 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10705 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10706 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10707 D3DDECL_END(),
10710 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10711 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10712 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10713 ok(!!d3d, "Failed to create a D3D object.\n");
10714 if (!(device = create_device(d3d, window, NULL)))
10716 skip("Failed to create a D3D device, skipping tests.\n");
10717 IDirect3D9_Release(d3d);
10718 DestroyWindow(window);
10719 return;
10722 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10723 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10725 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10726 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10728 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10729 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10730 hr = IDirect3DDevice9_BeginStateBlock(device);
10731 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10732 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10733 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10734 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10735 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10736 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10737 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10738 hr = IDirect3DStateBlock9_Apply(stateblock);
10739 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10740 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10741 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10742 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10743 declaration, declaration1);
10744 IDirect3DVertexDeclaration9_Release(declaration);
10746 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10747 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10748 hr = IDirect3DStateBlock9_Capture(stateblock);
10749 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10750 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10751 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10752 hr = IDirect3DStateBlock9_Apply(stateblock);
10753 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10754 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10755 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10756 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10757 declaration, declaration2);
10758 IDirect3DVertexDeclaration9_Release(declaration);
10760 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10761 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10762 hr = IDirect3DStateBlock9_Capture(stateblock);
10763 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10764 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10765 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10766 hr = IDirect3DStateBlock9_Apply(stateblock);
10767 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10768 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10769 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10770 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10771 declaration, declaration2);
10772 IDirect3DVertexDeclaration9_Release(declaration);
10774 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10775 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10776 hr = IDirect3DStateBlock9_Capture(stateblock);
10777 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10778 hr = IDirect3DStateBlock9_Apply(stateblock);
10779 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10780 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10781 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10782 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10784 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10785 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10786 hr = IDirect3DStateBlock9_Capture(stateblock);
10787 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10788 hr = IDirect3DStateBlock9_Apply(stateblock);
10789 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10790 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10791 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10792 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10793 declaration, declaration2);
10794 IDirect3DVertexDeclaration9_Release(declaration);
10796 IDirect3DStateBlock9_Release(stateblock);
10797 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10798 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10799 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10800 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10801 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10802 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10803 hr = IDirect3DStateBlock9_Apply(stateblock);
10804 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10805 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10806 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10807 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10808 declaration, declaration1);
10809 IDirect3DVertexDeclaration9_Release(declaration);
10811 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10812 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10813 hr = IDirect3DStateBlock9_Capture(stateblock);
10814 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10815 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10816 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10817 hr = IDirect3DStateBlock9_Apply(stateblock);
10818 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10819 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10820 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10821 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10822 declaration, declaration2);
10823 IDirect3DVertexDeclaration9_Release(declaration);
10825 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10826 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10827 hr = IDirect3DStateBlock9_Capture(stateblock);
10828 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10829 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10830 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10831 hr = IDirect3DStateBlock9_Apply(stateblock);
10832 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10833 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10834 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10835 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10836 declaration, declaration2);
10837 IDirect3DVertexDeclaration9_Release(declaration);
10839 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10840 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10841 hr = IDirect3DStateBlock9_Capture(stateblock);
10842 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10843 hr = IDirect3DStateBlock9_Apply(stateblock);
10844 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10845 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10846 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10847 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10849 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10850 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10851 hr = IDirect3DStateBlock9_Capture(stateblock);
10852 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10853 hr = IDirect3DStateBlock9_Apply(stateblock);
10854 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10855 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10856 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10857 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10858 declaration, declaration2);
10859 IDirect3DVertexDeclaration9_Release(declaration);
10861 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10862 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10863 IDirect3DVertexDeclaration9_Release(declaration1);
10864 IDirect3DVertexDeclaration9_Release(declaration2);
10865 IDirect3DStateBlock9_Release(stateblock);
10866 refcount = IDirect3DDevice9_Release(device);
10867 ok(!refcount, "Device has %u references left.\n", refcount);
10868 IDirect3D9_Release(d3d);
10869 DestroyWindow(window);
10872 static void test_resource_type(void)
10874 IDirect3DDevice9 *device;
10875 IDirect3DSurface9 *surface;
10876 IDirect3DTexture9 *texture;
10877 IDirect3DCubeTexture9 *cube_texture;
10878 IDirect3DVolume9 *volume;
10879 IDirect3DVolumeTexture9 *volume_texture;
10880 D3DSURFACE_DESC surface_desc;
10881 D3DVOLUME_DESC volume_desc;
10882 D3DRESOURCETYPE type;
10883 IDirect3D9 *d3d;
10884 ULONG refcount;
10885 HWND window;
10886 HRESULT hr;
10887 D3DCAPS9 caps;
10889 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10890 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10891 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10892 ok(!!d3d, "Failed to create a D3D object.\n");
10893 if (!(device = create_device(d3d, window, NULL)))
10895 skip("Failed to create a D3D device, skipping tests.\n");
10896 IDirect3D9_Release(d3d);
10897 DestroyWindow(window);
10898 return;
10901 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10902 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10904 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10905 D3DPOOL_SYSTEMMEM, &surface, NULL);
10906 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10907 type = IDirect3DSurface9_GetType(surface);
10908 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10909 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10910 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10911 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10912 surface_desc.Type);
10913 IDirect3DSurface9_Release(surface);
10915 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10916 D3DPOOL_SYSTEMMEM, &texture, NULL);
10917 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10918 type = IDirect3DTexture9_GetType(texture);
10919 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10921 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10922 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10923 /* The following code crashes, for the sake of completeness:
10924 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10925 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10927 * So applications will not depend on getting the "right" resource type - whatever it
10928 * may be - from the "wrong" vtable. */
10929 type = IDirect3DSurface9_GetType(surface);
10930 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10931 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10932 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10933 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10934 surface_desc.Type);
10935 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10936 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10937 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10938 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10939 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10940 surface_desc.Type);
10941 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10942 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10943 IDirect3DSurface9_Release(surface);
10945 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10946 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10947 type = IDirect3DSurface9_GetType(surface);
10948 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10949 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10950 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10951 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10952 surface_desc.Type);
10953 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10954 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10955 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10956 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10957 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10958 surface_desc.Type);
10959 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10960 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10961 IDirect3DSurface9_Release(surface);
10962 IDirect3DTexture9_Release(texture);
10964 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10966 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10967 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10968 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10969 type = IDirect3DCubeTexture9_GetType(cube_texture);
10970 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10972 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10973 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10974 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10975 type = IDirect3DSurface9_GetType(surface);
10976 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10977 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10978 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10979 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10980 surface_desc.Type);
10981 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10982 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10983 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10984 surface_desc.Type);
10985 IDirect3DSurface9_Release(surface);
10986 IDirect3DCubeTexture9_Release(cube_texture);
10988 else
10989 skip("Cube maps not supported.\n");
10991 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10993 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10994 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10995 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10996 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10997 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10999 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
11000 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
11001 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
11002 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
11003 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
11004 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11005 volume_desc.Type);
11006 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
11007 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
11008 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
11009 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
11010 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
11011 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11012 volume_desc.Type);
11013 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
11014 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
11015 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
11016 IDirect3DVolume9_Release(volume);
11018 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
11019 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
11020 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
11021 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
11022 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
11023 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11024 volume_desc.Type);
11025 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
11026 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
11027 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
11028 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
11029 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
11030 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
11031 volume_desc.Type);
11032 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
11033 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
11034 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
11035 IDirect3DVolume9_Release(volume);
11036 IDirect3DVolumeTexture9_Release(volume_texture);
11038 else
11039 skip("Mipmapped volume maps not supported.\n");
11041 refcount = IDirect3DDevice9_Release(device);
11042 ok(!refcount, "Device has %u references left.\n", refcount);
11043 IDirect3D9_Release(d3d);
11044 DestroyWindow(window);
11047 static void test_mipmap_lock(void)
11049 IDirect3DDevice9 *device;
11050 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
11051 IDirect3DTexture9 *texture, *texture_dst;
11052 IDirect3D9 *d3d;
11053 ULONG refcount;
11054 HWND window;
11055 HRESULT hr;
11056 D3DLOCKED_RECT locked_rect;
11058 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11059 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11060 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11061 ok(!!d3d, "Failed to create a D3D object.\n");
11062 if (!(device = create_device(d3d, window, NULL)))
11064 skip("Failed to create a D3D device, skipping tests.\n");
11065 IDirect3D9_Release(d3d);
11066 DestroyWindow(window);
11067 return;
11070 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11071 D3DPOOL_DEFAULT, &texture_dst, NULL);
11072 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11073 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
11074 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11075 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
11076 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11078 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11079 D3DPOOL_SYSTEMMEM, &texture, NULL);
11080 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11081 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11082 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11083 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
11084 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11086 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
11087 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11088 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
11089 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11090 hr = IDirect3DSurface9_UnlockRect(surface);
11091 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11093 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
11094 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
11095 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
11096 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11098 /* Apparently there's no validation on the container. */
11099 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
11100 (IDirect3DBaseTexture9 *)texture_dst);
11101 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
11103 hr = IDirect3DSurface9_UnlockRect(surface2);
11104 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11106 IDirect3DSurface9_Release(surface_dst2);
11107 IDirect3DSurface9_Release(surface_dst);
11108 IDirect3DSurface9_Release(surface2);
11109 IDirect3DSurface9_Release(surface);
11110 IDirect3DTexture9_Release(texture_dst);
11111 IDirect3DTexture9_Release(texture);
11113 refcount = IDirect3DDevice9_Release(device);
11114 ok(!refcount, "Device has %u references left.\n", refcount);
11115 IDirect3D9_Release(d3d);
11116 DestroyWindow(window);
11119 static void test_writeonly_resource(void)
11121 IDirect3D9 *d3d;
11122 IDirect3DDevice9 *device;
11123 IDirect3DVertexBuffer9 *buffer;
11124 ULONG refcount;
11125 HWND window;
11126 HRESULT hr;
11127 void *ptr;
11128 static const struct
11130 struct vec3 pos;
11132 quad[] =
11134 {{-1.0f, -1.0f, 0.0f}},
11135 {{-1.0f, 1.0f, 0.0f}},
11136 {{ 1.0f, -1.0f, 0.0f}},
11137 {{ 1.0f, 1.0f, 0.0f}}
11140 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11141 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11142 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11143 ok(!!d3d, "Failed to create a D3D object.\n");
11144 if (!(device = create_device(d3d, window, NULL)))
11146 skip("Failed to create a D3D device, skipping tests.\n");
11147 IDirect3D9_Release(d3d);
11148 DestroyWindow(window);
11149 return;
11152 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
11153 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
11154 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
11156 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
11157 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11158 memcpy(ptr, quad, sizeof(quad));
11159 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11160 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11161 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
11162 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
11163 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
11164 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
11166 hr = IDirect3DDevice9_BeginScene(device);
11167 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
11168 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
11169 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11170 hr = IDirect3DDevice9_EndScene(device);
11171 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
11173 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
11174 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11175 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11176 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11177 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11179 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
11180 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11181 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11182 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11183 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11185 refcount = IDirect3DVertexBuffer9_Release(buffer);
11186 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
11187 refcount = IDirect3DDevice9_Release(device);
11188 ok(!refcount, "Device has %u references left.\n", refcount);
11189 IDirect3D9_Release(d3d);
11190 DestroyWindow(window);
11193 static void test_lost_device(void)
11195 struct device_desc device_desc;
11196 IDirect3DDevice9 *device;
11197 IDirect3D9 *d3d;
11198 ULONG refcount;
11199 HWND window;
11200 HRESULT hr;
11201 BOOL ret;
11203 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11204 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11205 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11206 ok(!!d3d, "Failed to create a D3D object.\n");
11207 device_desc.device_window = window;
11208 device_desc.width = registry_mode.dmPelsWidth;
11209 device_desc.height = registry_mode.dmPelsHeight;
11210 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11211 if (!(device = create_device(d3d, window, &device_desc)))
11213 skip("Failed to create a D3D device, skipping tests.\n");
11214 goto done;
11217 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11218 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11219 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11220 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11222 ret = SetForegroundWindow(GetDesktopWindow());
11223 ok(ret, "Failed to set foreground window.\n");
11224 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11225 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11226 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11227 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11229 ret = ShowWindow(window, SW_RESTORE);
11230 ok(ret, "Failed to restore window.\n");
11231 ret = SetForegroundWindow(window);
11232 ok(ret, "Failed to set foreground window.\n");
11233 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11234 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
11235 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11236 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11238 hr = reset_device(device, &device_desc);
11239 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11240 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11241 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11242 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11243 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11245 device_desc.flags = 0;
11246 hr = reset_device(device, &device_desc);
11247 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11248 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11249 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11250 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11251 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11253 ret = SetForegroundWindow(GetDesktopWindow());
11254 ok(ret, "Failed to set foreground window.\n");
11255 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11256 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11257 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11258 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11260 ret = ShowWindow(window, SW_RESTORE);
11261 ok(ret, "Failed to restore window.\n");
11262 ret = SetForegroundWindow(window);
11263 ok(ret, "Failed to set foreground window.\n");
11264 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11265 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11266 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11267 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11269 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11270 hr = reset_device(device, &device_desc);
11271 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11272 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11273 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11274 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11275 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11277 ret = SetForegroundWindow(GetDesktopWindow());
11278 ok(ret, "Failed to set foreground window.\n");
11279 hr = reset_device(device, &device_desc);
11280 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11281 ret = ShowWindow(window, SW_RESTORE);
11282 ok(ret, "Failed to restore window.\n");
11283 ret = SetForegroundWindow(window);
11284 ok(ret, "Failed to set foreground window.\n");
11285 hr = reset_device(device, &device_desc);
11286 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11288 refcount = IDirect3DDevice9_Release(device);
11289 ok(!refcount, "Device has %u references left.\n", refcount);
11290 done:
11291 IDirect3D9_Release(d3d);
11292 DestroyWindow(window);
11295 static void test_resource_priority(void)
11297 IDirect3DDevice9 *device;
11298 IDirect3DSurface9 *surface;
11299 IDirect3DTexture9 *texture;
11300 IDirect3DVertexBuffer9 *buffer;
11301 IDirect3D9 *d3d;
11302 ULONG refcount;
11303 HWND window;
11304 HRESULT hr;
11305 static const struct
11307 D3DPOOL pool;
11308 const char *name;
11309 BOOL can_set_priority;
11311 test_data[] =
11313 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
11314 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
11315 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
11316 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
11318 unsigned int i;
11319 DWORD priority;
11321 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11322 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11323 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11324 ok(!!d3d, "Failed to create a D3D object.\n");
11325 if (!(device = create_device(d3d, window, NULL)))
11327 skip("Failed to create a D3D device, skipping tests.\n");
11328 IDirect3D9_Release(d3d);
11329 DestroyWindow(window);
11330 return;
11333 for (i = 0; i < ARRAY_SIZE(test_data); i++)
11335 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
11336 test_data[i].pool, &texture, NULL);
11337 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
11338 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11339 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11341 priority = IDirect3DTexture9_GetPriority(texture);
11342 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11343 priority = IDirect3DTexture9_SetPriority(texture, 1);
11344 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11345 priority = IDirect3DTexture9_GetPriority(texture);
11346 if (test_data[i].can_set_priority)
11348 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11349 priority = IDirect3DTexture9_SetPriority(texture, 2);
11350 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11352 else
11353 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11355 priority = IDirect3DSurface9_GetPriority(surface);
11356 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11357 priority = IDirect3DSurface9_SetPriority(surface, 1);
11358 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11359 priority = IDirect3DSurface9_GetPriority(surface);
11360 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11362 IDirect3DSurface9_Release(surface);
11363 IDirect3DTexture9_Release(texture);
11365 if (test_data[i].pool != D3DPOOL_MANAGED)
11367 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
11368 test_data[i].pool, &surface, NULL);
11369 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
11371 priority = IDirect3DSurface9_GetPriority(surface);
11372 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11373 priority = IDirect3DSurface9_SetPriority(surface, 1);
11374 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11375 priority = IDirect3DSurface9_GetPriority(surface);
11376 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11378 IDirect3DSurface9_Release(surface);
11381 if (test_data[i].pool != D3DPOOL_SCRATCH)
11383 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
11384 test_data[i].pool, &buffer, NULL);
11385 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
11387 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11388 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11389 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
11390 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11391 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11392 if (test_data[i].can_set_priority)
11394 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11395 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
11396 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11398 else
11399 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11401 IDirect3DVertexBuffer9_Release(buffer);
11405 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
11406 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11408 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11409 priority = IDirect3DSurface9_GetPriority(surface);
11410 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11411 priority = IDirect3DSurface9_SetPriority(surface, 1);
11412 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11413 priority = IDirect3DSurface9_GetPriority(surface);
11414 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11416 IDirect3DSurface9_Release(surface);
11418 refcount = IDirect3DDevice9_Release(device);
11419 ok(!refcount, "Device has %u references left.\n", refcount);
11420 IDirect3D9_Release(d3d);
11421 DestroyWindow(window);
11424 static void test_swapchain_parameters(void)
11426 IDirect3DDevice9 *device;
11427 IDirect3D9 *d3d;
11428 HWND window;
11429 HRESULT hr;
11430 unsigned int i;
11431 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
11432 IDirect3DSwapChain9 *swapchain;
11433 static const struct
11435 BOOL windowed;
11436 UINT backbuffer_count;
11437 D3DSWAPEFFECT swap_effect;
11438 HRESULT hr;
11440 tests[] =
11442 /* Swap effect 0 is not allowed. */
11443 {TRUE, 1, 0, D3DERR_INVALIDCALL},
11444 {FALSE, 1, 0, D3DERR_INVALIDCALL},
11446 /* All (non-ex) swap effects are allowed in
11447 * windowed and fullscreen mode. */
11448 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11449 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11450 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11451 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11452 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11454 /* Only one backbuffer in copy mode. */
11455 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
11456 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11457 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11458 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11460 /* Ok with the others, in fullscreen and windowed mode. */
11461 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11462 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11463 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11464 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11466 /* D3D9Ex swap effects. */
11467 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11468 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11469 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11470 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11471 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11472 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11474 /* 3 is the highest allowed backbuffer count. */
11475 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11476 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11477 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11478 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11479 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11482 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11483 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11484 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11485 ok(!!d3d, "Failed to create a D3D object.\n");
11486 if (!(device = create_device(d3d, window, NULL)))
11488 skip("Failed to create a D3D device, skipping tests.\n");
11489 IDirect3D9_Release(d3d);
11490 DestroyWindow(window);
11491 return;
11493 IDirect3DDevice9_Release(device);
11495 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11496 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11497 present_parameters_windowed.hDeviceWindow = window;
11498 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11499 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11500 present_parameters_windowed.Windowed = TRUE;
11501 present_parameters_windowed.BackBufferCount = 1;
11503 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11505 memset(&present_parameters, 0, sizeof(present_parameters));
11506 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11507 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11508 present_parameters.hDeviceWindow = window;
11509 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11511 present_parameters.SwapEffect = tests[i].swap_effect;
11512 present_parameters.Windowed = tests[i].windowed;
11513 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11515 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11516 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11517 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11518 if (SUCCEEDED(hr))
11520 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11522 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11523 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11525 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11526 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11527 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11528 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11529 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11530 bb_count, present_parameters2.BackBufferCount, i);
11531 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11532 tests[i].windowed, present_parameters2.Windowed, i);
11534 IDirect3DSwapChain9_Release(swapchain);
11535 IDirect3DDevice9_Release(device);
11538 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11539 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11540 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11542 memset(&present_parameters, 0, sizeof(present_parameters));
11543 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11544 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11545 present_parameters.hDeviceWindow = window;
11546 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11548 present_parameters.SwapEffect = tests[i].swap_effect;
11549 present_parameters.Windowed = tests[i].windowed;
11550 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11552 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11553 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11555 if (FAILED(hr))
11557 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11558 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11560 IDirect3DDevice9_Release(device);
11563 IDirect3D9_Release(d3d);
11564 DestroyWindow(window);
11567 static void test_check_device_format(void)
11569 static const D3DFORMAT adapter_formats[] =
11571 D3DFMT_A8R8G8B8,
11572 D3DFMT_X8R8G8B8,
11574 static const D3DFORMAT mipmap_autogen_formats[] =
11576 D3DFMT_R8G8B8,
11577 D3DFMT_A8R8G8B8,
11578 D3DFMT_X8R8G8B8,
11579 D3DFMT_R5G6B5,
11580 D3DFMT_X1R5G5B5,
11581 D3DFMT_A8P8,
11582 D3DFMT_P8,
11583 D3DFMT_A1R5G5B5,
11584 D3DFMT_A4R4G4B4,
11587 D3DFORMAT adapter_format, format;
11588 BOOL render_target_supported;
11589 unsigned int i, j;
11590 IDirect3D9 *d3d;
11591 HRESULT hr;
11593 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11594 ok(!!d3d, "Failed to create a D3D object.\n");
11596 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11597 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11599 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11601 else
11603 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11604 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11605 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11606 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11607 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11608 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11611 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11612 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11613 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11614 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11615 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11616 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11617 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11618 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11619 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11621 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11622 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11623 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11624 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11625 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11626 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11627 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11628 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11629 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11631 for (i = 0; i < ARRAY_SIZE(adapter_formats); ++i)
11633 adapter_format = adapter_formats[i];
11635 for (j = 0; j < ARRAY_SIZE(mipmap_autogen_formats); ++j)
11637 format = mipmap_autogen_formats[j];
11639 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, adapter_format,
11640 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, format);
11641 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
11642 render_target_supported = hr == D3D_OK;
11644 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, adapter_format,
11645 D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, format);
11646 if (render_target_supported)
11648 ok(hr == D3D_OK || hr == D3DOK_NOAUTOGEN, "Got unexpected hr %#x.\n", hr);
11650 else
11652 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
11657 IDirect3D9_Release(d3d);
11660 static void test_miptree_layout(void)
11662 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11663 IDirect3DCubeTexture9 *texture_cube;
11664 IDirect3DTexture9 *texture_2d;
11665 IDirect3DDevice9 *device;
11666 D3DLOCKED_RECT map_desc;
11667 BYTE *base = NULL;
11668 IDirect3D9 *d3d;
11669 D3DCAPS9 caps;
11670 UINT refcount;
11671 HWND window;
11672 HRESULT hr;
11674 static const struct
11676 D3DFORMAT format;
11677 const char *name;
11679 formats[] =
11681 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11682 {D3DFMT_A8, "D3DFMT_A8"},
11683 {D3DFMT_L8, "D3DFMT_L8"},
11684 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11685 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11687 static const struct
11689 D3DPOOL pool;
11690 const char *name;
11692 pools[] =
11694 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11695 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11696 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11699 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11700 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11701 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11702 ok(!!d3d, "Failed to create a D3D object.\n");
11703 if (!(device = create_device(d3d, window, NULL)))
11705 skip("Failed to create a D3D device, skipping tests.\n");
11706 goto done;
11709 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11710 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11712 base_dimension = 257;
11713 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11715 skip("Using power of two base dimension.\n");
11716 base_dimension = 256;
11719 for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx)
11721 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11722 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11724 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11725 continue;
11728 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11730 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11731 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11732 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11733 pools[pool_idx].name, formats[format_idx].name, hr);
11735 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11736 for (i = 0, offset = 0; i < level_count; ++i)
11738 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11739 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11740 pools[pool_idx].name, formats[format_idx].name, i, hr);
11742 if (!i)
11743 base = map_desc.pBits;
11744 else
11745 ok(map_desc.pBits == base + offset,
11746 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11747 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11748 offset += (base_dimension >> i) * map_desc.Pitch;
11750 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11751 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11752 pools[pool_idx].name, formats[format_idx].name, i, hr);
11755 IDirect3DTexture9_Release(texture_2d);
11758 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11759 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11761 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11762 continue;
11765 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11767 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11768 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11769 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11770 pools[pool_idx].name, formats[format_idx].name, hr);
11772 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11773 for (i = 0, offset = 0; i < 6; ++i)
11775 for (j = 0; j < level_count; ++j)
11777 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11778 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11779 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11781 if (!i && !j)
11782 base = map_desc.pBits;
11783 else
11784 ok(map_desc.pBits == base + offset,
11785 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11786 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11787 offset += (base_dimension >> j) * map_desc.Pitch;
11789 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11790 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11791 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11793 offset = (offset + 15) & ~15;
11796 IDirect3DCubeTexture9_Release(texture_cube);
11800 refcount = IDirect3DDevice9_Release(device);
11801 ok(!refcount, "Device has %u references left.\n", refcount);
11802 done:
11803 IDirect3D9_Release(d3d);
11804 DestroyWindow(window);
11807 static void test_get_render_target_data(void)
11809 IDirect3DSurface9 *offscreen_surface, *render_target;
11810 IDirect3DDevice9 *device;
11811 IDirect3D9 *d3d;
11812 UINT refcount;
11813 HWND window;
11814 HRESULT hr;
11816 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11817 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11818 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11819 ok(!!d3d, "Failed to create a D3D object.\n");
11820 if (!(device = create_device(d3d, window, NULL)))
11822 skip("Failed to create a D3D device.\n");
11823 IDirect3D9_Release(d3d);
11824 DestroyWindow(window);
11825 return;
11828 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11829 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11830 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11832 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11833 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11834 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11836 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11837 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11839 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11840 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11842 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11843 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11845 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11846 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11848 IDirect3DSurface9_Release(render_target);
11849 IDirect3DSurface9_Release(offscreen_surface);
11850 refcount = IDirect3DDevice9_Release(device);
11851 ok(!refcount, "Device has %u references left.\n", refcount);
11852 IDirect3D9_Release(d3d);
11853 DestroyWindow(window);
11856 static void test_render_target_device_mismatch(void)
11858 IDirect3DDevice9 *device, *device2;
11859 IDirect3DSurface9 *surface, *rt;
11860 IDirect3D9 *d3d;
11861 UINT refcount;
11862 HWND window;
11863 HRESULT hr;
11865 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11866 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11867 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11868 ok(!!d3d, "Failed to create a D3D object.\n");
11869 if (!(device = create_device(d3d, window, NULL)))
11871 skip("Failed to create a D3D device.\n");
11872 IDirect3D9_Release(d3d);
11873 DestroyWindow(window);
11874 return;
11877 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
11878 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11880 device2 = create_device(d3d, window, NULL);
11881 ok(!!device2, "Failed to create a D3D device.\n");
11883 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11884 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11885 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11887 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11888 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11890 IDirect3DSurface9_Release(surface);
11892 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11893 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11895 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11896 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11898 IDirect3DSurface9_Release(surface);
11900 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11901 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11902 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11903 IDirect3DSurface9_Release(surface);
11904 IDirect3DSurface9_Release(rt);
11906 refcount = IDirect3DDevice9_Release(device);
11907 ok(!refcount, "Device has %u references left.\n", refcount);
11908 refcount = IDirect3DDevice9_Release(device2);
11909 ok(!refcount, "Device has %u references left.\n", refcount);
11910 IDirect3D9_Release(d3d);
11911 DestroyWindow(window);
11914 static void test_format_unknown(void)
11916 IDirect3DDevice9 *device;
11917 IDirect3D9 *d3d;
11918 UINT refcount;
11919 HWND window;
11920 void *iface;
11921 HRESULT hr;
11923 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11924 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11925 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11926 ok(!!d3d, "Failed to create a D3D object.\n");
11927 if (!(device = create_device(d3d, window, NULL)))
11929 skip("Failed to create a D3D device.\n");
11930 IDirect3D9_Release(d3d);
11931 DestroyWindow(window);
11932 return;
11935 iface = (void *)0xdeadbeef;
11936 hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64,
11937 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
11938 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11939 ok(!iface, "Got unexpected iface %p.\n", iface);
11941 iface = (void *)0xdeadbeef;
11942 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 64, 64,
11943 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
11944 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11945 ok(!iface, "Got unexpected iface %p.\n", iface);
11947 iface = (void *)0xdeadbeef;
11948 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
11949 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
11950 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11951 ok(!iface, "Got unexpected iface %p.\n", iface);
11953 iface = (void *)0xdeadbeef;
11954 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
11955 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
11956 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11957 ok(!iface, "Got unexpected iface %p.\n", iface);
11959 iface = (void *)0xdeadbeef;
11960 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 1, 0,
11961 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
11962 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11963 ok(!iface, "Got unexpected iface %p.\n", iface);
11965 iface = (void *)0xdeadbeef;
11966 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
11967 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
11968 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11969 ok(!iface, "Got unexpected iface %p.\n", iface);
11971 refcount = IDirect3DDevice9_Release(device);
11972 ok(!refcount, "Device has %u references left.\n", refcount);
11973 IDirect3D9_Release(d3d);
11974 DestroyWindow(window);
11977 static void test_destroyed_window(void)
11979 IDirect3DDevice9 *device;
11980 IDirect3D9 *d3d9;
11981 ULONG refcount;
11982 HWND window;
11983 HRESULT hr;
11985 /* No WS_VISIBLE. */
11986 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11987 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11988 ok(!!window, "Failed to create a window.\n");
11990 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
11991 ok(!!d3d9, "Failed to create a D3D object.\n");
11992 device = create_device(d3d9, window, NULL);
11993 IDirect3D9_Release(d3d9);
11994 DestroyWindow(window);
11995 if (!device)
11997 skip("Failed to create a 3D device, skipping test.\n");
11998 return;
12001 hr = IDirect3DDevice9_BeginScene(device);
12002 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
12003 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
12004 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
12005 hr = IDirect3DDevice9_EndScene(device);
12006 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
12007 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12008 ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
12010 refcount = IDirect3DDevice9_Release(device);
12011 ok(!refcount, "Device has %u references left.\n", refcount);
12014 static void test_lockable_backbuffer(void)
12016 D3DPRESENT_PARAMETERS present_parameters = {0};
12017 struct device_desc device_desc;
12018 IDirect3DSurface9 *surface;
12019 IDirect3DDevice9 *device;
12020 D3DLOCKED_RECT lockrect;
12021 IDirect3D9 *d3d;
12022 ULONG refcount;
12023 HWND window;
12024 HRESULT hr;
12025 HDC dc;
12027 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
12028 0, 0, 640, 480, 0, 0, 0, 0);
12029 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12030 ok(!!d3d, "Failed to create a D3D object.\n");
12032 if (!(device = create_device(d3d, window, NULL)))
12034 skip("Failed to create a D3D device, skipping tests.\n");
12035 IDirect3D9_Release(d3d);
12036 DestroyWindow(window);
12037 return;
12040 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12041 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12043 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12044 todo_wine
12045 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12047 dc = (void *)0xdeadbeef;
12048 hr = IDirect3DSurface9_GetDC(surface, &dc);
12049 ok(dc == (void *)0xdeadbeef, "Unexpected DC returned.\n");
12050 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
12052 IDirect3DSurface9_Release(surface);
12054 /* Reset with D3DPRESENTFLAG_LOCKABLE_BACKBUFFER. */
12055 present_parameters.BackBufferWidth = 640;
12056 present_parameters.BackBufferHeight = 480;
12057 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
12058 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
12059 present_parameters.hDeviceWindow = window;
12060 present_parameters.Windowed = TRUE;
12061 present_parameters.EnableAutoDepthStencil = TRUE;
12062 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
12063 present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
12065 hr = IDirect3DDevice9_Reset(device, &present_parameters);
12066 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
12068 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12069 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12071 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12072 todo_wine
12073 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
12074 hr = IDirect3DSurface9_UnlockRect(surface);
12075 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
12077 IDirect3DSurface9_Release(surface);
12078 refcount = IDirect3DDevice9_Release(device);
12079 ok(!refcount, "Device has %u references left.\n", refcount);
12081 device_desc.width = 640;
12082 device_desc.height = 480;
12083 device_desc.device_window = window;
12084 device_desc.flags = CREATE_DEVICE_LOCKABLE_BACKBUFFER;
12086 device = create_device(d3d, window, &device_desc);
12087 ok(!!device, "Failed to create device.\n");
12089 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
12090 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
12092 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
12093 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
12094 hr = IDirect3DSurface9_UnlockRect(surface);
12095 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
12097 IDirect3DSurface9_Release(surface);
12098 refcount = IDirect3DDevice9_Release(device);
12099 ok(!refcount, "Device has %u references left.\n", refcount);
12100 IDirect3D9_Release(d3d);
12101 DestroyWindow(window);
12104 static void test_clip_planes_limits(void)
12106 static const DWORD device_flags[] = {0, CREATE_DEVICE_SWVP_ONLY};
12107 IDirect3DDevice9 *device;
12108 struct device_desc desc;
12109 unsigned int i, j;
12110 IDirect3D9 *d3d;
12111 ULONG refcount;
12112 float plane[4];
12113 D3DCAPS9 caps;
12114 DWORD state;
12115 HWND window;
12116 HRESULT hr;
12118 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
12119 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12120 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12121 ok(!!d3d, "Failed to create a D3D object.\n");
12123 for (i = 0; i < ARRAY_SIZE(device_flags); ++i)
12125 desc.device_window = window;
12126 desc.width = 640;
12127 desc.height = 480;
12128 desc.flags = device_flags[i];
12129 if (!(device = create_device(d3d, window, &desc)))
12131 skip("Failed to create D3D device, flags %#x.\n", desc.flags);
12132 continue;
12135 memset(&caps, 0, sizeof(caps));
12136 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12137 ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr);
12139 trace("Max user clip planes: %u.\n", caps.MaxUserClipPlanes);
12141 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12143 memset(plane, 0xff, sizeof(plane));
12144 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12145 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12146 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
12147 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12148 j, plane[0], plane[1], plane[2], plane[3]);
12151 plane[0] = 2.0f;
12152 plane[1] = 8.0f;
12153 plane[2] = 5.0f;
12154 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12156 plane[3] = j;
12157 hr = IDirect3DDevice9_SetClipPlane(device, j, plane);
12158 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", j, hr);
12160 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12162 float expected_d = j >= caps.MaxUserClipPlanes - 1 ? 2 * D3DMAXUSERCLIPPLANES - 1 : j;
12163 memset(plane, 0xff, sizeof(plane));
12164 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12165 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12166 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == expected_d,
12167 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12168 j, plane[0], plane[1], plane[2], plane[3]);
12171 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0xffffffff);
12172 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12173 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12174 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12175 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
12176 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x80000000);
12177 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12178 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12179 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12180 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
12182 refcount = IDirect3DDevice9_Release(device);
12183 ok(!refcount, "Device has %u references left.\n", refcount);
12186 IDirect3D9_Release(d3d);
12187 DestroyWindow(window);
12190 static void test_swapchain_multisample_reset(void)
12192 IDirect3DSwapChain9 *swapchain;
12193 D3DPRESENT_PARAMETERS d3dpp;
12194 IDirect3DDevice9 *device;
12195 DWORD quality_levels;
12196 IDirect3D9 *d3d;
12197 ULONG refcount;
12198 HWND window;
12199 HRESULT hr;
12201 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
12202 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12203 ok(!!window, "Failed to create a window.\n");
12204 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12205 ok(!!d3d, "Failed to create a D3D object.\n");
12207 if (IDirect3D9_CheckDeviceMultiSampleType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12208 D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &quality_levels) == D3DERR_NOTAVAILABLE)
12210 skip("Multisampling not supported for D3DFMT_A8R8G8B8.\n");
12211 IDirect3D9_Release(d3d);
12212 DestroyWindow(window);
12213 return;
12216 if (!(device = create_device(d3d, window, NULL)))
12218 skip("Failed to create a 3D device.\n");
12219 IDirect3D9_Release(d3d);
12220 DestroyWindow(window);
12221 return;
12224 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
12225 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12227 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
12228 ok(hr == D3D_OK, "Failed to get the implicit swapchain, hr %#x.\n", hr);
12229 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
12230 ok(hr == D3D_OK, "Failed to get present parameters, hr %#x.\n", hr);
12231 ok(d3dpp.MultiSampleType == D3DMULTISAMPLE_NONE,
12232 "Got unexpected multisample type %#x.\n", d3dpp.MultiSampleType);
12233 IDirect3DSwapChain9_Release(swapchain);
12235 d3dpp.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
12236 d3dpp.MultiSampleQuality = quality_levels - 1;
12237 hr = IDirect3DDevice9_Reset(device, &d3dpp);
12238 ok(hr == D3D_OK, "Failed to reset device, hr %#x.\n", hr);
12240 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
12241 ok(hr == D3D_OK, "Failed to clear, hr %#x.\n", hr);
12243 refcount = IDirect3DDevice9_Release(device);
12244 ok(!refcount, "Device has %u references left.\n", refcount);
12245 IDirect3D9_Release(d3d);
12246 DestroyWindow(window);
12249 START_TEST(device)
12251 WNDCLASSA wc = {0};
12252 IDirect3D9 *d3d9;
12253 DEVMODEW current_mode;
12255 memset(&current_mode, 0, sizeof(current_mode));
12256 current_mode.dmSize = sizeof(current_mode);
12257 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
12258 registry_mode.dmSize = sizeof(registry_mode);
12259 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
12260 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
12261 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
12263 skip("Current mode does not match registry mode, skipping test.\n");
12264 return;
12267 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
12269 skip("could not create D3D9 object\n");
12270 return;
12272 IDirect3D9_Release(d3d9);
12274 wc.lpfnWndProc = DefWindowProcA;
12275 wc.lpszClassName = "d3d9_test_wc";
12276 RegisterClassA(&wc);
12278 test_get_set_vertex_declaration();
12279 test_get_declaration();
12280 test_fvf_decl_conversion();
12281 test_fvf_decl_management();
12282 test_vertex_declaration_alignment();
12283 test_unused_declaration_type();
12284 test_fpu_setup();
12285 test_multi_device();
12286 test_display_formats();
12287 test_display_modes();
12288 test_swapchain();
12289 test_refcount();
12290 test_mipmap_levels();
12291 test_checkdevicemultisampletype();
12292 test_invalid_multisample();
12293 test_cursor();
12294 test_cursor_pos();
12295 test_reset_fullscreen();
12296 test_reset();
12297 test_scene();
12298 test_limits();
12299 test_depthstenciltest();
12300 test_get_rt();
12301 test_draw_primitive();
12302 test_null_stream();
12303 test_lights();
12304 test_set_stream_source();
12305 test_scissor_size();
12306 test_wndproc();
12307 test_wndproc_windowed();
12308 test_window_style();
12309 test_mode_change();
12310 test_device_window_reset();
12311 test_reset_resources();
12312 test_set_rt_vp_scissor();
12313 test_volume_get_container();
12314 test_volume_resource();
12315 test_vb_lock_flags();
12316 test_vertex_buffer_alignment();
12317 test_query_support();
12318 test_occlusion_query();
12319 test_timestamp_query();
12320 test_get_set_vertex_shader();
12321 test_vertex_shader_constant();
12322 test_get_set_pixel_shader();
12323 test_pixel_shader_constant();
12324 test_unsupported_shaders();
12325 test_texture_stage_states();
12326 test_cube_textures();
12327 test_mipmap_gen();
12328 test_filter();
12329 test_get_set_texture();
12330 test_lod();
12331 test_surface_get_container();
12332 test_surface_alignment();
12333 test_lockrect_offset();
12334 test_lockrect_invalid();
12335 test_private_data();
12336 test_getdc();
12337 test_surface_dimensions();
12338 test_surface_format_null();
12339 test_surface_double_unlock();
12340 test_surface_blocks();
12341 test_set_palette();
12342 test_swvp_buffer();
12343 test_managed_buffer();
12344 test_npot_textures();
12345 test_vidmem_accounting();
12346 test_volume_locking();
12347 test_update_volumetexture();
12348 test_create_rt_ds_fail();
12349 test_volume_blocks();
12350 test_lockbox_invalid();
12351 test_shared_handle();
12352 test_pixel_format();
12353 test_begin_end_state_block();
12354 test_shader_constant_apply();
12355 test_vdecl_apply();
12356 test_resource_type();
12357 test_mipmap_lock();
12358 test_writeonly_resource();
12359 test_lost_device();
12360 test_resource_priority();
12361 test_swapchain_parameters();
12362 test_check_device_format();
12363 test_miptree_layout();
12364 test_get_render_target_data();
12365 test_render_target_device_mismatch();
12366 test_format_unknown();
12367 test_destroyed_window();
12368 test_lockable_backbuffer();
12369 test_clip_planes_limits();
12370 test_swapchain_multisample_reset();
12372 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));