d3d9: Clamp clip plane index to valid range.
[wine.git] / dlls / d3d9 / tests / device.c
blob866f435f836836ce52e58532cb4fca67b59dac70
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 ShowWindow(device_window, SW_HIDE);
3910 flush_events();
3912 expect_messages = focus_loss_messages_hidden;
3913 windowposchanged_received = 0;
3914 SetForegroundWindow(GetDesktopWindow());
3915 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3916 expect_messages->message, expect_messages->window, i);
3917 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it.\n");
3918 expect_messages = NULL;
3919 flush_events();
3921 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
3922 ok(ret, "Failed to get display mode.\n");
3923 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
3924 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
3926 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
3927 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
3928 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
3929 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
3930 flush_events();
3932 syscommand_received = 0;
3933 expect_messages = sc_restore_messages;
3934 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
3935 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3936 expect_messages->message, expect_messages->window, i);
3937 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
3938 expect_messages = NULL;
3939 flush_events();
3941 expect_messages = sc_minimize_messages;
3942 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3943 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3944 expect_messages->message, expect_messages->window, i);
3945 expect_messages = NULL;
3946 flush_events();
3948 expect_messages = sc_maximize_messages;
3949 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
3950 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3951 expect_messages->message, expect_messages->window, i);
3952 expect_messages = NULL;
3953 flush_events();
3955 SetForegroundWindow(GetDesktopWindow());
3956 ShowWindow(device_window, SW_MINIMIZE);
3957 ShowWindow(device_window, SW_RESTORE);
3958 ShowWindow(focus_window, SW_MINIMIZE);
3959 ShowWindow(focus_window, SW_RESTORE);
3960 SetForegroundWindow(focus_window);
3961 flush_events();
3963 /* Releasing a device in lost state breaks follow-up tests on native. */
3964 hr = reset_device(device, &device_desc);
3965 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, i=%u.\n", hr, i);
3967 filter_messages = focus_window;
3969 ref = IDirect3DDevice9_Release(device);
3970 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3972 /* Fix up the mode until Wine's device release behavior is fixed. */
3973 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
3974 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
3976 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3977 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
3978 (LONG_PTR)test_proc, proc, i);
3980 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
3981 * on native in the test below. It isn't needed anyways. Creating the third
3982 * device will show it again. */
3983 filter_messages = NULL;
3984 ShowWindow(device_window, SW_HIDE);
3985 /* Remove the maximized state from the SYSCOMMAND test while we're not
3986 * interfering with a device. */
3987 ShowWindow(focus_window, SW_SHOWNORMAL);
3988 filter_messages = focus_window;
3990 device_desc.device_window = focus_window;
3991 if (!(device = create_device(d3d9, focus_window, &device_desc)))
3993 skip("Failed to create a D3D device, skipping tests.\n");
3994 goto done;
3996 filter_messages = NULL;
3997 SetForegroundWindow(focus_window); /* For KDE. */
3998 flush_events();
4000 expect_messages = focus_loss_messages_filtered;
4001 windowposchanged_received = 0;
4002 SetForegroundWindow(GetDesktopWindow());
4003 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4004 expect_messages->message, expect_messages->window, i);
4005 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4006 expect_messages = NULL;
4008 /* The window is iconic even though no message was sent. */
4009 ok(!IsIconic(focus_window) == !tests[i].iconic,
4010 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
4012 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4013 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
4015 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4016 ShowWindow(focus_window, SW_MINIMIZE);
4018 syscommand_received = 0;
4019 expect_messages = sc_restore_messages;
4020 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
4021 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4022 expect_messages->message, expect_messages->window, i);
4023 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
4024 expect_messages = NULL;
4025 flush_events();
4027 /* For FVWM. */
4028 ShowWindow(focus_window, SW_RESTORE);
4029 flush_events();
4031 expect_messages = sc_minimize_messages;
4032 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
4033 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4034 expect_messages->message, expect_messages->window, i);
4035 expect_messages = NULL;
4036 flush_events();
4038 expect_messages = sc_maximize_messages;
4039 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
4040 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4041 expect_messages->message, expect_messages->window, i);
4042 expect_messages = NULL;
4043 flush_events();
4045 /* Make sure the SetWindowPos call done by d3d9 is not a no-op. */
4046 SetWindowPos(focus_window, NULL, 10, 10, 100, 100, SWP_NOZORDER | SWP_NOACTIVATE);
4047 SetForegroundWindow(GetDesktopWindow());
4048 flush_events();
4049 SetForegroundWindow(GetDesktopWindow()); /* For FVWM. */
4050 flush_events();
4052 expect_messages = reactivate_messages_filtered;
4053 windowposchanged_received = 0;
4054 SetForegroundWindow(focus_window);
4055 flush_events();
4056 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4057 expect_messages->message, expect_messages->window, i);
4058 /* About 1 in 8 test runs receives WM_WINDOWPOSCHANGED on Vista. */
4059 ok(!windowposchanged_received || broken(1),
4060 "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
4061 expect_messages = NULL;
4063 filter_messages = focus_window;
4064 hr = IDirect3DDevice9_TestCooperativeLevel(device);
4065 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
4067 hr = reset_device(device, &device_desc);
4068 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4070 ref = IDirect3DDevice9_Release(device);
4071 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4073 device_desc.device_window = device_window;
4074 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4076 skip("Failed to create a D3D device, skipping tests.\n");
4077 goto done;
4079 filter_messages = NULL;
4080 flush_events();
4082 device_desc.width = user32_width;
4083 device_desc.height = user32_height;
4085 expect_messages = tests[i].mode_change_messages;
4086 filter_messages = focus_window;
4087 hr = reset_device(device, &device_desc);
4088 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4089 filter_messages = NULL;
4091 /* The WINDOWPOS structure passed to the first WM_WINDOWPOSCHANGING differs between windows versions.
4092 * Prior to Win10 17.03 it is consistent with a MoveWindow(0, 0, width, height) call. Since Windows
4093 * 10 17.03 it has x = 0, y = 0, width = 0, height = 0, flags = SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE
4094 * | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER (0x1837). Visually
4095 * it is clear that the window has not been resized. In previous Windows version the window is resized. */
4097 flush_events();
4098 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4099 expect_messages->message, expect_messages->window, i);
4101 /* World of Warplanes hides the window by removing WS_VISIBLE and expects Reset() to show it again. */
4102 device_style = GetWindowLongA(device_window, GWL_STYLE);
4103 SetWindowLongA(device_window, GWL_STYLE, device_style & ~WS_VISIBLE);
4105 flush_events();
4106 device_desc.width = d3d_width;
4107 device_desc.height = d3d_height;
4108 memset(&windowpos, 0, sizeof(windowpos));
4110 expect_messages = tests[i].mode_change_messages_hidden;
4111 filter_messages = focus_window;
4112 hr = reset_device(device, &device_desc);
4113 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4114 filter_messages = NULL;
4116 flush_events();
4117 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
4118 expect_messages->message, expect_messages->window, i);
4120 if (!(tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES))
4122 ok(windowpos.hwnd == device_window && !windowpos.hwndInsertAfter
4123 && !windowpos.x && !windowpos.y && !windowpos.cx && !windowpos.cy
4124 && windowpos.flags == (SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE),
4125 "Got unexpected WINDOWPOS hwnd=%p, insertAfter=%p, x=%d, y=%d, cx=%d, cy=%d, flags=%x\n",
4126 windowpos.hwnd, windowpos.hwndInsertAfter, windowpos.x, windowpos.y, windowpos.cx,
4127 windowpos.cy, windowpos.flags);
4130 device_style = GetWindowLongA(device_window, GWL_STYLE);
4131 if (tests[i].create_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4133 todo_wine ok(!(device_style & WS_VISIBLE), "Expected the device window to be hidden, i=%u.\n", i);
4134 ShowWindow(device_window, SW_MINIMIZE);
4135 ShowWindow(device_window, SW_RESTORE);
4137 else
4139 ok(device_style & WS_VISIBLE, "Expected the device window to be visible, i=%u.\n", i);
4142 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
4143 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx, i=%u.\n",
4144 (LONG_PTR)test_proc, i);
4146 filter_messages = focus_window;
4147 ref = IDirect3DDevice9_Release(device);
4148 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
4150 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4151 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx, i=%u.\n",
4152 (LONG_PTR)DefWindowProcA, proc, i);
4154 done:
4155 filter_messages = NULL;
4156 DestroyWindow(device_window);
4157 DestroyWindow(focus_window);
4158 SetEvent(thread_params.test_finished);
4159 WaitForSingleObject(thread, INFINITE);
4160 CloseHandle(thread);
4163 IDirect3D9_Release(d3d9);
4164 CloseHandle(thread_params.test_finished);
4165 CloseHandle(thread_params.window_created);
4166 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4169 static void test_wndproc_windowed(void)
4171 struct wndproc_thread_param thread_params;
4172 struct device_desc device_desc;
4173 IDirect3DDevice9 *device;
4174 WNDCLASSA wc = {0};
4175 IDirect3D9 *d3d9;
4176 HANDLE thread;
4177 LONG_PTR proc;
4178 HRESULT hr;
4179 ULONG ref;
4180 DWORD res, tid;
4181 HWND tmp;
4183 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4184 ok(!!d3d9, "Failed to create a D3D object.\n");
4186 wc.lpfnWndProc = test_proc;
4187 wc.lpszClassName = "d3d9_test_wndproc_wc";
4188 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4190 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
4191 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
4192 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
4193 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
4195 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4196 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4197 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4198 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
4199 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
4200 registry_mode.dmPelsHeight, 0, 0, 0, 0);
4201 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
4202 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
4204 res = WaitForSingleObject(thread_params.window_created, INFINITE);
4205 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
4207 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4208 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4209 (LONG_PTR)test_proc, proc);
4210 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4211 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4212 (LONG_PTR)test_proc, proc);
4214 trace("device_window %p, focus_window %p, dummy_window %p.\n",
4215 device_window, focus_window, thread_params.dummy_window);
4217 tmp = GetFocus();
4218 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4219 if (thread_params.running_in_foreground)
4221 tmp = GetForegroundWindow();
4222 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4223 thread_params.dummy_window, tmp);
4225 else
4226 skip("Not running in foreground, skip foreground window test\n");
4228 filter_messages = focus_window;
4230 device_desc.device_window = device_window;
4231 device_desc.width = 640;
4232 device_desc.height = 480;
4233 device_desc.flags = 0;
4234 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4236 skip("Failed to create a D3D device, skipping tests.\n");
4237 goto done;
4240 tmp = GetFocus();
4241 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
4242 tmp = GetForegroundWindow();
4243 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
4244 thread_params.dummy_window, tmp);
4246 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4247 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4248 (LONG_PTR)test_proc, proc);
4250 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4251 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4252 (LONG_PTR)test_proc, proc);
4254 filter_messages = NULL;
4256 device_desc.width = registry_mode.dmPelsWidth;
4257 device_desc.height = registry_mode.dmPelsHeight;
4258 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4259 hr = reset_device(device, &device_desc);
4260 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4262 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4263 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4264 (LONG_PTR)test_proc, proc);
4266 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4267 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4269 device_desc.flags = 0;
4270 hr = reset_device(device, &device_desc);
4271 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4273 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4274 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4275 (LONG_PTR)test_proc, proc);
4277 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4278 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4279 (LONG_PTR)test_proc, proc);
4281 filter_messages = focus_window;
4283 ref = IDirect3DDevice9_Release(device);
4284 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4286 filter_messages = device_window;
4288 device_desc.device_window = focus_window;
4289 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4291 skip("Failed to create a D3D device, skipping tests.\n");
4292 goto done;
4295 filter_messages = NULL;
4297 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4298 hr = reset_device(device, &device_desc);
4299 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4301 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4302 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4303 (LONG_PTR)test_proc, proc);
4305 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4306 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4308 device_desc.flags = 0;
4309 hr = reset_device(device, &device_desc);
4310 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4312 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4313 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4314 (LONG_PTR)test_proc, proc);
4316 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4317 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4318 (LONG_PTR)test_proc, proc);
4320 filter_messages = device_window;
4322 ref = IDirect3DDevice9_Release(device);
4323 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4325 device_desc.device_window = device_window;
4326 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4328 skip("Failed to create a D3D device, skipping tests.\n");
4329 goto done;
4332 filter_messages = NULL;
4334 device_desc.device_window = device_window;
4335 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4336 hr = reset_device(device, &device_desc);
4337 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4339 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4340 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4341 (LONG_PTR)test_proc, proc);
4343 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4344 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
4346 device_desc.flags = 0;
4347 hr = reset_device(device, &device_desc);
4348 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4350 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
4351 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4352 (LONG_PTR)test_proc, proc);
4354 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
4355 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
4356 (LONG_PTR)test_proc, proc);
4358 filter_messages = device_window;
4360 ref = IDirect3DDevice9_Release(device);
4361 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4363 done:
4364 filter_messages = NULL;
4365 IDirect3D9_Release(d3d9);
4367 SetEvent(thread_params.test_finished);
4368 WaitForSingleObject(thread, INFINITE);
4369 CloseHandle(thread_params.test_finished);
4370 CloseHandle(thread_params.window_created);
4371 CloseHandle(thread);
4373 DestroyWindow(device_window);
4374 DestroyWindow(focus_window);
4375 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
4378 static void test_reset_fullscreen(void)
4380 struct device_desc device_desc;
4381 D3DDISPLAYMODE d3ddm, d3ddm2;
4382 unsigned int mode_count, i;
4383 IDirect3DDevice9 *device;
4384 WNDCLASSEXA wc = {0};
4385 IDirect3D9 *d3d;
4386 HRESULT hr;
4387 ATOM atom;
4388 static const struct message messages[] =
4390 /* Windows usually sends wparam = TRUE, except on the testbot,
4391 * where it randomly sends FALSE. Ignore it. */
4392 {WM_ACTIVATEAPP, FOCUS_WINDOW, FALSE, 0},
4393 {0, 0, FALSE, 0},
4396 d3d = Direct3DCreate9(D3D_SDK_VERSION);
4397 ok(!!d3d, "Failed to create a D3D object.\n");
4398 expect_messages = messages;
4400 wc.cbSize = sizeof(wc);
4401 wc.lpfnWndProc = test_proc;
4402 wc.lpszClassName = "test_reset_fullscreen";
4404 atom = RegisterClassExA(&wc);
4405 ok(atom, "Failed to register a new window class. GetLastError:%d\n", GetLastError());
4407 device_window = focus_window = CreateWindowExA(0, wc.lpszClassName, "Test Reset Fullscreen", 0,
4408 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, NULL, NULL, NULL, NULL);
4409 ok(device_window != NULL, "Failed to create a window. GetLastError:%d\n", GetLastError());
4412 * Create a device in windowed mode.
4413 * Since the device is windowed and we haven't called any methods that
4414 * could show the window (such as ShowWindow or SetWindowPos) yet,
4415 * WM_ACTIVATEAPP will not have been sent.
4417 if (!(device = create_device(d3d, device_window, NULL)))
4419 skip("Unable to create device. Skipping test.\n");
4420 goto cleanup;
4424 * Switch to fullscreen mode.
4425 * This will force the window to be shown and will cause the WM_ACTIVATEAPP
4426 * message to be sent.
4428 device_desc.width = registry_mode.dmPelsWidth;
4429 device_desc.height = registry_mode.dmPelsHeight;
4430 device_desc.device_window = device_window;
4431 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4432 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4434 flush_events();
4435 ok(expect_messages->message == 0, "Expected to receive message %#x.\n", expect_messages->message);
4436 expect_messages = NULL;
4438 IDirect3D9_GetAdapterDisplayMode(d3d, D3DADAPTER_DEFAULT, &d3ddm);
4439 mode_count = IDirect3D9_GetAdapterModeCount(d3d, D3DADAPTER_DEFAULT, d3ddm.Format);
4440 for (i = 0; i < mode_count; ++i)
4442 hr = IDirect3D9_EnumAdapterModes(d3d, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
4443 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4445 if (d3ddm2.Width != d3ddm.Width || d3ddm2.Height != d3ddm.Height)
4446 break;
4448 if (i == mode_count)
4450 skip("Could not find a suitable display mode.\n");
4451 goto cleanup;
4454 wm_size_received = 0;
4456 /* Fullscreen mode change. */
4457 device_desc.width = d3ddm2.Width;
4458 device_desc.height = d3ddm2.Height;
4459 device_desc.device_window = device_window;
4460 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4461 ok(SUCCEEDED(reset_device(device, &device_desc)), "Failed to reset device.\n");
4463 flush_events();
4464 ok(!wm_size_received, "Received unexpected WM_SIZE message.\n");
4466 cleanup:
4467 if (device) IDirect3DDevice9_Release(device);
4468 IDirect3D9_Release(d3d);
4469 DestroyWindow(device_window);
4470 device_window = focus_window = NULL;
4471 UnregisterClassA(wc.lpszClassName, GetModuleHandleA(NULL));
4475 static inline void set_fpu_cw(WORD cw)
4477 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4478 #define D3D9_TEST_SET_FPU_CW 1
4479 __asm__ volatile ("fnclex");
4480 __asm__ volatile ("fldcw %0" : : "m" (cw));
4481 #elif defined(__i386__) && defined(_MSC_VER)
4482 #define D3D9_TEST_SET_FPU_CW 1
4483 __asm fnclex;
4484 __asm fldcw cw;
4485 #endif
4488 static inline WORD get_fpu_cw(void)
4490 WORD cw = 0;
4491 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
4492 #define D3D9_TEST_GET_FPU_CW 1
4493 __asm__ volatile ("fnstcw %0" : "=m" (cw));
4494 #elif defined(__i386__) && defined(_MSC_VER)
4495 #define D3D9_TEST_GET_FPU_CW 1
4496 __asm fnstcw cw;
4497 #endif
4498 return cw;
4501 static WORD callback_cw, callback_set_cw;
4502 static DWORD callback_tid;
4504 static HRESULT WINAPI dummy_object_QueryInterface(IUnknown *iface, REFIID riid, void **out)
4506 *out = NULL;
4507 return E_NOINTERFACE;
4510 static ULONG WINAPI dummy_object_AddRef(IUnknown *iface)
4512 callback_cw = get_fpu_cw();
4513 set_fpu_cw(callback_set_cw);
4514 callback_tid = GetCurrentThreadId();
4515 return 2;
4518 static ULONG WINAPI dummy_object_Release(IUnknown *iface)
4520 callback_cw = get_fpu_cw();
4521 set_fpu_cw(callback_set_cw);
4522 callback_tid = GetCurrentThreadId();
4523 return 1;
4526 static const IUnknownVtbl dummy_object_vtbl =
4528 dummy_object_QueryInterface,
4529 dummy_object_AddRef,
4530 dummy_object_Release,
4533 static const GUID d3d9_private_data_test_guid =
4535 0xfdb37466,
4536 0x428f,
4537 0x4edf,
4538 {0xa3,0x7f,0x9b,0x1d,0xf4,0x88,0xc5,0xfc}
4541 static void test_fpu_setup(void)
4543 #if defined(D3D9_TEST_SET_FPU_CW) && defined(D3D9_TEST_GET_FPU_CW)
4544 static const BOOL is_64bit = sizeof(void *) > sizeof(int);
4545 IUnknown dummy_object = {&dummy_object_vtbl};
4546 struct device_desc device_desc;
4547 IDirect3DSurface9 *surface;
4548 IDirect3DDevice9 *device;
4549 WORD cw, expected_cw;
4550 HWND window = NULL;
4551 IDirect3D9 *d3d9;
4552 HRESULT hr;
4554 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_CAPTION, 0, 0,
4555 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, 0, 0, 0, 0);
4556 ok(!!window, "Failed to create a window.\n");
4557 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4558 ok(!!d3d9, "Failed to create a D3D object.\n");
4560 device_desc.device_window = window;
4561 device_desc.width = 640;
4562 device_desc.height = 480;
4563 device_desc.flags = 0;
4565 set_fpu_cw(0xf60);
4566 cw = get_fpu_cw();
4567 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4569 if (!(device = create_device(d3d9, window, &device_desc)))
4571 skip("Failed to create a 3D device, skipping test.\n");
4572 set_fpu_cw(0x37f);
4573 goto done;
4576 expected_cw = is_64bit ? 0xf60 : 0x7f;
4578 cw = get_fpu_cw();
4579 todo_wine_if(is_64bit)
4580 ok(cw == expected_cw, "cw is %#x, expected %#x.\n", cw, expected_cw);
4582 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4583 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4585 callback_set_cw = 0xf60;
4586 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4587 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4588 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4589 todo_wine_if(is_64bit)
4590 ok(callback_cw == expected_cw, "Callback cw is %#x, expected %#x.\n", callback_cw, expected_cw);
4591 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4592 cw = get_fpu_cw();
4593 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4595 callback_cw = 0;
4596 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4597 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4598 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4599 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4600 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4602 callback_set_cw = 0x7f;
4603 set_fpu_cw(0x7f);
4605 IDirect3DSurface9_Release(surface);
4607 callback_cw = 0;
4608 IDirect3DDevice9_Release(device);
4609 ok(callback_cw == 0x7f, "Callback cw is %#x, expected 0x7f.\n", callback_cw);
4610 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4612 cw = get_fpu_cw();
4613 ok(cw == 0x7f, "cw is %#x, expected 0x7f.\n", cw);
4614 set_fpu_cw(0xf60);
4615 cw = get_fpu_cw();
4616 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4618 device_desc.flags = CREATE_DEVICE_FPU_PRESERVE;
4619 device = create_device(d3d9, window, &device_desc);
4620 ok(device != NULL, "CreateDevice failed.\n");
4622 cw = get_fpu_cw();
4623 ok(cw == 0xf60, "cw is %#x, expected 0xf60.\n", cw);
4625 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
4626 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
4628 callback_cw = 0;
4629 callback_set_cw = 0x37f;
4630 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
4631 &dummy_object, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
4632 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
4633 ok(callback_cw == 0xf60, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4634 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4635 cw = get_fpu_cw();
4636 ok(cw == 0x37f, "cw is %#x, expected 0x37f.\n", cw);
4638 IDirect3DSurface9_Release(surface);
4640 callback_cw = 0;
4641 IDirect3DDevice9_Release(device);
4642 ok(callback_cw == 0x37f, "Callback cw is %#x, expected 0xf60.\n", callback_cw);
4643 ok(callback_tid == GetCurrentThreadId(), "Got unexpected thread id.\n");
4645 done:
4646 IDirect3D9_Release(d3d9);
4647 DestroyWindow(window);
4648 #endif
4651 static void test_window_style(void)
4653 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
4654 LONG device_style, device_exstyle;
4655 LONG focus_style, focus_exstyle;
4656 struct device_desc device_desc;
4657 LONG style, expected_style;
4658 IDirect3DDevice9 *device;
4659 IDirect3D9 *d3d9;
4660 HRESULT hr;
4661 ULONG ref;
4662 BOOL ret;
4663 static const struct
4665 DWORD device_flags;
4666 LONG style, focus_loss_style, exstyle;
4668 tests[] =
4670 {0, WS_VISIBLE, WS_MINIMIZE, WS_EX_TOPMOST},
4671 {CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
4673 unsigned int i;
4675 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4676 ok(!!d3d9, "Failed to create a D3D object.\n");
4677 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
4679 for (i = 0; i < ARRAY_SIZE(tests); ++i)
4681 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4682 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4683 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4684 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
4686 device_style = GetWindowLongA(device_window, GWL_STYLE);
4687 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
4688 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
4689 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
4691 GetWindowRect(focus_window, &focus_rect);
4692 GetWindowRect(device_window, &device_rect);
4694 device_desc.device_window = device_window;
4695 device_desc.width = registry_mode.dmPelsWidth;
4696 device_desc.height = registry_mode.dmPelsHeight;
4697 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
4698 if (!(device = create_device(d3d9, focus_window, &device_desc)))
4700 skip("Failed to create a D3D device, skipping tests.\n");
4701 DestroyWindow(device_window);
4702 DestroyWindow(focus_window);
4703 break;
4706 style = GetWindowLongA(device_window, GWL_STYLE);
4707 expected_style = device_style | tests[i].style;
4708 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4709 expected_style, style, i);
4710 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4711 expected_style = device_exstyle | tests[i].exstyle;
4712 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4713 expected_style, style, i);
4715 style = GetWindowLongA(focus_window, GWL_STYLE);
4716 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4717 focus_style, style, i);
4718 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4719 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4720 focus_exstyle, style, i);
4722 GetWindowRect(device_window, &r);
4723 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4724 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
4725 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
4726 else
4727 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
4728 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
4729 GetClientRect(device_window, &r2);
4730 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal.\n");
4731 GetWindowRect(focus_window, &r);
4732 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
4733 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
4735 device_desc.flags = 0;
4736 hr = reset_device(device, &device_desc);
4737 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4739 style = GetWindowLongA(device_window, GWL_STYLE);
4740 expected_style = device_style | tests[i].style;
4741 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4742 ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
4743 expected_style, style, i);
4744 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4745 expected_style = device_exstyle | tests[i].exstyle;
4746 todo_wine_if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
4747 ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
4748 expected_style, style, i);
4750 style = GetWindowLongA(focus_window, GWL_STYLE);
4751 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
4752 focus_style, style, i);
4753 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4754 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
4755 focus_exstyle, style, i);
4757 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
4758 hr = reset_device(device, &device_desc);
4759 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4760 ret = SetForegroundWindow(GetDesktopWindow());
4761 ok(ret, "Failed to set foreground window.\n");
4763 style = GetWindowLongA(device_window, GWL_STYLE);
4764 expected_style = device_style | tests[i].focus_loss_style | tests[i].style;
4765 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x.\n",
4766 expected_style, style);
4767 style = GetWindowLongA(device_window, GWL_EXSTYLE);
4768 expected_style = device_exstyle | tests[i].exstyle;
4769 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x.\n",
4770 expected_style, style);
4772 style = GetWindowLongA(focus_window, GWL_STYLE);
4773 ok(style == focus_style, "Expected focus window style %#x, got %#x.\n",
4774 focus_style, style);
4775 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
4776 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x.\n",
4777 focus_exstyle, style);
4779 /* In d3d8 follow-up tests fail on native if the device is destroyed while
4780 * lost. This doesn't happen in d3d9 on my test machine but it still seems
4781 * like a good idea to reset it first. */
4782 ShowWindow(focus_window, SW_MINIMIZE);
4783 ShowWindow(focus_window, SW_RESTORE);
4784 ret = SetForegroundWindow(focus_window);
4785 ok(ret, "Failed to set foreground window.\n");
4786 flush_events();
4787 hr = reset_device(device, &device_desc);
4788 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
4790 ref = IDirect3DDevice9_Release(device);
4791 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
4793 DestroyWindow(device_window);
4794 DestroyWindow(focus_window);
4796 IDirect3D9_Release(d3d9);
4799 static const POINT *expect_pos;
4801 static LRESULT CALLBACK test_cursor_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
4803 if (message == WM_MOUSEMOVE)
4805 if (expect_pos && expect_pos->x && expect_pos->y)
4807 POINT p = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
4809 ClientToScreen(window, &p);
4810 if (expect_pos->x == p.x && expect_pos->y == p.y)
4811 ++expect_pos;
4815 return DefWindowProcA(window, message, wparam, lparam);
4818 static void test_cursor_pos(void)
4820 IDirect3DSurface9 *cursor;
4821 IDirect3DDevice9 *device;
4822 WNDCLASSA wc = {0};
4823 IDirect3D9 *d3d9;
4824 UINT refcount;
4825 HWND window;
4826 HRESULT hr;
4827 BOOL ret;
4829 /* Note that we don't check for movement we're not supposed to receive.
4830 * That's because it's hard to distinguish from the user accidentally
4831 * moving the mouse. */
4832 static const POINT points[] =
4834 {50, 50},
4835 {75, 75},
4836 {100, 100},
4837 {125, 125},
4838 {150, 150},
4839 {125, 125},
4840 {150, 150},
4841 {150, 150},
4842 {0, 0},
4845 wc.lpfnWndProc = test_cursor_proc;
4846 wc.lpszClassName = "d3d9_test_cursor_wc";
4847 ok(RegisterClassA(&wc), "Failed to register window class.\n");
4848 window = CreateWindowA("d3d9_test_cursor_wc", "d3d9_test", WS_POPUP | WS_SYSMENU,
4849 0, 0, 320, 240, NULL, NULL, NULL, NULL);
4850 ShowWindow(window, SW_SHOW);
4851 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4852 ok(!!d3d9, "Failed to create a D3D object.\n");
4854 device = create_device(d3d9, window, NULL);
4855 if (!device)
4857 skip("Failed to create a D3D device, skipping tests.\n");
4858 goto done;
4861 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
4862 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &cursor, NULL);
4863 ok(SUCCEEDED(hr), "Failed to create cursor surface, hr %#x.\n", hr);
4864 hr = IDirect3DDevice9_SetCursorProperties(device, 0, 0, cursor);
4865 ok(SUCCEEDED(hr), "Failed to set cursor properties, hr %#x.\n", hr);
4866 IDirect3DSurface9_Release(cursor);
4867 ret = IDirect3DDevice9_ShowCursor(device, TRUE);
4868 ok(!ret, "Failed to show cursor, hr %#x.\n", ret);
4870 flush_events();
4871 expect_pos = points;
4873 ret = SetCursorPos(50, 50);
4874 ok(ret, "Failed to set cursor position.\n");
4875 flush_events();
4877 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4878 flush_events();
4879 /* SetCursorPosition() eats duplicates. */
4880 IDirect3DDevice9_SetCursorPosition(device, 75, 75, 0);
4881 flush_events();
4883 ret = SetCursorPos(100, 100);
4884 ok(ret, "Failed to set cursor position.\n");
4885 flush_events();
4886 /* Even if the position was set with SetCursorPos(). */
4887 IDirect3DDevice9_SetCursorPosition(device, 100, 100, 0);
4888 flush_events();
4890 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4891 flush_events();
4892 ret = SetCursorPos(150, 150);
4893 ok(ret, "Failed to set cursor position.\n");
4894 flush_events();
4895 IDirect3DDevice9_SetCursorPosition(device, 125, 125, 0);
4896 flush_events();
4898 IDirect3DDevice9_SetCursorPosition(device, 150, 150, 0);
4899 flush_events();
4900 /* SetCursorPos() doesn't. */
4901 ret = SetCursorPos(150, 150);
4902 ok(ret, "Failed to set cursor position.\n");
4903 flush_events();
4905 ok(!expect_pos->x && !expect_pos->y, "Didn't receive MOUSEMOVE %u (%d, %d).\n",
4906 (unsigned)(expect_pos - points), expect_pos->x, expect_pos->y);
4908 refcount = IDirect3DDevice9_Release(device);
4909 ok(!refcount, "Device has %u references left.\n", refcount);
4910 done:
4911 DestroyWindow(window);
4912 UnregisterClassA("d3d9_test_cursor_wc", GetModuleHandleA(NULL));
4913 IDirect3D9_Release(d3d9);
4916 static void test_mode_change(void)
4918 RECT d3d_rect, focus_rect, r;
4919 struct device_desc device_desc;
4920 IDirect3DSurface9 *backbuffer;
4921 IDirect3DDevice9 *device;
4922 D3DSURFACE_DESC desc;
4923 IDirect3D9 *d3d9;
4924 DEVMODEW devmode;
4925 ULONG refcount;
4926 UINT adapter_mode_count, i;
4927 HRESULT hr;
4928 DWORD ret;
4929 LONG change_ret;
4930 D3DDISPLAYMODE d3ddm;
4931 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
4933 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
4934 ok(!!d3d9, "Failed to create a D3D object.\n");
4936 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
4937 for (i = 0; i < adapter_mode_count; ++i)
4939 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
4940 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
4942 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
4943 continue;
4944 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
4945 * refuses to create a device at these sizes. */
4946 if (d3ddm.Width < 640 || d3ddm.Height < 480)
4947 continue;
4949 if (!user32_width)
4951 user32_width = d3ddm.Width;
4952 user32_height = d3ddm.Height;
4953 continue;
4956 /* Make sure the d3d mode is smaller in width or height and at most
4957 * equal in the other dimension than the mode passed to
4958 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
4959 * the ChangeDisplaySettings parameters + 12. */
4960 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
4961 continue;
4962 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
4964 d3d_width = d3ddm.Width;
4965 d3d_height = d3ddm.Height;
4966 break;
4968 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
4970 d3d_width = user32_width;
4971 d3d_height = user32_height;
4972 user32_width = d3ddm.Width;
4973 user32_height = d3ddm.Height;
4974 break;
4978 if (!d3d_width)
4980 skip("Could not find adequate modes, skipping mode tests.\n");
4981 IDirect3D9_Release(d3d9);
4982 return;
4985 memset(&devmode, 0, sizeof(devmode));
4986 devmode.dmSize = sizeof(devmode);
4987 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
4988 devmode.dmPelsWidth = user32_width;
4989 devmode.dmPelsHeight = user32_height;
4990 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
4991 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
4993 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4994 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4995 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
4996 0, 0, user32_width / 2, user32_height / 2, 0, 0, 0, 0);
4998 SetRect(&d3d_rect, 0, 0, d3d_width, d3d_height);
4999 GetWindowRect(focus_window, &focus_rect);
5001 device_desc.device_window = device_window;
5002 device_desc.width = d3d_width;
5003 device_desc.height = d3d_height;
5004 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5005 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5007 skip("Failed to create a D3D device, skipping tests.\n");
5008 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5009 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5010 goto done;
5013 devmode.dmPelsWidth = user32_width;
5014 devmode.dmPelsHeight = user32_height;
5015 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5016 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5018 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5019 ok(ret, "Failed to get display mode.\n");
5020 ok(devmode.dmPelsWidth == user32_width && devmode.dmPelsHeight == user32_height,
5021 "Expected resolution %ux%u, got %ux%u.\n",
5022 user32_width, user32_height, devmode.dmPelsWidth, devmode.dmPelsHeight);
5024 GetWindowRect(device_window, &r);
5025 ok(EqualRect(&r, &d3d_rect), "Expected %s, got %s.\n",
5026 wine_dbgstr_rect(&d3d_rect), wine_dbgstr_rect(&r));
5027 GetWindowRect(focus_window, &r);
5028 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s.\n",
5029 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r));
5031 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
5032 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
5033 hr = IDirect3DSurface9_GetDesc(backbuffer, &desc);
5034 ok(SUCCEEDED(hr), "Failed to get backbuffer desc, hr %#x.\n", hr);
5035 ok(desc.Width == d3d_width, "Got unexpected backbuffer width %u, expected %u.\n",
5036 desc.Width, d3d_width);
5037 ok(desc.Height == d3d_height, "Got unexpected backbuffer height %u, expected %u.\n",
5038 desc.Height, d3d_height);
5039 IDirect3DSurface9_Release(backbuffer);
5041 refcount = IDirect3DDevice9_Release(device);
5042 ok(!refcount, "Device has %u references left.\n", refcount);
5044 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5045 ok(ret, "Failed to get display mode.\n");
5046 todo_wine ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5047 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5048 "Expected resolution %ux%u, got %ux%u.\n",
5049 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5051 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
5052 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5054 /* The mode restore also happens when the device was created at the original screen size. */
5056 device_desc.device_window = device_window;
5057 device_desc.width = registry_mode.dmPelsWidth;
5058 device_desc.height = registry_mode.dmPelsHeight;
5059 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5060 ok(!!(device = create_device(d3d9, focus_window, &device_desc)), "Failed to create a D3D device.\n");
5062 devmode.dmPelsWidth = user32_width;
5063 devmode.dmPelsHeight = user32_height;
5064 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
5065 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
5067 refcount = IDirect3DDevice9_Release(device);
5068 ok(!refcount, "Device has %u references left.\n", refcount);
5070 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
5071 ok(ret, "Failed to get display mode.\n");
5072 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
5073 && devmode.dmPelsHeight == registry_mode.dmPelsHeight,
5074 "Expected resolution %ux%u, got %ux%u.\n",
5075 registry_mode.dmPelsWidth, registry_mode.dmPelsHeight, devmode.dmPelsWidth, devmode.dmPelsHeight);
5077 done:
5078 DestroyWindow(device_window);
5079 DestroyWindow(focus_window);
5080 IDirect3D9_Release(d3d9);
5083 static void test_device_window_reset(void)
5085 RECT fullscreen_rect, device_rect, r;
5086 struct device_desc device_desc;
5087 IDirect3DDevice9 *device;
5088 WNDCLASSA wc = {0};
5089 IDirect3D9 *d3d9;
5090 LONG_PTR proc;
5091 HRESULT hr;
5092 ULONG ref;
5094 wc.lpfnWndProc = test_proc;
5095 wc.lpszClassName = "d3d9_test_wndproc_wc";
5096 ok(RegisterClassA(&wc), "Failed to register window class.\n");
5098 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5099 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
5100 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5101 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
5102 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5103 ok(!!d3d9, "Failed to create a D3D object.\n");
5105 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
5106 GetWindowRect(device_window, &device_rect);
5108 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5109 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5110 (LONG_PTR)test_proc, proc);
5111 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5112 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5113 (LONG_PTR)test_proc, proc);
5115 device_desc.device_window = NULL;
5116 device_desc.width = registry_mode.dmPelsWidth;
5117 device_desc.height = registry_mode.dmPelsHeight;
5118 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5119 if (!(device = create_device(d3d9, focus_window, &device_desc)))
5121 skip("Failed to create a D3D device, skipping tests.\n");
5122 goto done;
5125 GetWindowRect(focus_window, &r);
5126 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5127 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5128 GetWindowRect(device_window, &r);
5129 ok(EqualRect(&r, &device_rect), "Expected %s, got %s.\n",
5130 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r));
5132 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5133 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5134 (LONG_PTR)test_proc, proc);
5135 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5136 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5138 device_desc.device_window = device_window;
5139 hr = reset_device(device, &device_desc);
5140 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5142 GetWindowRect(focus_window, &r);
5143 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5144 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5145 GetWindowRect(device_window, &r);
5146 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s.\n",
5147 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r));
5149 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
5150 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
5151 (LONG_PTR)test_proc, proc);
5152 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
5153 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
5155 ref = IDirect3DDevice9_Release(device);
5156 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5158 done:
5159 IDirect3D9_Release(d3d9);
5160 DestroyWindow(device_window);
5161 DestroyWindow(focus_window);
5162 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
5165 static void test_reset_resources(void)
5167 IDirect3DSurface9 *surface, *rt;
5168 IDirect3DTexture9 *texture;
5169 IDirect3DDevice9 *device;
5170 IDirect3D9 *d3d9;
5171 unsigned int i;
5172 D3DCAPS9 caps;
5173 HWND window;
5174 HRESULT hr;
5175 ULONG ref;
5177 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5178 0, 0, 640, 480, 0, 0, 0, 0);
5179 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5180 ok(!!d3d9, "Failed to create a D3D object.\n");
5182 if (!(device = create_device(d3d9, window, NULL)))
5184 skip("Failed to create a D3D device, skipping tests.\n");
5185 goto done;
5188 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5189 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5191 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128,
5192 D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
5193 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
5194 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
5195 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
5196 IDirect3DSurface9_Release(surface);
5198 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
5200 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
5201 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
5202 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
5203 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
5204 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
5205 IDirect3DTexture9_Release(texture);
5206 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
5207 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
5208 IDirect3DSurface9_Release(surface);
5211 hr = reset_device(device, NULL);
5212 ok(SUCCEEDED(hr), "Failed to reset device.\n");
5214 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
5215 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
5216 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
5217 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
5218 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
5219 IDirect3DSurface9_Release(surface);
5220 IDirect3DSurface9_Release(rt);
5222 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
5224 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
5225 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
5228 ref = IDirect3DDevice9_Release(device);
5229 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
5231 done:
5232 IDirect3D9_Release(d3d9);
5233 DestroyWindow(window);
5236 static void test_set_rt_vp_scissor(void)
5238 IDirect3DStateBlock9 *stateblock;
5239 IDirect3DDevice9 *device;
5240 IDirect3DSurface9 *rt;
5241 IDirect3D9 *d3d9;
5242 D3DVIEWPORT9 vp;
5243 UINT refcount;
5244 HWND window;
5245 HRESULT hr;
5246 RECT rect;
5248 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
5249 0, 0, 640, 480, 0, 0, 0, 0);
5250 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5251 ok(!!d3d9, "Failed to create a D3D object.\n");
5252 if (!(device = create_device(d3d9, window, NULL)))
5254 skip("Failed to create a D3D device, skipping tests.\n");
5255 DestroyWindow(window);
5256 return;
5259 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
5260 D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5261 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5263 hr = IDirect3DDevice9_GetViewport(device, &vp);
5264 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5265 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5266 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5267 ok(vp.Width == 640, "Got unexpected vp.Width %u.\n", vp.Width);
5268 ok(vp.Height == 480, "Got unexpected vp.Height %u.\n", vp.Height);
5269 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5270 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5272 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5273 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5274 ok(rect.left == 0 && rect.top == 0 && rect.right == 640 && rect.bottom == 480,
5275 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5277 hr = IDirect3DDevice9_BeginStateBlock(device);
5278 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
5280 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5281 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5283 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
5284 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
5285 IDirect3DStateBlock9_Release(stateblock);
5287 hr = IDirect3DDevice9_GetViewport(device, &vp);
5288 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5289 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5290 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5291 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5292 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5293 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5294 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5296 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5297 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5298 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5299 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5301 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5302 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5304 vp.X = 10;
5305 vp.Y = 20;
5306 vp.Width = 30;
5307 vp.Height = 40;
5308 vp.MinZ = 0.25f;
5309 vp.MaxZ = 0.75f;
5310 hr = IDirect3DDevice9_SetViewport(device, &vp);
5311 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5313 SetRect(&rect, 50, 60, 70, 80);
5314 hr = IDirect3DDevice9_SetScissorRect(device, &rect);
5315 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
5317 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5318 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5320 hr = IDirect3DDevice9_GetViewport(device, &vp);
5321 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
5322 ok(!vp.X, "Got unexpected vp.X %u.\n", vp.X);
5323 ok(!vp.Y, "Got unexpected vp.Y %u.\n", vp.Y);
5324 ok(vp.Width == 128, "Got unexpected vp.Width %u.\n", vp.Width);
5325 ok(vp.Height == 128, "Got unexpected vp.Height %u.\n", vp.Height);
5326 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
5327 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
5329 hr = IDirect3DDevice9_GetScissorRect(device, &rect);
5330 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
5331 ok(rect.left == 0 && rect.top == 0 && rect.right == 128 && rect.bottom == 128,
5332 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
5334 IDirect3DSurface9_Release(rt);
5335 refcount = IDirect3DDevice9_Release(device);
5336 ok(!refcount, "Device has %u references left.\n", refcount);
5337 IDirect3D9_Release(d3d9);
5338 DestroyWindow(window);
5341 static void test_volume_get_container(void)
5343 IDirect3DVolumeTexture9 *texture = NULL;
5344 IDirect3DVolume9 *volume = NULL;
5345 IDirect3DDevice9 *device;
5346 IUnknown *container;
5347 IDirect3D9 *d3d9;
5348 ULONG refcount;
5349 D3DCAPS9 caps;
5350 HWND window;
5351 HRESULT hr;
5353 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5354 0, 0, 640, 480, 0, 0, 0, 0);
5355 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5356 ok(!!d3d9, "Failed to create a D3D object.\n");
5357 if (!(device = create_device(d3d9, window, NULL)))
5359 skip("Failed to create a D3D device, skipping tests.\n");
5360 IDirect3D9_Release(d3d9);
5361 DestroyWindow(window);
5362 return;
5365 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5366 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5367 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5369 skip("No volume texture support, skipping tests.\n");
5370 IDirect3DDevice9_Release(device);
5371 IDirect3D9_Release(d3d9);
5372 DestroyWindow(window);
5373 return;
5376 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5377 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5378 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5379 ok(!!texture, "Got unexpected texture %p.\n", texture);
5381 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5382 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5383 ok(!!volume, "Got unexpected volume %p.\n", volume);
5385 /* These should work... */
5386 container = NULL;
5387 hr = IDirect3DVolume9_GetContainer(volume, &IID_IUnknown, (void **)&container);
5388 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5389 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5390 IUnknown_Release(container);
5392 container = NULL;
5393 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DResource9, (void **)&container);
5394 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5395 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5396 IUnknown_Release(container);
5398 container = NULL;
5399 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DBaseTexture9, (void **)&container);
5400 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5401 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5402 IUnknown_Release(container);
5404 container = NULL;
5405 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolumeTexture9, (void **)&container);
5406 ok(SUCCEEDED(hr), "Failed to get volume container, hr %#x.\n", hr);
5407 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
5408 IUnknown_Release(container);
5410 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
5411 hr = IDirect3DVolume9_GetContainer(volume, &IID_IDirect3DVolume9, (void **)&container);
5412 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5413 ok(!container, "Got unexpected container %p.\n", container);
5415 IDirect3DVolume9_Release(volume);
5416 IDirect3DVolumeTexture9_Release(texture);
5417 refcount = IDirect3DDevice9_Release(device);
5418 ok(!refcount, "Device has %u references left.\n", refcount);
5419 IDirect3D9_Release(d3d9);
5420 DestroyWindow(window);
5423 static void test_volume_resource(void)
5425 IDirect3DVolumeTexture9 *texture;
5426 IDirect3DResource9 *resource;
5427 IDirect3DVolume9 *volume;
5428 IDirect3DDevice9 *device;
5429 IDirect3D9 *d3d9;
5430 ULONG refcount;
5431 D3DCAPS9 caps;
5432 HWND window;
5433 HRESULT hr;
5435 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5436 0, 0, 640, 480, 0, 0, 0, 0);
5437 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5438 ok(!!d3d9, "Failed to create a D3D object.\n");
5439 if (!(device = create_device(d3d9, window, NULL)))
5441 skip("Failed to create a D3D device, skipping tests.\n");
5442 IDirect3D9_Release(d3d9);
5443 DestroyWindow(window);
5444 return;
5447 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5448 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5449 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
5451 skip("No volume texture support, skipping tests.\n");
5452 IDirect3DDevice9_Release(device);
5453 IDirect3D9_Release(d3d9);
5454 DestroyWindow(window);
5455 return;
5458 hr = IDirect3DDevice9_CreateVolumeTexture(device, 128, 128, 128, 1, 0,
5459 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, 0);
5460 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
5461 hr = IDirect3DVolumeTexture9_GetVolumeLevel(texture, 0, &volume);
5462 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
5463 IDirect3DVolumeTexture9_Release(texture);
5465 hr = IDirect3DVolume9_QueryInterface(volume, &IID_IDirect3DResource9, (void **)&resource);
5466 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
5468 IDirect3DVolume9_Release(volume);
5469 refcount = IDirect3DDevice9_Release(device);
5470 ok(!refcount, "Device has %u references left.\n", refcount);
5471 IDirect3D9_Release(d3d9);
5472 DestroyWindow(window);
5475 static void test_vb_lock_flags(void)
5477 static const struct
5479 DWORD flags;
5480 const char *debug_string;
5481 HRESULT win7_result;
5483 test_data[] =
5485 {D3DLOCK_READONLY, "D3DLOCK_READONLY", D3D_OK },
5486 {D3DLOCK_DISCARD, "D3DLOCK_DISCARD", D3D_OK },
5487 {D3DLOCK_NOOVERWRITE, "D3DLOCK_NOOVERWRITE", D3D_OK },
5488 {D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD", D3D_OK },
5489 {D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY, "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY", D3D_OK },
5490 {D3DLOCK_READONLY | D3DLOCK_DISCARD, "D3DLOCK_READONLY | D3DLOCK_DISCARD", D3DERR_INVALIDCALL},
5491 /* Completely bogus flags aren't an error. */
5492 {0xdeadbeef, "0xdeadbeef", D3DERR_INVALIDCALL},
5494 IDirect3DVertexBuffer9 *buffer;
5495 IDirect3DDevice9 *device;
5496 IDirect3D9 *d3d9;
5497 unsigned int i;
5498 ULONG refcount;
5499 HWND window;
5500 HRESULT hr;
5501 void *data;
5503 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5504 0, 0, 640, 480, 0, 0, 0, 0);
5505 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5506 ok(!!d3d9, "Failed to create a D3D object.\n");
5507 if (!(device = create_device(d3d9, window, NULL)))
5509 skip("Failed to create a D3D device, skipping tests.\n");
5510 IDirect3D9_Release(d3d9);
5511 DestroyWindow(window);
5512 return;
5515 hr = IDirect3DDevice9_CreateVertexBuffer(device, 1024, D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
5516 ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
5518 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
5520 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, test_data[i].flags);
5521 /* Windows XP always returns D3D_OK even with flags that don't make
5522 * sense. Windows 7 returns an error. At least one game (Shaiya)
5523 * depends on the Windows XP result, so mark the Windows 7 behavior as
5524 * broken. */
5525 ok(hr == D3D_OK || broken(hr == test_data[i].win7_result), "Got unexpected hr %#x for %s.\n",
5526 hr, test_data[i].debug_string);
5527 if (SUCCEEDED(hr))
5529 ok(!!data, "Got unexpected data %p.\n", data);
5530 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5531 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5535 IDirect3DVertexBuffer9_Release(buffer);
5536 refcount = IDirect3DDevice9_Release(device);
5537 ok(!refcount, "Device has %u references left.\n", refcount);
5538 IDirect3D9_Release(d3d9);
5539 DestroyWindow(window);
5542 static const char *debug_d3dpool(D3DPOOL pool)
5544 switch (pool)
5546 case D3DPOOL_DEFAULT:
5547 return "D3DPOOL_DEFAULT";
5548 case D3DPOOL_SYSTEMMEM:
5549 return "D3DPOOL_SYSTEMMEM";
5550 case D3DPOOL_SCRATCH:
5551 return "D3DPOOL_SCRATCH";
5552 case D3DPOOL_MANAGED:
5553 return "D3DPOOL_MANAGED";
5554 default:
5555 return "unknown pool";
5559 static void test_vertex_buffer_alignment(void)
5561 static const D3DPOOL pools[] = {D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DPOOL_MANAGED};
5562 static const DWORD sizes[] = {1, 4, 16, 17, 32, 33, 64, 65, 1024, 1025, 1048576, 1048577};
5563 IDirect3DVertexBuffer9 *buffer = NULL;
5564 const unsigned int align = 16;
5565 IDirect3DDevice9 *device;
5566 unsigned int i, j;
5567 IDirect3D9 *d3d9;
5568 ULONG refcount;
5569 HWND window;
5570 HRESULT hr;
5571 void *data;
5573 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5574 0, 0, 640, 480, 0, 0, 0, 0);
5575 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5576 ok(!!d3d9, "Failed to create a D3D object.\n");
5577 if (!(device = create_device(d3d9, window, NULL)))
5579 skip("Failed to create a D3D device, skipping tests.\n");
5580 IDirect3D9_Release(d3d9);
5581 DestroyWindow(window);
5582 return;
5585 for (i = 0; i < ARRAY_SIZE(sizes); ++i)
5587 for (j = 0; j < ARRAY_SIZE(pools); ++j)
5589 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizes[i], 0, 0, pools[j], &buffer, NULL);
5590 if (pools[j] == D3DPOOL_SCRATCH)
5591 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x trying to create a D3DPOOL_SCRATCH buffer.\n", hr);
5592 else
5593 ok(SUCCEEDED(hr), "Failed to create vertex buffer in pool %s with size %u, hr %#x.\n",
5594 debug_d3dpool(pools[j]), sizes[i], hr);
5595 if (FAILED(hr))
5596 continue;
5598 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, 0);
5599 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
5600 ok(!((DWORD_PTR)data & (align - 1)),
5601 "Vertex buffer start address %p is not %u byte aligned (size %u, pool %s).\n",
5602 data, align, sizes[i], debug_d3dpool(pools[j]));
5603 hr = IDirect3DVertexBuffer9_Unlock(buffer);
5604 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
5605 IDirect3DVertexBuffer9_Release(buffer);
5609 refcount = IDirect3DDevice9_Release(device);
5610 ok(!refcount, "Device has %u references left.\n", refcount);
5611 IDirect3D9_Release(d3d9);
5612 DestroyWindow(window);
5615 static void test_query_support(void)
5617 static const D3DQUERYTYPE queries[] =
5619 D3DQUERYTYPE_VCACHE,
5620 D3DQUERYTYPE_RESOURCEMANAGER,
5621 D3DQUERYTYPE_VERTEXSTATS,
5622 D3DQUERYTYPE_EVENT,
5623 D3DQUERYTYPE_OCCLUSION,
5624 D3DQUERYTYPE_TIMESTAMP,
5625 D3DQUERYTYPE_TIMESTAMPDISJOINT,
5626 D3DQUERYTYPE_TIMESTAMPFREQ,
5627 D3DQUERYTYPE_PIPELINETIMINGS,
5628 D3DQUERYTYPE_INTERFACETIMINGS,
5629 D3DQUERYTYPE_VERTEXTIMINGS,
5630 D3DQUERYTYPE_PIXELTIMINGS,
5631 D3DQUERYTYPE_BANDWIDTHTIMINGS,
5632 D3DQUERYTYPE_CACHEUTILIZATION,
5634 IDirect3DQuery9 *query = NULL;
5635 IDirect3DDevice9 *device;
5636 IDirect3D9 *d3d9;
5637 unsigned int i;
5638 ULONG refcount;
5639 BOOL supported;
5640 HWND window;
5641 HRESULT hr;
5643 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5644 0, 0, 640, 480, 0, 0, 0, 0);
5645 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5646 ok(!!d3d9, "Failed to create a D3D object.\n");
5647 if (!(device = create_device(d3d9, window, NULL)))
5649 skip("Failed to create a D3D device, skipping tests.\n");
5650 IDirect3D9_Release(d3d9);
5651 DestroyWindow(window);
5652 return;
5655 for (i = 0; i < ARRAY_SIZE(queries); ++i)
5657 hr = IDirect3DDevice9_CreateQuery(device, queries[i], NULL);
5658 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5660 supported = hr == D3D_OK;
5662 hr = IDirect3DDevice9_CreateQuery(device, queries[i], &query);
5663 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, queries[i]);
5665 ok(!supported || query, "Query %#x was claimed to be supported, but can't be created.\n", queries[i]);
5666 ok(supported || !query, "Query %#x was claimed not to be supported, but can be created.\n", queries[i]);
5668 if (query)
5670 IDirect3DQuery9_Release(query);
5671 query = NULL;
5675 for (i = 0; i < 40; ++i)
5677 /* Windows 10 17.09 (build 16299.19) added an undocumented query with an enum value of 0x16 (=22).
5678 * It returns D3D_OK when asking for support and E_FAIL when trying to actually create it. */
5679 if ((D3DQUERYTYPE_VCACHE <= i && i <= D3DQUERYTYPE_MEMORYPRESSURE) || i == 0x16)
5680 continue;
5682 hr = IDirect3DDevice9_CreateQuery(device, i, NULL);
5683 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5685 query = (IDirect3DQuery9 *)0xdeadbeef;
5686 hr = IDirect3DDevice9_CreateQuery(device, i, &query);
5687 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x for query %#x.\n", hr, i);
5688 ok(query == (IDirect3DQuery9 *)0xdeadbeef, "Got unexpected query %p.\n", query);
5691 refcount = IDirect3DDevice9_Release(device);
5692 ok(!refcount, "Device has %u references left.\n", refcount);
5693 IDirect3D9_Release(d3d9);
5694 DestroyWindow(window);
5697 static void test_occlusion_query(void)
5699 static const float quad[] =
5701 -1.0f, -1.0f, 0.0f,
5702 -1.0f, 1.0f, 0.0f,
5703 1.0f, 1.0f, 0.0f,
5704 1.0f, -1.0f, 0.0f,
5706 unsigned int data_size, i, count;
5707 struct device_desc device_desc;
5708 IDirect3DQuery9 *query = NULL;
5709 IDirect3DDevice9 *device;
5710 IDirect3DSurface9 *rt;
5711 IDirect3D9 *d3d9;
5712 D3DVIEWPORT9 vp;
5713 ULONG refcount;
5714 D3DCAPS9 caps;
5715 HWND window;
5716 HRESULT hr;
5717 union
5719 WORD word[4];
5720 DWORD dword[2];
5721 UINT64 uint;
5722 } data, expected;
5723 BOOL broken_occlusion = FALSE;
5724 expected.uint = registry_mode.dmPelsWidth * registry_mode.dmPelsHeight;
5726 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
5727 0, 0, 640, 480, 0, 0, 0, 0);
5728 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5729 ok(!!d3d9, "Failed to create a D3D object.\n");
5730 device_desc.device_window = window;
5731 device_desc.width = registry_mode.dmPelsWidth;
5732 device_desc.height = registry_mode.dmPelsHeight;
5733 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
5734 if (!(device = create_device(d3d9, window, &device_desc)))
5736 skip("Failed to create a D3D device, skipping tests.\n");
5737 IDirect3D9_Release(d3d9);
5738 DestroyWindow(window);
5739 return;
5742 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 1.0f, 0);
5743 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
5744 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5745 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5746 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5747 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
5749 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_OCCLUSION, &query);
5750 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5751 if (!query)
5753 skip("Occlusion queries are not supported, skipping tests.\n");
5754 IDirect3DDevice9_Release(device);
5755 IDirect3D9_Release(d3d9);
5756 DestroyWindow(window);
5757 return;
5760 data_size = IDirect3DQuery9_GetDataSize(query);
5761 ok(data_size == sizeof(DWORD), "Unexpected data size %u.\n", data_size);
5763 memset(&data, 0xff, sizeof(data));
5764 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5765 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5766 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5767 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5768 ok(data.dword[0] == 0xdddddddd && data.dword[1] == 0xffffffff,
5769 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5771 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5772 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5773 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5774 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5775 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5776 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5778 data.dword[0] = 0x12345678;
5779 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
5780 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5781 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5782 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5783 if (hr == D3D_OK)
5784 ok(!data.dword[0], "Got unexpected query result %u.\n", data.dword[0]);
5786 hr = IDirect3DDevice9_BeginScene(device);
5787 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5788 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5789 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5790 hr = IDirect3DDevice9_EndScene(device);
5791 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5793 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5794 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5795 for (i = 0; i < 500; ++i)
5797 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5798 break;
5799 Sleep(10);
5801 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5803 memset(&data, 0xff, sizeof(data));
5804 hr = IDirect3DQuery9_GetData(query, &data, data_size, D3DGETDATA_FLUSH);
5805 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5806 ok(data.dword[0] == expected.dword[0] || broken(!data.dword[0]),
5807 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5808 if (!data.dword[0])
5810 win_skip("Occlusion query result looks broken, ignoring returned count.\n");
5811 broken_occlusion = TRUE;
5814 memset(&data, 0xff, sizeof(data));
5815 hr = IDirect3DQuery9_GetData(query, &data, sizeof(WORD), D3DGETDATA_FLUSH);
5816 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5817 if (!broken_occlusion)
5818 ok(data.word[0] == expected.word[0],
5819 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5820 ok(data.word[1] == 0xffff,
5821 "Data was modified outside of the expected size (0x%.8x).\n", data.dword[0]);
5823 memset(&data, 0xf0, sizeof(data));
5824 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5825 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5826 if (!broken_occlusion)
5827 ok(data.dword[0] == expected.dword[0],
5828 "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5829 /* Different drivers seem to return different data in those high bytes on Windows, but they all
5830 write something there and the extra data is consistent (I've seen 0x00000000 and 0xdddddddd
5831 on AMD and Nvidia respectively). */
5832 if (0)
5834 ok(data.dword[1] != 0xf0f0f0f0, "high bytes of data were not modified (0x%.8x).\n",
5835 data.dword[1]);
5838 memset(&data, 0xff, sizeof(data));
5839 hr = IDirect3DQuery9_GetData(query, &data, 0, D3DGETDATA_FLUSH);
5840 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5841 ok(data.dword[0] == 0xffffffff, "Occlusion query returned an unexpected result (0x%.8x).\n", data.dword[0]);
5843 /* This crashes on Windows. */
5844 if (0)
5846 hr = IDirect3DQuery9_GetData(query, NULL, data_size, D3DGETDATA_FLUSH);
5847 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5850 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5851 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5852 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5853 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5854 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5855 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5857 if (broken_occlusion)
5858 goto done;
5860 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
5861 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
5863 vp.X = 0;
5864 vp.Y = 0;
5865 vp.Width = min(caps.MaxTextureWidth, 8192);
5866 vp.Height = min(caps.MaxTextureHeight, 8192);
5867 vp.MinZ = 0.0f;
5868 vp.MaxZ = 1.0f;
5869 hr = IDirect3DDevice9_SetViewport(device, &vp);
5870 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
5872 hr = IDirect3DDevice9_CreateRenderTarget(device, vp.Width, vp.Height,
5873 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
5874 if (FAILED(hr))
5876 skip("Failed to create render target (width %u, height %u), hr %#x.\n", vp.Width, vp.Height, hr);
5877 goto done;
5879 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
5880 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
5881 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
5882 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
5883 ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
5885 expected.uint = vp.Width * vp.Height;
5886 count = ((((UINT64)~0u) + 1) / expected.uint) + 1;
5887 expected.uint *= count;
5889 trace("Expects 0x%08x%08x samples.\n", expected.dword[1], expected.dword[0]);
5891 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
5892 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5893 hr = IDirect3DDevice9_BeginScene(device);
5894 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
5895 for (i = 0; i < count; i++)
5897 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
5898 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
5900 hr = IDirect3DDevice9_EndScene(device);
5901 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
5902 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
5903 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5905 for (i = 0; i < 500; ++i)
5907 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
5908 break;
5909 Sleep(10);
5911 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5913 memset(&data, 0xff, sizeof(data));
5914 hr = IDirect3DQuery9_GetData(query, &data, sizeof(data), D3DGETDATA_FLUSH);
5915 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5916 ok((data.dword[0] == expected.dword[0] && data.dword[1] == expected.dword[1])
5917 || (data.dword[0] == 0xffffffff && !data.dword[1])
5918 || broken(data.dword[0] < 0xffffffff && !data.dword[1]),
5919 "Got unexpected query result 0x%08x%08x.\n", data.dword[1], data.dword[0]);
5921 IDirect3DSurface9_Release(rt);
5923 done:
5924 IDirect3DQuery9_Release(query);
5925 refcount = IDirect3DDevice9_Release(device);
5926 ok(!refcount, "Device has %u references left.\n", refcount);
5927 IDirect3D9_Release(d3d9);
5928 DestroyWindow(window);
5931 static void test_timestamp_query(void)
5933 static const float quad[] =
5935 -1.0f, -1.0f, 0.0f,
5936 -1.0f, 1.0f, 0.0f,
5937 1.0f, 1.0f, 0.0f,
5938 1.0f, -1.0f, 0.0f,
5940 IDirect3DQuery9 *query, *disjoint_query, *freq_query;
5941 unsigned int data_size, i;
5942 IDirect3DDevice9 *device;
5943 IDirect3D9 *d3d9;
5944 ULONG refcount;
5945 HWND window;
5946 HRESULT hr;
5947 DWORD timestamp[2], freq[2];
5948 WORD disjoint[2];
5950 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
5951 0, 0, 640, 480, 0, 0, 0, 0);
5952 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
5953 ok(!!d3d9, "Failed to create a D3D object.\n");
5954 if (!(device = create_device(d3d9, window, NULL)))
5956 skip("Failed to create a D3D device, skipping tests.\n");
5957 IDirect3D9_Release(d3d9);
5958 DestroyWindow(window);
5959 return;
5962 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPFREQ, &freq_query);
5963 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
5964 if (FAILED(hr))
5966 skip("Timestamp queries are not supported, skipping tests.\n");
5967 IDirect3DDevice9_Release(device);
5968 IDirect3D9_Release(d3d9);
5969 DestroyWindow(window);
5970 return;
5972 data_size = IDirect3DQuery9_GetDataSize(freq_query);
5973 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
5975 memset(freq, 0xff, sizeof(freq));
5976 hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH);
5977 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5978 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
5979 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5980 ok(freq[0] == 0xdddddddd && freq[1] == 0xffffffff,
5981 "Got unexpected query result 0x%08x%08x.\n", freq[1], freq[0]);
5983 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMPDISJOINT, &disjoint_query);
5984 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
5985 data_size = IDirect3DQuery9_GetDataSize(disjoint_query);
5986 ok(data_size == sizeof(BOOL), "Query data size is %u, 4 expected.\n", data_size);
5988 memset(disjoint, 0xff, sizeof(disjoint));
5989 hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH);
5990 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5991 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
5992 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5993 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xffff,
5994 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
5995 hr = IDirect3DQuery9_GetData(disjoint_query, &disjoint, sizeof(DWORD), D3DGETDATA_FLUSH);
5996 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
5997 ok(disjoint[0] == 0xdddd && disjoint[1] == 0xdddd,
5998 "Got unexpected query result 0x%04x%04x.\n", disjoint[1], disjoint[0]);
6000 hr = IDirect3DDevice9_CreateQuery(device, D3DQUERYTYPE_TIMESTAMP, &query);
6001 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6002 data_size = IDirect3DQuery9_GetDataSize(query);
6003 ok(data_size == sizeof(UINT64), "Query data size is %u, 8 expected.\n", data_size);
6005 hr = IDirect3DQuery9_Issue(freq_query, D3DISSUE_END);
6006 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6007 for (i = 0; i < 500; ++i)
6009 if ((hr = IDirect3DQuery9_GetData(freq_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6010 break;
6011 Sleep(10);
6013 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6015 memset(freq, 0xff, sizeof(freq));
6016 hr = IDirect3DQuery9_GetData(freq_query, freq, sizeof(DWORD), D3DGETDATA_FLUSH);
6017 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6018 ok(freq[1] == 0xffffffff,
6019 "Freq was modified outside of the expected size (0x%.8x).\n", freq[1]);
6020 hr = IDirect3DQuery9_GetData(freq_query, &freq, sizeof(freq), D3DGETDATA_FLUSH);
6021 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6022 ok(freq[1] != 0xffffffff, "High bytes of freq were not modified (0x%.8x).\n",
6023 freq[1]);
6025 memset(timestamp, 0xff, sizeof(timestamp));
6026 hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH);
6027 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6028 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6029 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6030 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xffffffff,
6031 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6032 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6033 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6034 ok(timestamp[0] == 0xdddddddd && timestamp[1] == 0xdddddddd,
6035 "Got unexpected query result 0x%08x%08x.\n", timestamp[1], timestamp[0]);
6037 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
6038 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6039 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
6040 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6041 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_BEGIN);
6042 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6044 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6045 ok(hr == S_FALSE || hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6047 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6048 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
6049 hr = IDirect3DDevice9_BeginScene(device);
6050 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6051 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6052 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6053 hr = IDirect3DDevice9_EndScene(device);
6054 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6056 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6057 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6058 for (i = 0; i < 500; ++i)
6060 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6061 break;
6062 Sleep(10);
6064 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6066 memset(timestamp, 0xff, sizeof(timestamp));
6067 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(DWORD), D3DGETDATA_FLUSH);
6068 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6069 ok(timestamp[1] == 0xffffffff,
6070 "Timestamp was modified outside of the expected size (0x%.8x).\n",
6071 timestamp[1]);
6073 hr = IDirect3DQuery9_Issue(query, D3DISSUE_BEGIN);
6074 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6075 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6076 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6077 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6078 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6080 hr = IDirect3DQuery9_Issue(disjoint_query, D3DISSUE_END);
6081 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6082 for (i = 0; i < 500; ++i)
6084 if ((hr = IDirect3DQuery9_GetData(disjoint_query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6085 break;
6086 Sleep(10);
6088 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6090 memset(disjoint, 0xff, sizeof(disjoint));
6091 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(WORD), D3DGETDATA_FLUSH);
6092 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6093 ok(disjoint[1] == 0xffff,
6094 "Disjoint was modified outside of the expected size (0x%.4hx).\n", disjoint[1]);
6095 hr = IDirect3DQuery9_GetData(disjoint_query, disjoint, sizeof(disjoint), D3DGETDATA_FLUSH);
6096 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6097 ok(disjoint[1] != 0xffff, "High bytes of disjoint were not modified (0x%.4hx).\n", disjoint[1]);
6099 /* It's not strictly necessary for the TIMESTAMP query to be inside
6100 * a TIMESTAMP_DISJOINT query. */
6101 hr = IDirect3DDevice9_BeginScene(device);
6102 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
6103 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLEFAN, 2, quad, 3 * sizeof(float));
6104 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
6105 hr = IDirect3DDevice9_EndScene(device);
6106 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
6108 hr = IDirect3DQuery9_Issue(query, D3DISSUE_END);
6109 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6110 for (i = 0; i < 500; ++i)
6112 if ((hr = IDirect3DQuery9_GetData(query, NULL, 0, D3DGETDATA_FLUSH)) != S_FALSE)
6113 break;
6114 Sleep(10);
6116 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6117 hr = IDirect3DQuery9_GetData(query, timestamp, sizeof(timestamp), D3DGETDATA_FLUSH);
6118 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
6120 IDirect3DQuery9_Release(query);
6121 IDirect3DQuery9_Release(disjoint_query);
6122 IDirect3DQuery9_Release(freq_query);
6123 refcount = IDirect3DDevice9_Release(device);
6124 ok(!refcount, "Device has %u references left.\n", refcount);
6125 IDirect3D9_Release(d3d9);
6126 DestroyWindow(window);
6129 static void test_get_set_vertex_shader(void)
6131 IDirect3DVertexShader9 *current_shader = NULL;
6132 IDirect3DVertexShader9 *shader = NULL;
6133 const IDirect3DVertexShader9Vtbl *shader_vtbl;
6134 IDirect3DDevice9 *device;
6135 ULONG refcount, i;
6136 IDirect3D9 *d3d;
6137 D3DCAPS9 caps;
6138 HWND window;
6139 HRESULT hr;
6141 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6142 0, 0, 640, 480, 0, 0, 0, 0);
6143 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6144 ok(!!d3d, "Failed to create a D3D object.\n");
6145 if (!(device = create_device(d3d, window, NULL)))
6147 skip("Failed to create a D3D device, skipping tests.\n");
6148 IDirect3D9_Release(d3d);
6149 DestroyWindow(window);
6150 return;
6153 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6154 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6155 if (!(caps.VertexShaderVersion & 0xffff))
6157 skip("No vertex shader support, skipping tests.\n");
6158 IDirect3DDevice9_Release(device);
6159 IDirect3D9_Release(d3d);
6160 DestroyWindow(window);
6161 return;
6164 hr = IDirect3DDevice9_CreateVertexShader(device, simple_vs, &shader);
6165 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6166 ok(!!shader, "Got unexpected shader %p.\n", shader);
6168 /* SetVertexShader() should not touch the shader's refcount. */
6169 i = get_refcount((IUnknown *)shader);
6170 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6171 refcount = get_refcount((IUnknown *)shader);
6172 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6173 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6175 /* GetVertexShader() should increase the shader's refcount by one. */
6176 i = refcount + 1;
6177 hr = IDirect3DDevice9_GetVertexShader(device, &current_shader);
6178 refcount = get_refcount((IUnknown *)shader);
6179 ok(SUCCEEDED(hr), "Failed to get vertex shader, hr %#x.\n", hr);
6180 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6181 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6182 IDirect3DVertexShader9_Release(current_shader);
6184 /* SetVertexShader() with a bogus shader vtbl */
6185 shader_vtbl = shader->lpVtbl;
6186 shader->lpVtbl = (IDirect3DVertexShader9Vtbl *)0xdeadbeef;
6187 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6188 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6189 shader->lpVtbl = NULL;
6190 hr = IDirect3DDevice9_SetVertexShader(device, shader);
6191 ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
6192 shader->lpVtbl = shader_vtbl;
6194 IDirect3DVertexShader9_Release(shader);
6195 refcount = IDirect3DDevice9_Release(device);
6196 ok(!refcount, "Device has %u references left.\n", refcount);
6197 IDirect3D9_Release(d3d);
6198 DestroyWindow(window);
6201 static void test_vertex_shader_constant(void)
6203 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};
6204 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6205 IDirect3DDevice9 *device;
6206 struct device_desc desc;
6207 DWORD consts_swvp;
6208 IDirect3D9 *d3d;
6209 ULONG refcount;
6210 D3DCAPS9 caps;
6211 DWORD consts;
6212 HWND window;
6213 HRESULT hr;
6215 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6216 0, 0, 640, 480, 0, 0, 0, 0);
6217 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6218 ok(!!d3d, "Failed to create a D3D object.\n");
6219 if (!(device = create_device(d3d, window, NULL)))
6221 skip("Failed to create a D3D device, skipping tests.\n");
6222 IDirect3D9_Release(d3d);
6223 DestroyWindow(window);
6224 return;
6227 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6228 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6229 if (!(caps.VertexShaderVersion & 0xffff))
6231 skip("No vertex shader support, skipping tests.\n");
6232 IDirect3DDevice9_Release(device);
6233 IDirect3D9_Release(d3d);
6234 DestroyWindow(window);
6235 return;
6237 consts = caps.MaxVertexShaderConst;
6239 /* A simple check that the stuff works at all. */
6240 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, c, 1);
6241 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6243 /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4
6244 * consts from MAX - 1. */
6245 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, c, 1);
6246 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6247 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6248 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6249 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6250 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6251 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6252 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6254 /* Constant -1. */
6255 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, -1, c, 1);
6256 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6258 refcount = IDirect3DDevice9_Release(device);
6259 ok(!refcount, "Device has %u references left.\n", refcount);
6261 desc.device_window = window;
6262 desc.width = 640;
6263 desc.height = 480;
6264 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6266 if (!(device = create_device(d3d, window, &desc)))
6268 skip("Failed to create a D3D device, skipping tests.\n");
6269 IDirect3D9_Release(d3d);
6270 DestroyWindow(window);
6271 return;
6273 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6274 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6275 consts_swvp = caps.MaxVertexShaderConst;
6276 todo_wine
6277 ok(consts_swvp == 8192, "Unexpected consts_swvp %u.\n", consts_swvp);
6279 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6280 todo_wine
6281 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6282 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 1, c, 1);
6283 todo_wine
6284 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6285 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts - 1, d, 4);
6286 todo_wine
6287 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6288 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6289 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6290 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp, c, 1);
6291 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6293 refcount = IDirect3DDevice9_Release(device);
6294 ok(!refcount, "Device has %u references left.\n", refcount);
6296 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6297 if (!(device = create_device(d3d, window, &desc)))
6299 skip("Failed to create a D3D device, skipping tests.\n");
6300 IDirect3D9_Release(d3d);
6301 DestroyWindow(window);
6302 return;
6304 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6305 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6306 ok(consts == caps.MaxVertexShaderConst, "Unexpected caps.MaxVertexShaderConst %u, consts %u.\n",
6307 caps.MaxVertexShaderConst, consts);
6309 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6310 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6311 todo_wine
6312 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6313 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6314 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6316 IDirect3DDevice9_SetSoftwareVertexProcessing(device, 1);
6318 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts + 0, c, 1);
6319 todo_wine
6320 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6321 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, consts_swvp - 1, c, 1);
6322 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6324 refcount = IDirect3DDevice9_Release(device);
6325 ok(!refcount, "Device has %u references left.\n", refcount);
6327 IDirect3D9_Release(d3d);
6328 DestroyWindow(window);
6331 static void test_get_set_pixel_shader(void)
6333 IDirect3DPixelShader9 *current_shader = NULL;
6334 IDirect3DPixelShader9 *shader = NULL;
6335 const IDirect3DPixelShader9Vtbl *shader_vtbl;
6336 IDirect3DDevice9 *device;
6337 ULONG refcount, i;
6338 IDirect3D9 *d3d;
6339 D3DCAPS9 caps;
6340 HWND window;
6341 HRESULT hr;
6343 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6344 0, 0, 640, 480, 0, 0, 0, 0);
6345 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6346 ok(!!d3d, "Failed to create a D3D object.\n");
6347 if (!(device = create_device(d3d, window, NULL)))
6349 skip("Failed to create a D3D device, skipping tests.\n");
6350 IDirect3D9_Release(d3d);
6351 DestroyWindow(window);
6352 return;
6355 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6356 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6357 if (!(caps.PixelShaderVersion & 0xffff))
6359 skip("No pixel shader support, skipping tests.\n");
6360 IDirect3DDevice9_Release(device);
6361 IDirect3D9_Release(d3d);
6362 DestroyWindow(window);
6363 return;
6366 hr = IDirect3DDevice9_CreatePixelShader(device, simple_ps, &shader);
6367 ok(SUCCEEDED(hr), "Failed to create shader, hr %#x.\n", hr);
6368 ok(!!shader, "Got unexpected shader %p.\n", shader);
6370 /* SetPixelShader() should not touch the shader's refcount. */
6371 i = get_refcount((IUnknown *)shader);
6372 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6373 refcount = get_refcount((IUnknown *)shader);
6374 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6375 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6377 /* GetPixelShader() should increase the shader's refcount by one. */
6378 i = refcount + 1;
6379 hr = IDirect3DDevice9_GetPixelShader(device, &current_shader);
6380 refcount = get_refcount((IUnknown *)shader);
6381 ok(SUCCEEDED(hr), "Failed to get pixel shader, hr %#x.\n", hr);
6382 ok(refcount == i, "Got unexpected refcount %u, expected %u.\n", refcount, i);
6383 ok(current_shader == shader, "Got unexpected shader %p, expected %p.\n", current_shader, shader);
6384 IDirect3DPixelShader9_Release(current_shader);
6386 /* SetPixelShader() with a bogus shader vtbl */
6387 shader_vtbl = shader->lpVtbl;
6388 shader->lpVtbl = (IDirect3DPixelShader9Vtbl *)0xdeadbeef;
6389 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6390 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6391 shader->lpVtbl = NULL;
6392 hr = IDirect3DDevice9_SetPixelShader(device, shader);
6393 ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
6394 shader->lpVtbl = shader_vtbl;
6396 IDirect3DPixelShader9_Release(shader);
6397 refcount = IDirect3DDevice9_Release(device);
6398 ok(!refcount, "Device has %u references left.\n", refcount);
6399 IDirect3D9_Release(d3d);
6400 DestroyWindow(window);
6403 static void test_pixel_shader_constant(void)
6405 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};
6406 static const float c[4] = {0.0, 0.0, 0.0, 0.0};
6407 IDirect3DDevice9 *device;
6408 DWORD consts = 0;
6409 IDirect3D9 *d3d;
6410 ULONG refcount;
6411 D3DCAPS9 caps;
6412 HWND window;
6413 HRESULT hr;
6415 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6416 0, 0, 640, 480, 0, 0, 0, 0);
6417 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6418 ok(!!d3d, "Failed to create a D3D object.\n");
6419 if (!(device = create_device(d3d, window, NULL)))
6421 skip("Failed to create a D3D device, skipping tests.\n");
6422 IDirect3D9_Release(d3d);
6423 DestroyWindow(window);
6424 return;
6427 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6428 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6429 if (!(caps.PixelShaderVersion & 0xffff))
6431 skip("No pixel shader support, skipping tests.\n");
6432 IDirect3DDevice9_Release(device);
6433 IDirect3D9_Release(d3d);
6434 DestroyWindow(window);
6435 return;
6438 /* A simple check that the stuff works at all. */
6439 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, c, 1);
6440 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6442 /* Is there really no max pixel shader constant value??? Test how far I can go. */
6443 while (SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device, consts++, c, 1)));
6444 consts = consts - 1;
6445 trace("SetPixelShaderConstantF was able to set %u shader constants.\n", consts);
6447 /* Test corner cases: Write 4 consts from MAX - 1, everything else is
6448 * pointless given the way the constant limit was determined. */
6449 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, consts - 1, d, 4);
6450 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6452 /* Constant -1. */
6453 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, -1, c, 1);
6454 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6456 refcount = IDirect3DDevice9_Release(device);
6457 ok(!refcount, "Device has %u references left.\n", refcount);
6458 IDirect3D9_Release(d3d);
6459 DestroyWindow(window);
6462 static void test_unsupported_shaders(void)
6464 static const DWORD vs_3_0[] =
6466 0xfffe0300, /* vs_3_0 */
6467 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
6468 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
6469 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
6470 0x0000ffff, /* end */
6473 #if 0
6474 float4 main(const float4 color : COLOR) : SV_TARGET
6476 float4 o;
6478 o = color;
6480 return o;
6482 #endif
6483 static const DWORD ps_4_0[] =
6485 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
6486 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
6487 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
6488 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
6489 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
6490 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
6491 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
6492 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
6493 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
6494 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
6495 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
6496 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6497 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
6498 0x00000000, 0x00000000, 0x00000000,
6500 #if 0
6501 vs_1_1
6502 dcl_position v0
6503 def c255, 1.0, 1.0, 1.0, 1.0
6504 add r0, v0, c255
6505 mov oPos, r0
6506 #endif
6507 static const DWORD vs_1_255[] =
6509 0xfffe0101,
6510 0x0000001f, 0x80000000, 0x900f0000,
6511 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6512 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
6513 0x00000001, 0xc00f0000, 0x80e40000,
6514 0x0000ffff
6516 #if 0
6517 vs_1_1
6518 dcl_position v0
6519 def c256, 1.0, 1.0, 1.0, 1.0
6520 add r0, v0, c256
6521 mov oPos, r0
6522 #endif
6523 static const DWORD vs_1_256[] =
6525 0xfffe0101,
6526 0x0000001f, 0x80000000, 0x900f0000,
6527 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6528 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6529 0x00000001, 0xc00f0000, 0x80e40000,
6530 0x0000ffff
6532 #if 0
6533 vs_3_0
6534 dcl_position v0
6535 dcl_position o0
6536 def c256, 1.0, 1.0, 1.0, 1.0
6537 add r0, v0, c256
6538 mov o0, r0
6539 #endif
6540 static const DWORD vs_3_256[] =
6542 0xfffe0300,
6543 0x0200001f, 0x80000000, 0x900f0000,
6544 0x0200001f, 0x80000000, 0xe00f0000,
6545 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6546 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
6547 0x02000001, 0xe00f0000, 0x80e40000,
6548 0x0000ffff
6550 #if 0
6551 /* This shader source generates syntax errors with the native shader assembler
6552 * due to the constant register index values.
6553 * The bytecode was modified by hand to use the intended values. */
6554 vs_3_0
6555 dcl_position v0
6556 dcl_position o0
6557 defi i16, 1, 1, 1, 1
6558 rep i16
6559 add r0, r0, v0
6560 endrep
6561 mov o0, r0
6562 #endif
6563 static const DWORD vs_3_i16[] =
6565 0xfffe0300,
6566 0x0200001f, 0x80000000, 0x900f0000,
6567 0x0200001f, 0x80000000, 0xe00f0000,
6568 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6569 0x01000026, 0xf0e40010,
6570 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6571 0x00000027,
6572 0x02000001, 0xe00f0000, 0x80e40000,
6573 0x0000ffff
6575 #if 0
6576 /* This shader source generates syntax errors with the native shader assembler
6577 * due to the constant register index values.
6578 * The bytecode was modified by hand to use the intended values. */
6579 vs_3_0
6580 dcl_position v0
6581 dcl_position o0
6582 defb b16, true
6583 mov r0, v0
6584 if b16
6585 add r0, r0, v0
6586 endif
6587 mov o0, r0
6588 #endif
6589 static const DWORD vs_3_b16[] =
6591 0xfffe0300,
6592 0x0200001f, 0x80000000, 0x900f0000,
6593 0x0200001f, 0x80000000, 0xe00f0000,
6594 0x0200002f, 0xe00f0810, 0x00000001,
6595 0x02000001, 0x800f0000, 0x90e40000,
6596 0x01000028, 0xe0e40810,
6597 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6598 0x0000002b,
6599 0x02000001, 0xe00f0000, 0x80e40000,
6600 0x0000ffff
6602 #if 0
6603 /* This shader source generates syntax errors with the native shader assembler
6604 * due to the constant register index values.
6605 * The bytecode was modified by hand to use the intended values. */
6606 ps_1_1
6607 def c8, 1.0, 1.0, 1.0, 1.0
6608 add r0, v0, c8
6609 #endif
6610 static const DWORD ps_1_8[] =
6612 0xffff0101,
6613 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6614 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
6615 0x0000ffff
6617 #if 0
6618 /* This shader source generates syntax errors with the native shader assembler
6619 * due to the constant register index values.
6620 * The bytecode was modified by hand to use the intended values. */
6621 ps_2_0
6622 def c32, 1.0, 1.0, 1.0, 1.0
6623 add oC0, v0, c32
6624 #endif
6625 static const DWORD ps_2_32[] =
6627 0xffff0200,
6628 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6629 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
6630 0x0000ffff
6632 #if 0
6633 /* This shader source generates syntax errors with the native shader assembler
6634 * due to the constant register index values.
6635 * The bytecode was modified by hand to use the intended values. */
6636 ps_3_0
6637 dcl_color0 v0
6638 def c224, 1.0, 1.0, 1.0, 1.0
6639 add oC0, v0, c224
6640 #endif
6641 static const DWORD ps_3_224[] =
6643 0xffff0300,
6644 0x0200001f, 0x8000000a, 0x900f0000,
6645 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
6646 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
6647 0x0000ffff
6649 #if 0
6650 /* This shader source generates syntax errors with the native shader assembler
6651 * due to the constant register index values.
6652 * The bytecode was modified by hand to use the intended values. */
6653 ps_2_0
6654 defb b0, true
6655 defi i0, 1, 1, 1, 1
6656 rep i0
6657 if b0
6658 add r0, r0, v0
6659 endif
6660 endrep
6661 mov oC0, r0
6662 #endif
6663 static const DWORD ps_2_0_boolint[] =
6665 0xffff0200,
6666 0x0200002f, 0xe00f0800, 0x00000001,
6667 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
6668 0x01000026, 0xf0e40000,
6669 0x01000028, 0xe0e40800,
6670 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
6671 0x0000002b,
6672 0x00000027,
6673 0x02000001, 0x800f0800, 0x80e40000,
6674 0x0000ffff
6677 IDirect3DVertexShader9 *vs = NULL;
6678 IDirect3DPixelShader9 *ps = NULL;
6679 IDirect3DDevice9 *device;
6680 struct device_desc desc;
6681 IDirect3D9 * d3d;
6682 ULONG refcount;
6683 D3DCAPS9 caps;
6684 HWND window;
6685 HRESULT hr;
6687 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6688 0, 0, 640, 480, 0, 0, 0, 0);
6689 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6690 ok(!!d3d, "Failed to create a D3D object.\n");
6691 if (!(device = create_device(d3d, window, NULL)))
6693 skip("Failed to create a D3D device, skipping tests.\n");
6694 IDirect3D9_Release(d3d);
6695 DestroyWindow(window);
6696 return;
6699 /* These should always fail, regardless of supported shader version. */
6700 hr = IDirect3DDevice9_CreateVertexShader(device, simple_ps, &vs);
6701 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6702 hr = IDirect3DDevice9_CreatePixelShader(device, simple_vs, &ps);
6703 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6704 hr = IDirect3DDevice9_CreatePixelShader(device, ps_4_0, &ps);
6705 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6707 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6708 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6709 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
6711 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_0, &vs);
6712 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6713 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
6715 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6716 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6718 else
6720 skip("GPU supports SM2+, skipping SM1 test.\n");
6723 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6725 else
6727 skip("This GPU supports SM3, skipping unsupported shader test.\n");
6729 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_255, &vs);
6730 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6731 IDirect3DVertexShader9_Release(vs);
6732 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6733 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6734 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6735 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6736 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_i16, &vs);
6737 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6738 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_b16, &vs);
6739 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6742 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
6744 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
6745 goto cleanup;
6747 hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_8, &ps);
6748 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6749 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_32, &ps);
6750 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6751 hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_224, &ps);
6752 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6753 hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_0_boolint, &ps);
6754 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6755 if (ps)
6756 IDirect3DPixelShader9_Release(ps);
6758 refcount = IDirect3DDevice9_Release(device);
6759 ok(!refcount, "Device has %u references left.\n", refcount);
6761 desc.device_window = window;
6762 desc.width = 640;
6763 desc.height = 480;
6764 desc.flags = CREATE_DEVICE_SWVP_ONLY;
6766 if (!(device = create_device(d3d, window, &desc)))
6768 skip("Failed to create a D3D device, skipping tests.\n");
6769 IDirect3D9_Release(d3d);
6770 DestroyWindow(window);
6771 return;
6774 vs = NULL;
6775 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6776 todo_wine
6777 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6778 if (vs)
6779 IDirect3DVertexShader9_Release(vs);
6780 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6781 todo_wine
6782 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6783 if (vs)
6784 IDirect3DVertexShader9_Release(vs);
6786 refcount = IDirect3DDevice9_Release(device);
6787 ok(!refcount, "Device has %u references left.\n", refcount);
6789 desc.flags = CREATE_DEVICE_MIXED_ONLY;
6790 if (!(device = create_device(d3d, window, &desc)))
6792 skip("Failed to create a D3D device, skipping tests.\n");
6793 IDirect3D9_Release(d3d);
6794 DestroyWindow(window);
6795 return;
6797 hr = IDirect3DDevice9_SetSoftwareVertexProcessing(device, 0);
6798 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6800 hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_256, &vs);
6801 todo_wine
6802 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6803 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6804 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6805 if (vs)
6806 IDirect3DVertexShader9_Release(vs);
6808 hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_256, &vs);
6809 todo_wine
6810 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6811 hr = IDirect3DDevice9_SetVertexShader(device, vs);
6812 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6813 if (vs)
6814 IDirect3DVertexShader9_Release(vs);
6816 cleanup:
6817 refcount = IDirect3DDevice9_Release(device);
6818 ok(!refcount, "Device has %u references left.\n", refcount);
6819 IDirect3D9_Release(d3d);
6820 DestroyWindow(window);
6823 /* Test the default texture stage state values */
6824 static void test_texture_stage_states(void)
6826 IDirect3DDevice9 *device;
6827 IDirect3D9 *d3d;
6828 unsigned int i;
6829 ULONG refcount;
6830 D3DCAPS9 caps;
6831 DWORD value;
6832 HWND window;
6833 HRESULT hr;
6835 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6836 0, 0, 640, 480, 0, 0, 0, 0);
6837 d3d = Direct3DCreate9(D3D_SDK_VERSION);
6838 ok(!!d3d, "Failed to create a D3D object.\n");
6839 if (!(device = create_device(d3d, window, NULL)))
6841 skip("Failed to create a D3D device, skipping tests.\n");
6842 IDirect3D9_Release(d3d);
6843 DestroyWindow(window);
6844 return;
6847 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6848 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6850 for (i = 0; i < caps.MaxTextureBlendStages; ++i)
6852 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLOROP, &value);
6853 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6854 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_MODULATE),
6855 "Got unexpected value %#x for D3DTSS_COLOROP, stage %u.\n", value, i);
6856 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG1, &value);
6857 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6858 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_COLORARG1, stage %u.\n", value, i);
6859 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG2, &value);
6860 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6861 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG2, stage %u.\n", value, i);
6862 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAOP, &value);
6863 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6864 ok(value == (i ? D3DTOP_DISABLE : D3DTOP_SELECTARG1),
6865 "Got unexpected value %#x for D3DTSS_ALPHAOP, stage %u.\n", value, i);
6866 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG1, &value);
6867 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6868 ok(value == D3DTA_TEXTURE, "Got unexpected value %#x for D3DTSS_ALPHAARG1, stage %u.\n", value, i);
6869 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG2, &value);
6870 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6871 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG2, stage %u.\n", value, i);
6872 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT00, &value);
6873 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6874 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT00, stage %u.\n", value, i);
6875 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT01, &value);
6876 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6877 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT01, stage %u.\n", value, i);
6878 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT10, &value);
6879 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6880 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT10, stage %u.\n", value, i);
6881 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVMAT11, &value);
6882 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6883 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVMAT11, stage %u.\n", value, i);
6884 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXCOORDINDEX, &value);
6885 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6886 ok(value == i, "Got unexpected value %#x for D3DTSS_TEXCOORDINDEX, stage %u.\n", value, i);
6887 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLSCALE, &value);
6888 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6889 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLSCALE, stage %u.\n", value, i);
6890 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_BUMPENVLOFFSET, &value);
6891 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6892 ok(!value, "Got unexpected value %#x for D3DTSS_BUMPENVLOFFSET, stage %u.\n", value, i);
6893 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &value);
6894 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6895 ok(value == D3DTTFF_DISABLE,
6896 "Got unexpected value %#x for D3DTSS_TEXTURETRANSFORMFLAGS, stage %u.\n", value, i);
6897 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_COLORARG0, &value);
6898 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6899 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_COLORARG0, stage %u.\n", value, i);
6900 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_ALPHAARG0, &value);
6901 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6902 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_ALPHAARG0, stage %u.\n", value, i);
6903 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_RESULTARG, &value);
6904 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6905 ok(value == D3DTA_CURRENT, "Got unexpected value %#x for D3DTSS_RESULTARG, stage %u.\n", value, i);
6906 hr = IDirect3DDevice9_GetTextureStageState(device, i, D3DTSS_CONSTANT, &value);
6907 ok(SUCCEEDED(hr), "Failed to get texture stage state, hr %#x.\n", hr);
6908 ok(!value, "Got unexpected value %#x for D3DTSS_CONSTANT, stage %u.\n", value, i);
6911 refcount = IDirect3DDevice9_Release(device);
6912 ok(!refcount, "Device has %u references left.\n", refcount);
6913 IDirect3D9_Release(d3d);
6914 DestroyWindow(window);
6917 static void test_cube_texture_mipmap_gen(IDirect3DDevice9 *device)
6919 IDirect3DCubeTexture9 *texture;
6920 IDirect3D9 *d3d;
6921 HRESULT hr;
6923 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
6924 ok(SUCCEEDED(hr), "Failed to get D3D, hr %#x.\n", hr);
6925 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6926 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_CUBETEXTURE, D3DFMT_X8R8G8B8);
6927 IDirect3D9_Release(d3d);
6928 if (hr != D3D_OK)
6930 skip("No cube mipmap generation support, skipping tests.\n");
6931 return;
6934 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
6935 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
6936 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6937 IDirect3DCubeTexture9_Release(texture);
6939 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
6940 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
6941 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6942 IDirect3DCubeTexture9_Release(texture);
6945 static void test_cube_texture_levels(IDirect3DDevice9 *device)
6947 IDirect3DCubeTexture9 *texture;
6948 IDirect3DSurface9 *surface;
6949 D3DSURFACE_DESC desc;
6950 DWORD levels;
6951 HRESULT hr;
6952 D3DCAPS9 caps;
6954 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6955 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
6956 if (FAILED(IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
6957 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL)))
6959 skip("Failed to create cube texture, skipping tests.\n");
6960 return;
6963 levels = IDirect3DCubeTexture9_GetLevelCount(texture);
6964 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP)
6965 ok(levels == 7, "Got unexpected levels %u.\n", levels);
6966 else
6967 ok(levels == 1, "Got unexpected levels %u.\n", levels);
6969 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels - 1, &desc);
6970 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6971 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels, &desc);
6972 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6973 hr = IDirect3DCubeTexture9_GetLevelDesc(texture, levels + 1, &desc);
6974 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6976 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
6977 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
6978 IDirect3DSurface9_Release(surface);
6979 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_NEGATIVE_Z + 1, 0, &surface);
6980 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6981 hr = IDirect3DCubeTexture9_GetCubeMapSurface(texture, D3DCUBEMAP_FACE_POSITIVE_X - 1, 0, &surface);
6982 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
6984 IDirect3DCubeTexture9_Release(texture);
6987 static void test_cube_textures(void)
6989 IDirect3DCubeTexture9 *texture;
6990 IDirect3DDevice9 *device;
6991 IDirect3D9 *d3d;
6992 ULONG refcount;
6993 D3DCAPS9 caps;
6994 HWND window;
6995 HRESULT hr;
6997 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
6998 0, 0, 640, 480, 0, 0, 0, 0);
6999 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7000 ok(!!d3d, "Failed to create a D3D object.\n");
7001 if (!(device = create_device(d3d, window, NULL)))
7003 skip("Failed to create a D3D device, skipping tests.\n");
7004 IDirect3D9_Release(d3d);
7005 DestroyWindow(window);
7006 return;
7009 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7010 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
7012 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
7014 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7015 ok(hr == D3D_OK, "Failed to create D3DPOOL_DEFAULT cube texture, hr %#x.\n", hr);
7016 IDirect3DCubeTexture9_Release(texture);
7017 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7018 ok(hr == D3D_OK, "Failed to create D3DPOOL_MANAGED cube texture, hr %#x.\n", hr);
7019 IDirect3DCubeTexture9_Release(texture);
7020 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7021 ok(hr == D3D_OK, "Failed to create D3DPOOL_SYSTEMMEM cube texture, hr %#x.\n", hr);
7022 IDirect3DCubeTexture9_Release(texture);
7024 else
7026 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7027 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_DEFAULT cube texture.\n", hr);
7028 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7029 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_MANAGED cube texture.\n", hr);
7030 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &texture, NULL);
7031 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for D3DPOOL_SYSTEMMEM cube texture.\n", hr);
7033 hr = IDirect3DDevice9_CreateCubeTexture(device, 512, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
7034 ok(hr == D3D_OK, "Failed to create D3DPOOL_SCRATCH cube texture, hr %#x.\n", hr);
7035 IDirect3DCubeTexture9_Release(texture);
7037 test_cube_texture_mipmap_gen(device);
7038 test_cube_texture_levels(device);
7040 refcount = IDirect3DDevice9_Release(device);
7041 ok(!refcount, "Device has %u references left.\n", refcount);
7042 IDirect3D9_Release(d3d);
7043 DestroyWindow(window);
7046 static void test_mipmap_gen(void)
7048 static const D3DFORMAT formats[] =
7050 D3DFMT_A8R8G8B8,
7051 D3DFMT_X8R8G8B8,
7052 D3DFMT_A1R5G5B5,
7053 D3DFMT_A4R4G4B4,
7054 D3DFMT_A8,
7055 D3DFMT_L8,
7056 D3DFMT_A8L8,
7057 D3DFMT_V8U8,
7058 D3DFMT_DXT5,
7060 D3DTEXTUREFILTERTYPE filter_type;
7061 IDirect3DTexture9 *texture;
7062 IDirect3DSurface9 *surface;
7063 IDirect3DDevice9 *device;
7064 D3DSURFACE_DESC desc;
7065 D3DLOCKED_RECT lr;
7066 IDirect3D9 *d3d;
7067 BOOL renderable;
7068 ULONG refcount;
7069 unsigned int i;
7070 DWORD levels;
7071 HWND window;
7072 HRESULT hr;
7074 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7075 ok(!!d3d, "Failed to create a D3D object.\n");
7077 for (i = 0; i < ARRAY_SIZE(formats); ++i)
7079 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7080 0, D3DRTYPE_TEXTURE, formats[i]);
7081 if (FAILED(hr))
7083 skip("Skipping unsupported format %#x.\n", formats[i]);
7084 continue;
7086 renderable = SUCCEEDED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7087 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, formats[i]));
7088 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7089 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, formats[i]);
7090 ok((hr == D3D_OK && renderable) || hr == D3DOK_NOAUTOGEN,
7091 "Got unexpected hr %#x for %srenderable format %#x.\n",
7092 hr, renderable ? "" : "non", formats[i]);
7095 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7096 D3DUSAGE_AUTOGENMIPMAP, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK)
7098 skip("No mipmap generation support, skipping tests.\n");
7099 IDirect3D9_Release(d3d);
7100 return;
7103 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7104 0, 0, 640, 480, 0, 0, 0, 0);
7105 if (!(device = create_device(d3d, window, NULL)))
7107 skip("Failed to create a D3D device, skipping tests.\n");
7108 IDirect3D9_Release(d3d);
7109 DestroyWindow(window);
7110 return;
7113 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, (D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP),
7114 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7115 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7116 IDirect3DTexture9_Release(texture);
7118 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, D3DUSAGE_AUTOGENMIPMAP,
7119 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7120 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7122 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7123 ok(filter_type == D3DTEXF_LINEAR /* || broken(filter_type == D3DTEXF_POINT)*/,
7124 "Got unexpected filter_type %#x.\n", filter_type);
7125 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_NONE);
7126 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7127 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_ANISOTROPIC);
7128 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7129 filter_type = IDirect3DTexture9_GetAutoGenFilterType(texture);
7130 ok(filter_type == D3DTEXF_ANISOTROPIC, "Got unexpected filter_type %#x.\n", filter_type);
7131 hr = IDirect3DTexture9_SetAutoGenFilterType(texture, D3DTEXF_LINEAR);
7132 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7134 levels = IDirect3DTexture9_GetLevelCount(texture);
7135 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7137 for (i = 0; i < 6 /* 64 = 2 ^ 6 */; ++i)
7139 surface = NULL;
7140 hr = IDirect3DTexture9_GetSurfaceLevel(texture, i, &surface);
7141 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7142 if (surface)
7143 IDirect3DSurface9_Release(surface);
7145 hr = IDirect3DTexture9_GetLevelDesc(texture, i, &desc);
7146 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7148 hr = IDirect3DTexture9_LockRect(texture, i, &lr, NULL, 0);
7149 ok(hr == (i ? D3DERR_INVALIDCALL : D3D_OK), "Got unexpected hr %#x for level %u.\n", hr, i);
7150 if (SUCCEEDED(hr))
7152 hr = IDirect3DTexture9_UnlockRect(texture, i);
7153 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7156 IDirect3DTexture9_Release(texture);
7158 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 2, D3DUSAGE_AUTOGENMIPMAP,
7159 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7160 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7161 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 6, D3DUSAGE_AUTOGENMIPMAP,
7162 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7163 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7165 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_AUTOGENMIPMAP,
7166 D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
7167 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7168 levels = IDirect3DTexture9_GetLevelCount(texture);
7169 ok(levels == 1, "Got unexpected levels %u.\n", levels);
7170 IDirect3DTexture9_Release(texture);
7172 refcount = IDirect3DDevice9_Release(device);
7173 ok(!refcount, "Device has %u references left.\n", refcount);
7174 IDirect3D9_Release(d3d);
7175 DestroyWindow(window);
7178 static void test_filter(void)
7180 static const struct
7182 DWORD magfilter, minfilter, mipfilter;
7183 BOOL has_texture;
7184 HRESULT result;
7186 tests[] =
7188 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7189 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7190 {D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7191 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, FALSE, D3D_OK },
7192 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, FALSE, D3D_OK },
7194 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7195 {D3DTEXF_POINT, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7196 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, D3D_OK },
7197 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_POINT, TRUE, D3D_OK },
7199 {D3DTEXF_NONE, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7200 {D3DTEXF_LINEAR, D3DTEXF_NONE, D3DTEXF_NONE, TRUE, D3DERR_UNSUPPORTEDTEXTUREFILTER},
7201 {D3DTEXF_LINEAR, D3DTEXF_POINT, D3DTEXF_NONE, TRUE, E_FAIL },
7202 {D3DTEXF_POINT, D3DTEXF_LINEAR, D3DTEXF_NONE, TRUE, E_FAIL },
7203 {D3DTEXF_POINT, D3DTEXF_POINT, D3DTEXF_LINEAR, TRUE, E_FAIL },
7205 IDirect3DTexture9 *texture;
7206 IDirect3DDevice9 *device;
7207 IDirect3D9 *d3d;
7208 unsigned int i;
7209 ULONG refcount;
7210 DWORD passes;
7211 HWND window;
7212 HRESULT hr;
7214 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7215 ok(!!d3d, "Failed to create a D3D object.\n");
7217 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7218 0, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7220 skip("D3DFMT_A32B32G32R32F not supported, skipping tests.\n");
7221 IDirect3D9_Release(d3d);
7222 return;
7225 if (SUCCEEDED(hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7226 D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)))
7228 skip("D3DFMT_A32B32G32R32F supports filtering, skipping tests.\n");
7229 IDirect3D9_Release(d3d);
7230 return;
7233 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7234 0, 0, 640, 480, 0, 0, 0, 0);
7235 if (!(device = create_device(d3d, window, NULL)))
7237 skip("Failed to create a D3D device, skipping tests.\n");
7238 IDirect3D9_Release(d3d);
7239 DestroyWindow(window);
7240 return;
7243 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, 0,
7244 D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &texture, NULL);
7245 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7247 /* Needed for ValidateDevice(). */
7248 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7249 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
7251 for (i = 0; i < ARRAY_SIZE(tests); ++i)
7253 if (tests[i].has_texture)
7255 hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
7256 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7258 else
7260 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7261 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7264 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, tests[i].magfilter);
7265 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7266 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, tests[i].minfilter);
7267 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7268 hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, tests[i].mipfilter);
7269 ok(SUCCEEDED(hr), "Failed to set sampler state, hr %#x.\n", hr);
7271 passes = 0xdeadbeef;
7272 hr = IDirect3DDevice9_ValidateDevice(device, &passes);
7273 ok(hr == tests[i].result,
7274 "Got unexpected hr %#x, expected %#x (mag %#x, min %#x, mip %#x, has_texture %#x).\n",
7275 hr, tests[i].result, tests[i].magfilter, tests[i].minfilter,
7276 tests[i].mipfilter, tests[i].has_texture);
7277 if (SUCCEEDED(hr))
7278 ok(!!passes, "Got unexpected passes %#x.\n", passes);
7279 else
7280 ok(passes == 0xdeadbeef, "Got unexpected passes %#x.\n", passes);
7283 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7284 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7285 IDirect3DTexture9_Release(texture);
7287 refcount = IDirect3DDevice9_Release(device);
7288 ok(!refcount, "Device has %u references left.\n", refcount);
7289 IDirect3D9_Release(d3d);
7290 DestroyWindow(window);
7293 static void test_get_set_texture(void)
7295 const IDirect3DBaseTexture9Vtbl *texture_vtbl;
7296 IDirect3DBaseTexture9 *texture;
7297 IDirect3DDevice9 *device;
7298 IDirect3D9 *d3d;
7299 ULONG refcount;
7300 HWND window;
7301 HRESULT hr;
7303 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7304 0, 0, 640, 480, 0, 0, 0, 0);
7305 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7306 ok(!!d3d, "Failed to create a D3D object.\n");
7307 if (!(device = create_device(d3d, window, NULL)))
7309 skip("Failed to create a D3D device, skipping tests.\n");
7310 IDirect3D9_Release(d3d);
7311 DestroyWindow(window);
7312 return;
7315 texture = (IDirect3DBaseTexture9 *)0xdeadbeef;
7316 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7317 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7318 hr = IDirect3DDevice9_GetTexture(device, 0, &texture);
7319 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7320 ok(!texture, "Got unexpected texture %p.\n", texture);
7322 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0, D3DFMT_A8R8G8B8,
7323 D3DPOOL_MANAGED, (IDirect3DTexture9 **)&texture, NULL);
7324 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7325 texture_vtbl = texture->lpVtbl;
7326 texture->lpVtbl = (IDirect3DBaseTexture9Vtbl *)0xdeadbeef;
7327 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7328 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7329 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7330 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7331 texture->lpVtbl = NULL;
7332 hr = IDirect3DDevice9_SetTexture(device, 0, texture);
7333 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7334 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7335 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
7336 texture->lpVtbl = texture_vtbl;
7337 IDirect3DBaseTexture9_Release(texture);
7339 refcount = IDirect3DDevice9_Release(device);
7340 ok(!refcount, "Device has %u references left.\n", refcount);
7341 IDirect3D9_Release(d3d);
7342 DestroyWindow(window);
7345 static void test_lod(void)
7347 IDirect3DTexture9 *texture;
7348 IDirect3DDevice9 *device;
7349 IDirect3D9 *d3d;
7350 ULONG refcount;
7351 HWND window;
7352 HRESULT hr;
7353 DWORD ret;
7355 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7356 0, 0, 640, 480, 0, 0, 0, 0);
7357 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7358 ok(!!d3d, "Failed to create a D3D object.\n");
7359 if (!(device = create_device(d3d, window, NULL)))
7361 skip("Failed to create a D3D device, skipping tests.\n");
7362 IDirect3D9_Release(d3d);
7363 DestroyWindow(window);
7364 return;
7367 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0,
7368 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7369 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7371 /* SetLOD() is only supported on D3DPOOL_MANAGED textures, but doesn't
7372 * return a HRESULT, so it can't return a normal error. Instead, the call
7373 * is simply ignored. */
7374 ret = IDirect3DTexture9_SetLOD(texture, 0);
7375 ok(!ret, "Got unexpected ret %u.\n", ret);
7376 ret = IDirect3DTexture9_SetLOD(texture, 1);
7377 ok(!ret, "Got unexpected ret %u.\n", ret);
7378 ret = IDirect3DTexture9_SetLOD(texture, 2);
7379 ok(!ret, "Got unexpected ret %u.\n", ret);
7380 ret = IDirect3DTexture9_GetLOD(texture);
7381 ok(!ret, "Got unexpected ret %u.\n", ret);
7383 IDirect3DTexture9_Release(texture);
7384 refcount = IDirect3DDevice9_Release(device);
7385 ok(!refcount, "Device has %u references left.\n", refcount);
7386 IDirect3D9_Release(d3d);
7387 DestroyWindow(window);
7390 static void test_surface_get_container(void)
7392 IDirect3DTexture9 *texture = NULL;
7393 IDirect3DSurface9 *surface = NULL;
7394 IDirect3DDevice9 *device;
7395 IUnknown *container;
7396 IDirect3D9 *d3d;
7397 ULONG refcount;
7398 HWND window;
7399 HRESULT hr;
7401 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7402 0, 0, 640, 480, 0, 0, 0, 0);
7403 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7404 ok(!!d3d, "Failed to create a D3D object.\n");
7405 if (!(device = create_device(d3d, window, NULL)))
7407 skip("Failed to create a D3D device, skipping tests.\n");
7408 IDirect3D9_Release(d3d);
7409 DestroyWindow(window);
7410 return;
7413 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0,
7414 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7415 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
7416 ok(!!texture, "Got unexpected texture %p.\n", texture);
7418 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7419 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
7420 ok(!!surface, "Got unexpected surface %p.\n", surface);
7422 /* These should work... */
7423 container = NULL;
7424 hr = IDirect3DSurface9_GetContainer(surface, &IID_IUnknown, (void **)&container);
7425 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7426 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7427 IUnknown_Release(container);
7429 container = NULL;
7430 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DResource9, (void **)&container);
7431 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7432 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7433 IUnknown_Release(container);
7435 container = NULL;
7436 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DBaseTexture9, (void **)&container);
7437 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7438 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7439 IUnknown_Release(container);
7441 container = NULL;
7442 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **)&container);
7443 ok(SUCCEEDED(hr), "Failed to get surface container, hr %#x.\n", hr);
7444 ok(container == (IUnknown *)texture, "Got unexpected container %p, expected %p.\n", container, texture);
7445 IUnknown_Release(container);
7447 /* ...and this one shouldn't. This should return E_NOINTERFACE and set container to NULL. */
7448 hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DSurface9, (void **)&container);
7449 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
7450 ok(!container, "Got unexpected container %p.\n", container);
7452 IDirect3DSurface9_Release(surface);
7453 IDirect3DTexture9_Release(texture);
7454 refcount = IDirect3DDevice9_Release(device);
7455 ok(!refcount, "Device has %u references left.\n", refcount);
7456 IDirect3D9_Release(d3d);
7457 DestroyWindow(window);
7460 static void test_surface_alignment(void)
7462 IDirect3DSurface9 *surface;
7463 IDirect3DDevice9 *device;
7464 D3DLOCKED_RECT lr;
7465 unsigned int i, j;
7466 IDirect3D9 *d3d;
7467 ULONG refcount;
7468 HWND window;
7469 HRESULT hr;
7471 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7472 0, 0, 640, 480, 0, 0, 0, 0);
7473 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7474 ok(!!d3d, "Failed to create a D3D object.\n");
7475 if (!(device = create_device(d3d, window, NULL)))
7477 skip("Failed to create a D3D device, skipping tests.\n");
7478 IDirect3D9_Release(d3d);
7479 DestroyWindow(window);
7480 return;
7483 /* Test a sysmem surface because those aren't affected by the hardware's np2 restrictions. */
7484 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 5, 5,
7485 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
7486 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7488 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
7489 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7490 ok(!(lr.Pitch & 3), "Got misaligned pitch %d.\n", lr.Pitch);
7491 /* Some applications also depend on the exact pitch, rather than just the
7492 * alignment. */
7493 ok(lr.Pitch == 12, "Got unexpected pitch %d.\n", lr.Pitch);
7494 hr = IDirect3DSurface9_UnlockRect(surface);
7495 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7496 IDirect3DSurface9_Release(surface);
7498 for (i = 0; i < 5; ++i)
7500 IDirect3DTexture9 *texture;
7501 unsigned int level_count;
7502 D3DSURFACE_DESC desc;
7503 int expected_pitch;
7505 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0,
7506 MAKEFOURCC('D', 'X', 'T', '1' + i), D3DPOOL_MANAGED, &texture, NULL);
7507 ok(SUCCEEDED(hr) || hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7508 if (FAILED(hr))
7510 skip("DXT%u surfaces are not supported, skipping tests.\n", i + 1);
7511 continue;
7514 level_count = IDirect3DBaseTexture9_GetLevelCount(texture);
7515 for (j = 0; j < level_count; ++j)
7517 IDirect3DTexture9_GetLevelDesc(texture, j, &desc);
7518 hr = IDirect3DTexture9_LockRect(texture, j, &lr, NULL, 0);
7519 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
7520 hr = IDirect3DTexture9_UnlockRect(texture, j);
7521 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
7523 expected_pitch = ((desc.Width + 3) >> 2) << 3;
7524 if (i > 0)
7525 expected_pitch <<= 1;
7526 ok(lr.Pitch == expected_pitch, "Got unexpected pitch %d for DXT%u level %u (%ux%u), expected %d.\n",
7527 lr.Pitch, i + 1, j, desc.Width, desc.Height, expected_pitch);
7529 IDirect3DTexture9_Release(texture);
7532 refcount = IDirect3DDevice9_Release(device);
7533 ok(!refcount, "Device has %u references left.\n", refcount);
7534 IDirect3D9_Release(d3d);
7535 DestroyWindow(window);
7538 /* Since the DXT formats are based on 4x4 blocks, locking works slightly
7539 * different from regular formats. This test verifies we return the correct
7540 * memory offsets. */
7541 static void test_lockrect_offset(void)
7543 static const struct
7545 D3DFORMAT format;
7546 const char *name;
7547 unsigned int block_width;
7548 unsigned int block_height;
7549 unsigned int block_size;
7551 dxt_formats[] =
7553 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 8},
7554 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 16},
7555 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 16},
7556 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 16},
7557 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 16},
7558 {MAKEFOURCC('A','T','I','1'), "ATI1N", 1, 1, 1},
7559 {MAKEFOURCC('A','T','I','2'), "ATI2N", 1, 1, 1},
7561 unsigned int expected_offset, offset, i;
7562 const RECT rect = {60, 60, 68, 68};
7563 IDirect3DSurface9 *surface;
7564 D3DLOCKED_RECT locked_rect;
7565 IDirect3DDevice9 *device;
7566 int expected_pitch;
7567 IDirect3D9 *d3d;
7568 ULONG refcount;
7569 HWND window;
7570 BYTE *base;
7571 HRESULT hr;
7573 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7574 0, 0, 640, 480, 0, 0, 0, 0);
7575 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7576 ok(!!d3d, "Failed to create a D3D object.\n");
7577 if (!(device = create_device(d3d, window, NULL)))
7579 skip("Failed to create a D3D device, skipping tests.\n");
7580 IDirect3D9_Release(d3d);
7581 DestroyWindow(window);
7582 return;
7585 for (i = 0; i < ARRAY_SIZE(dxt_formats); ++i)
7587 if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
7588 0, D3DRTYPE_TEXTURE, dxt_formats[i].format)))
7590 skip("Format %s not supported, skipping lockrect offset tests.\n", dxt_formats[i].name);
7591 continue;
7594 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7595 dxt_formats[i].format, D3DPOOL_SCRATCH, &surface, NULL);
7596 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7598 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7599 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7601 base = locked_rect.pBits;
7602 expected_pitch = (128 + dxt_formats[i].block_height - 1) / dxt_formats[i].block_width
7603 * dxt_formats[i].block_size;
7604 ok(locked_rect.Pitch == expected_pitch, "Got unexpected pitch %d for format %s, expected %d.\n",
7605 locked_rect.Pitch, dxt_formats[i].name, expected_pitch);
7607 hr = IDirect3DSurface9_UnlockRect(surface);
7608 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7610 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
7611 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
7613 offset = (BYTE *)locked_rect.pBits - base;
7614 expected_offset = (rect.top / dxt_formats[i].block_height) * expected_pitch
7615 + (rect.left / dxt_formats[i].block_width) * dxt_formats[i].block_size;
7616 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u.\n",
7617 offset, dxt_formats[i].name, expected_offset);
7619 hr = IDirect3DSurface9_UnlockRect(surface);
7620 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
7622 IDirect3DSurface9_Release(surface);
7625 refcount = IDirect3DDevice9_Release(device);
7626 ok(!refcount, "Device has %u references left.\n", refcount);
7627 IDirect3D9_Release(d3d);
7628 DestroyWindow(window);
7631 static void test_lockrect_invalid(void)
7633 static const struct
7635 RECT rect;
7636 HRESULT win7_result;
7638 test_data[] =
7640 {{60, 60, 68, 68}, D3D_OK}, /* Valid */
7641 {{60, 60, 60, 68}, D3DERR_INVALIDCALL}, /* 0 height */
7642 {{60, 60, 68, 60}, D3DERR_INVALIDCALL}, /* 0 width */
7643 {{68, 60, 60, 68}, D3DERR_INVALIDCALL}, /* left > right */
7644 {{60, 68, 68, 60}, D3DERR_INVALIDCALL}, /* top > bottom */
7645 {{-8, 60, 0, 68}, D3DERR_INVALIDCALL}, /* left < surface */
7646 {{60, -8, 68, 0}, D3DERR_INVALIDCALL}, /* top < surface */
7647 {{-16, 60, -8, 68}, D3DERR_INVALIDCALL}, /* right < surface */
7648 {{60, -16, 68, -8}, D3DERR_INVALIDCALL}, /* bottom < surface */
7649 {{60, 60, 136, 68}, D3DERR_INVALIDCALL}, /* right > surface */
7650 {{60, 60, 68, 136}, D3DERR_INVALIDCALL}, /* bottom > surface */
7651 {{136, 60, 144, 68}, D3DERR_INVALIDCALL}, /* left > surface */
7652 {{60, 136, 68, 144}, D3DERR_INVALIDCALL}, /* top > surface */
7654 static const RECT test_rect_2 = {0, 0, 8, 8};
7655 IDirect3DSurface9 *surface = NULL;
7656 D3DLOCKED_RECT locked_rect;
7657 IDirect3DDevice9 *device;
7658 IDirect3DTexture9 *texture;
7659 IDirect3DCubeTexture9 *cube_texture;
7660 HRESULT hr, expected_hr;
7661 unsigned int i, r;
7662 IDirect3D9 *d3d;
7663 ULONG refcount;
7664 HWND window;
7665 BYTE *base;
7666 static const struct
7668 D3DRESOURCETYPE type;
7669 D3DPOOL pool;
7670 const char *name;
7672 resources[] =
7674 {D3DRTYPE_SURFACE, D3DPOOL_SCRATCH, "scratch surface"},
7675 {D3DRTYPE_TEXTURE, D3DPOOL_MANAGED, "managed texture"},
7676 {D3DRTYPE_TEXTURE, D3DPOOL_SYSTEMMEM, "sysmem texture"},
7677 {D3DRTYPE_TEXTURE, D3DPOOL_SCRATCH, "scratch texture"},
7678 {D3DRTYPE_CUBETEXTURE, D3DPOOL_MANAGED, "default cube texture"},
7679 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SYSTEMMEM, "sysmem cube texture"},
7680 {D3DRTYPE_CUBETEXTURE, D3DPOOL_SCRATCH, "scratch cube texture"},
7683 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7684 0, 0, 640, 480, 0, 0, 0, 0);
7685 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7686 ok(!!d3d, "Failed to create a D3D object.\n");
7687 if (!(device = create_device(d3d, window, NULL)))
7689 skip("Failed to create a D3D device, skipping tests.\n");
7690 IDirect3D9_Release(d3d);
7691 DestroyWindow(window);
7692 return;
7695 for (r = 0; r < ARRAY_SIZE(resources); ++r)
7697 texture = NULL;
7698 cube_texture = NULL;
7699 switch (resources[r].type)
7701 case D3DRTYPE_SURFACE:
7702 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
7703 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7704 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, type %s.\n",
7705 hr, resources[r].name);
7706 break;
7708 case D3DRTYPE_TEXTURE:
7709 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
7710 resources[r].pool, &texture, NULL);
7711 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, type %s.\n",
7712 hr, resources[r].name);
7713 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7714 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7715 hr, resources[r].name);
7716 break;
7718 case D3DRTYPE_CUBETEXTURE:
7719 hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
7720 resources[r].pool, &cube_texture, NULL);
7721 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x, type %s.\n",
7722 hr, resources[r].name);
7723 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
7724 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
7725 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x, type %s.\n",
7726 hr, resources[r].name);
7727 break;
7729 default:
7730 break;
7733 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7734 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x, type %s.\n", hr, resources[r].name);
7735 base = locked_rect.pBits;
7736 hr = IDirect3DSurface9_UnlockRect(surface);
7737 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7738 expected_hr = resources[r].type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
7739 hr = IDirect3DSurface9_UnlockRect(surface);
7740 ok(hr == expected_hr, "Got hr %#x, expected %#x, type %s.\n", hr, expected_hr, resources[r].name);
7742 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
7744 unsigned int offset, expected_offset;
7745 const RECT *rect = &test_data[i].rect;
7747 locked_rect.pBits = (BYTE *)0xdeadbeef;
7748 locked_rect.Pitch = 0xdeadbeef;
7750 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, rect, 0);
7751 /* Windows XP accepts invalid locking rectangles, windows 7 rejects
7752 * them. Some games (C&C3) depend on the XP behavior, mark the Win 7
7753 * one broken. */
7754 ok(SUCCEEDED(hr) || broken(hr == test_data[i].win7_result),
7755 "Failed to lock surface with rect %s, hr %#x, type %s.\n",
7756 wine_dbgstr_rect(rect), hr, resources[r].name);
7757 if (FAILED(hr))
7758 continue;
7760 offset = (BYTE *)locked_rect.pBits - base;
7761 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7762 ok(offset == expected_offset,
7763 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7764 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7766 hr = IDirect3DSurface9_UnlockRect(surface);
7767 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7769 if (texture)
7771 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, rect, 0);
7772 ok(SUCCEEDED(hr),
7773 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7774 wine_dbgstr_rect(rect), hr, resources[r].name);
7775 if (FAILED(hr))
7776 continue;
7778 offset = (BYTE *)locked_rect.pBits - base;
7779 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7780 ok(offset == expected_offset,
7781 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7782 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7784 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7785 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7787 if (cube_texture)
7789 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7790 &locked_rect, rect, 0);
7791 ok(SUCCEEDED(hr),
7792 "Failed to lock texture with rect %s, hr %#x, type %s.\n",
7793 wine_dbgstr_rect(rect), hr, resources[r].name);
7794 if (FAILED(hr))
7795 continue;
7797 offset = (BYTE *)locked_rect.pBits - base;
7798 expected_offset = rect->top * locked_rect.Pitch + rect->left * 4;
7799 ok(offset == expected_offset,
7800 "Got unexpected offset %u (expected %u) for rect %s, type %s.\n",
7801 offset, expected_offset, wine_dbgstr_rect(rect), resources[r].name);
7803 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7804 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7808 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7809 ok(SUCCEEDED(hr), "Failed to lock surface with rect NULL, hr %#x, type %s.\n", hr, resources[r].name);
7810 locked_rect.pBits = (BYTE *)0xdeadbeef;
7811 locked_rect.Pitch = 1;
7812 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7813 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7814 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7815 locked_rect.pBits, resources[r].name);
7816 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7817 locked_rect.Pitch, resources[r].name);
7818 hr = IDirect3DSurface9_UnlockRect(surface);
7819 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7821 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7822 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7823 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7824 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_data[0].rect, 0);
7825 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7826 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7827 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &test_rect_2, 0);
7828 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7829 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7830 hr = IDirect3DSurface9_UnlockRect(surface);
7831 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x, type %s.\n", hr, resources[r].name);
7833 IDirect3DSurface9_Release(surface);
7835 if (texture)
7837 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7838 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7839 hr, resources[r].name);
7840 locked_rect.pBits = (BYTE *)0xdeadbeef;
7841 locked_rect.Pitch = 1;
7842 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
7843 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7844 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7845 locked_rect.pBits, resources[r].name);
7846 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7847 locked_rect.Pitch, resources[r].name);
7848 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7849 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7850 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7851 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7852 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7853 ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7855 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7856 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7857 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7858 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_data[0].rect, 0);
7859 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7860 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7861 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, &test_rect_2, 0);
7862 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7863 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7864 hr = IDirect3DTexture9_UnlockRect(texture, 0);
7865 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7867 IDirect3DTexture9_Release(texture);
7869 if (cube_texture)
7871 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7872 &locked_rect, NULL, 0);
7873 ok(SUCCEEDED(hr), "Failed to lock texture with rect NULL, hr %#x, type %s.\n",
7874 hr, resources[r].name);
7875 locked_rect.pBits = (BYTE *)0xdeadbeef;
7876 locked_rect.Pitch = 1;
7877 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7878 &locked_rect, NULL, 0);
7879 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7880 ok(locked_rect.pBits == (BYTE *)0xdeadbeef, "Got unexpected pBits: %p, type %s.\n",
7881 locked_rect.pBits, resources[r].name);
7882 ok(locked_rect.Pitch == 1, "Got unexpected pitch %d, type %s.\n",
7883 locked_rect.Pitch, resources[r].name);
7884 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
7885 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7886 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7887 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7888 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7889 todo_wine ok(hr == D3D_OK, "Got unexpected hr %#x, type %s.\n", hr, resources[r].name);
7891 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7892 &locked_rect, &test_data[0].rect, 0);
7893 ok(hr == D3D_OK, "Got unexpected hr %#x for rect %s, type %s.\n",
7894 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7895 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7896 &locked_rect, &test_data[0].rect, 0);
7897 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7898 hr, wine_dbgstr_rect(&test_data[0].rect), resources[r].name);
7899 hr = IDirect3DCubeTexture9_LockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0,
7900 &locked_rect, &test_rect_2, 0);
7901 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect %s, type %s.\n",
7902 hr, wine_dbgstr_rect(&test_rect_2), resources[r].name);
7903 hr = IDirect3DCubeTexture9_UnlockRect(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_X, 0);
7904 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x, type %s.\n", hr, resources[r].name);
7906 IDirect3DCubeTexture9_Release(cube_texture);
7910 refcount = IDirect3DDevice9_Release(device);
7911 ok(!refcount, "Device has %u references left.\n", refcount);
7912 IDirect3D9_Release(d3d);
7913 DestroyWindow(window);
7916 static void test_private_data(void)
7918 ULONG refcount, expected_refcount;
7919 IDirect3DTexture9 *texture;
7920 IDirect3DSurface9 *surface, *surface2;
7921 IDirect3DDevice9 *device;
7922 IDirect3D9 *d3d;
7923 IUnknown *ptr;
7924 HWND window;
7925 HRESULT hr;
7926 DWORD size;
7927 DWORD data[4] = {1, 2, 3, 4};
7928 static const GUID d3d9_private_data_test_guid2 =
7930 0x2e5afac2,
7931 0x87b5,
7932 0x4c10,
7933 {0x9b,0x4b,0x89,0xd7,0xd1,0x12,0xe7,0x2b}
7936 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
7937 0, 0, 640, 480, 0, 0, 0, 0);
7938 d3d = Direct3DCreate9(D3D_SDK_VERSION);
7939 ok(!!d3d, "Failed to create a D3D object.\n");
7940 if (!(device = create_device(d3d, window, NULL)))
7942 skip("Failed to create a D3D device, skipping tests.\n");
7943 IDirect3D9_Release(d3d);
7944 DestroyWindow(window);
7945 return;
7948 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4,
7949 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
7950 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
7952 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7953 device, 0, D3DSPD_IUNKNOWN);
7954 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7955 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7956 device, 5, D3DSPD_IUNKNOWN);
7957 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7958 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7959 device, sizeof(IUnknown *) * 2, D3DSPD_IUNKNOWN);
7960 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7962 /* A failing SetPrivateData call does not clear the old data with the same tag. */
7963 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7964 sizeof(device), D3DSPD_IUNKNOWN);
7965 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
7966 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, device,
7967 sizeof(device) * 2, D3DSPD_IUNKNOWN);
7968 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
7969 size = sizeof(ptr);
7970 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
7971 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
7972 IUnknown_Release(ptr);
7973 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7974 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
7976 refcount = get_refcount((IUnknown *)device);
7977 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7978 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7979 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7980 expected_refcount = refcount + 1;
7981 refcount = get_refcount((IUnknown *)device);
7982 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7983 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
7984 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7985 expected_refcount = refcount - 1;
7986 refcount = get_refcount((IUnknown *)device);
7987 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7989 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7990 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7991 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7992 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7993 surface, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
7994 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
7995 refcount = get_refcount((IUnknown *)device);
7996 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
7998 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid,
7999 device, sizeof(IUnknown *), D3DSPD_IUNKNOWN);
8000 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8001 size = 2 * sizeof(ptr);
8002 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8003 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8004 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8005 expected_refcount = refcount + 2;
8006 refcount = get_refcount((IUnknown *)device);
8007 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8008 ok(ptr == (IUnknown *)device, "Got unexpected ptr %p, expected %p.\n", ptr, device);
8009 IUnknown_Release(ptr);
8010 expected_refcount--;
8012 ptr = (IUnknown *)0xdeadbeef;
8013 size = 1;
8014 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8015 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8016 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8017 size = 2 * sizeof(ptr);
8018 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, NULL, &size);
8019 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
8020 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8021 refcount = get_refcount((IUnknown *)device);
8022 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8023 size = 1;
8024 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, &ptr, &size);
8025 ok(hr == D3DERR_MOREDATA, "Got unexpected hr %#x.\n", hr);
8026 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
8027 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8028 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, NULL, NULL);
8029 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8030 size = 0xdeadbabe;
8031 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid2, &ptr, &size);
8032 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8033 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
8034 ok(size == 0xdeadbabe, "Got unexpected size %u.\n", size);
8035 /* GetPrivateData with size = NULL causes an access violation on Windows if the
8036 * requested data exists. */
8038 /* Destroying the surface frees the held reference. */
8039 IDirect3DSurface9_Release(surface);
8040 expected_refcount = refcount - 2;
8041 refcount = get_refcount((IUnknown *)device);
8042 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
8044 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH,
8045 &texture, NULL);
8046 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8047 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8048 ok(SUCCEEDED(hr), "Failed to get texture level 0, hr %#x.\n", hr);
8049 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
8050 ok(SUCCEEDED(hr), "Failed to get texture level 1, hr %#x.\n", hr);
8052 hr = IDirect3DTexture9_SetPrivateData(texture, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8053 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8055 memset(data, 0, sizeof(data));
8056 size = sizeof(data);
8057 hr = IDirect3DSurface9_GetPrivateData(surface, &d3d9_private_data_test_guid, data, &size);
8058 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8059 hr = IDirect3DTexture9_GetPrivateData(texture, &d3d9_private_data_test_guid, data, &size);
8060 ok(SUCCEEDED(hr), "Failed to get private data, hr %#x.\n", hr);
8061 ok(data[0] == 1 && data[1] == 2 && data[2] == 3 && data[3] == 4,
8062 "Got unexpected private data: %u, %u, %u, %u.\n", data[0], data[1], data[2], data[3]);
8064 hr = IDirect3DTexture9_FreePrivateData(texture, &d3d9_private_data_test_guid);
8065 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8067 hr = IDirect3DSurface9_SetPrivateData(surface, &d3d9_private_data_test_guid, data, sizeof(data), 0);
8068 ok(SUCCEEDED(hr), "Failed to set private data, hr %#x.\n", hr);
8069 hr = IDirect3DSurface9_GetPrivateData(surface2, &d3d9_private_data_test_guid, data, &size);
8070 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
8072 hr = IDirect3DSurface9_FreePrivateData(surface, &d3d9_private_data_test_guid);
8073 ok(SUCCEEDED(hr), "Failed to free private data, hr %#x.\n", hr);
8075 IDirect3DSurface9_Release(surface2);
8076 IDirect3DSurface9_Release(surface);
8077 IDirect3DTexture9_Release(texture);
8079 refcount = IDirect3DDevice9_Release(device);
8080 ok(!refcount, "Device has %u references left.\n", refcount);
8081 IDirect3D9_Release(d3d);
8082 DestroyWindow(window);
8085 static void test_getdc(void)
8087 static const struct
8089 const char *name;
8090 D3DFORMAT format;
8091 unsigned int bit_count;
8092 DWORD mask_r, mask_g, mask_b;
8093 BOOL getdc_supported;
8095 testdata[] =
8097 {"A8R8G8B8", D3DFMT_A8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8098 {"X8R8G8B8", D3DFMT_X8R8G8B8, 32, 0x00000000, 0x00000000, 0x00000000, TRUE },
8099 {"R5G6B5", D3DFMT_R5G6B5, 16, 0x0000f800, 0x000007e0, 0x0000001f, TRUE },
8100 {"X1R5G5B5", D3DFMT_X1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8101 {"A1R5G5B5", D3DFMT_A1R5G5B5, 16, 0x00007c00, 0x000003e0, 0x0000001f, TRUE },
8102 {"R8G8B8", D3DFMT_R8G8B8, 24, 0x00000000, 0x00000000, 0x00000000, TRUE },
8103 {"A2R10G10B10", D3DFMT_A2R10G10B10, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8104 {"V8U8", D3DFMT_V8U8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8105 {"Q8W8V8U8", D3DFMT_Q8W8V8U8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8106 {"A8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8107 {"X8B8G8R8", D3DFMT_A8B8G8R8, 32, 0x00000000, 0x00000000, 0x00000000, FALSE},
8108 {"R3G3B2", D3DFMT_R3G3B2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8109 {"P8", D3DFMT_P8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8110 {"L8", D3DFMT_L8, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8111 {"A8L8", D3DFMT_A8L8, 16, 0x00000000, 0x00000000, 0x00000000, FALSE},
8112 {"DXT1", D3DFMT_DXT1, 4, 0x00000000, 0x00000000, 0x00000000, FALSE},
8113 {"DXT2", D3DFMT_DXT2, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8114 {"DXT3", D3DFMT_DXT3, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8115 {"DXT4", D3DFMT_DXT4, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8116 {"DXT5", D3DFMT_DXT5, 8, 0x00000000, 0x00000000, 0x00000000, FALSE},
8118 IDirect3DSurface9 *surface, *surface2;
8119 IDirect3DCubeTexture9 *cube_texture;
8120 struct device_desc device_desc;
8121 IDirect3DTexture9 *texture;
8122 IDirect3DDevice9 *device;
8123 D3DLOCKED_RECT map_desc;
8124 IDirect3D9 *d3d;
8125 unsigned int i;
8126 ULONG refcount;
8127 HWND window;
8128 HDC dc, dc2;
8129 HRESULT hr;
8131 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8132 0, 0, 640, 480, 0, 0, 0, 0);
8133 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8134 ok(!!d3d, "Failed to create a D3D object.\n");
8135 if (!(device = create_device(d3d, window, NULL)))
8137 skip("Failed to create a D3D device, skipping tests.\n");
8138 IDirect3D9_Release(d3d);
8139 DestroyWindow(window);
8140 return;
8143 for (i = 0; i < ARRAY_SIZE(testdata); ++i)
8145 texture = NULL;
8146 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8147 testdata[i].format, D3DPOOL_SYSTEMMEM, &surface, NULL);
8148 if (FAILED(hr))
8150 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
8151 testdata[i].format, D3DPOOL_MANAGED, &texture, NULL);
8152 if (FAILED(hr))
8154 skip("Failed to create surface for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8155 continue;
8157 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8158 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8161 dc = (void *)0x1234;
8162 hr = IDirect3DSurface9_GetDC(surface, &dc);
8163 if (testdata[i].getdc_supported)
8164 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8165 else
8166 ok(FAILED(hr), "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8168 if (SUCCEEDED(hr))
8170 unsigned int width_bytes;
8171 DIBSECTION dib;
8172 HBITMAP bitmap;
8173 DWORD type;
8174 int size;
8176 type = GetObjectType(dc);
8177 ok(type == OBJ_MEMDC, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8178 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
8179 type = GetObjectType(bitmap);
8180 ok(type == OBJ_BITMAP, "Got unexpected object type %#x for format %s.\n", type, testdata[i].name);
8182 size = GetObjectA(bitmap, sizeof(dib), &dib);
8183 ok(size == sizeof(dib), "Got unexpected size %d for format %s.\n", size, testdata[i].name);
8184 ok(!dib.dsBm.bmType, "Got unexpected type %#x for format %s.\n",
8185 dib.dsBm.bmType, testdata[i].name);
8186 ok(dib.dsBm.bmWidth == 64, "Got unexpected width %d for format %s.\n",
8187 dib.dsBm.bmWidth, testdata[i].name);
8188 ok(dib.dsBm.bmHeight == 64, "Got unexpected height %d for format %s.\n",
8189 dib.dsBm.bmHeight, testdata[i].name);
8190 width_bytes = ((dib.dsBm.bmWidth * testdata[i].bit_count + 31) >> 3) & ~3;
8191 ok(dib.dsBm.bmWidthBytes == width_bytes, "Got unexpected width bytes %d for format %s.\n",
8192 dib.dsBm.bmWidthBytes, testdata[i].name);
8193 ok(dib.dsBm.bmPlanes == 1, "Got unexpected plane count %d for format %s.\n",
8194 dib.dsBm.bmPlanes, testdata[i].name);
8195 ok(dib.dsBm.bmBitsPixel == testdata[i].bit_count,
8196 "Got unexpected bit count %d for format %s.\n",
8197 dib.dsBm.bmBitsPixel, testdata[i].name);
8198 ok(!!dib.dsBm.bmBits, "Got unexpected bits %p for format %s.\n",
8199 dib.dsBm.bmBits, testdata[i].name);
8201 ok(dib.dsBmih.biSize == sizeof(dib.dsBmih), "Got unexpected size %u for format %s.\n",
8202 dib.dsBmih.biSize, testdata[i].name);
8203 ok(dib.dsBmih.biWidth == 64, "Got unexpected width %d for format %s.\n",
8204 dib.dsBmih.biHeight, testdata[i].name);
8205 ok(dib.dsBmih.biHeight == 64, "Got unexpected height %d for format %s.\n",
8206 dib.dsBmih.biHeight, testdata[i].name);
8207 ok(dib.dsBmih.biPlanes == 1, "Got unexpected plane count %u for format %s.\n",
8208 dib.dsBmih.biPlanes, testdata[i].name);
8209 ok(dib.dsBmih.biBitCount == testdata[i].bit_count, "Got unexpected bit count %u for format %s.\n",
8210 dib.dsBmih.biBitCount, testdata[i].name);
8211 ok(dib.dsBmih.biCompression == (testdata[i].bit_count == 16 ? BI_BITFIELDS : BI_RGB),
8212 "Got unexpected compression %#x for format %s.\n",
8213 dib.dsBmih.biCompression, testdata[i].name);
8214 ok(!dib.dsBmih.biSizeImage, "Got unexpected image size %u for format %s.\n",
8215 dib.dsBmih.biSizeImage, testdata[i].name);
8216 ok(!dib.dsBmih.biXPelsPerMeter, "Got unexpected horizontal resolution %d for format %s.\n",
8217 dib.dsBmih.biXPelsPerMeter, testdata[i].name);
8218 ok(!dib.dsBmih.biYPelsPerMeter, "Got unexpected vertical resolution %d for format %s.\n",
8219 dib.dsBmih.biYPelsPerMeter, testdata[i].name);
8220 ok(!dib.dsBmih.biClrUsed, "Got unexpected used colour count %u for format %s.\n",
8221 dib.dsBmih.biClrUsed, testdata[i].name);
8222 ok(!dib.dsBmih.biClrImportant, "Got unexpected important colour count %u for format %s.\n",
8223 dib.dsBmih.biClrImportant, testdata[i].name);
8225 if (dib.dsBmih.biCompression == BI_BITFIELDS)
8227 ok(dib.dsBitfields[0] == testdata[i].mask_r && dib.dsBitfields[1] == testdata[i].mask_g
8228 && dib.dsBitfields[2] == testdata[i].mask_b,
8229 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8230 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8232 else
8234 ok(!dib.dsBitfields[0] && !dib.dsBitfields[1] && !dib.dsBitfields[2],
8235 "Got unexpected colour masks 0x%08x 0x%08x 0x%08x for format %s.\n",
8236 dib.dsBitfields[0], dib.dsBitfields[1], dib.dsBitfields[2], testdata[i].name);
8238 ok(!dib.dshSection, "Got unexpected section %p for format %s.\n", dib.dshSection, testdata[i].name);
8239 ok(!dib.dsOffset, "Got unexpected offset %u for format %s.\n", dib.dsOffset, testdata[i].name);
8241 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8242 ok(hr == D3D_OK, "Failed to release DC, hr %#x.\n", hr);
8244 else
8246 ok(dc == (void *)0x1234, "Got unexpected dc %p.\n", dc);
8249 IDirect3DSurface9_Release(surface);
8250 if (texture)
8251 IDirect3DTexture9_Release(texture);
8253 if (!testdata[i].getdc_supported)
8254 continue;
8256 if (FAILED(hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 0, 0,
8257 testdata[i].format, D3DPOOL_MANAGED, &cube_texture, NULL)))
8259 skip("Failed to create cube texture for format %s (hr %#x), skipping tests.\n", testdata[i].name, hr);
8260 continue;
8263 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
8264 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8265 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, D3DCUBEMAP_FACE_NEGATIVE_Y, 2, &surface2);
8266 ok(SUCCEEDED(hr), "Failed to get cube surface for format %s, hr %#x.\n", testdata[i].name, hr);
8268 hr = IDirect3DSurface9_GetDC(surface, &dc);
8269 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8270 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8271 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8272 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8273 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8274 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8275 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8277 hr = IDirect3DSurface9_GetDC(surface, &dc);
8278 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8279 dc2 = (void *)0x1234;
8280 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8281 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8282 ok(dc2 == (void *)0x1234, "Got unexpected dc %p for format %s.\n", dc, testdata[i].name);
8283 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8284 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8285 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8286 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8288 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8289 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8290 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8291 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8292 hr = IDirect3DSurface9_UnlockRect(surface);
8293 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8294 hr = IDirect3DSurface9_UnlockRect(surface);
8295 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8297 hr = IDirect3DSurface9_GetDC(surface, &dc);
8298 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8299 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8300 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8301 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8302 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8304 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8305 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8306 hr = IDirect3DSurface9_GetDC(surface, &dc);
8307 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8308 hr = IDirect3DSurface9_UnlockRect(surface);
8309 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8311 hr = IDirect3DSurface9_GetDC(surface, &dc);
8312 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8313 hr = IDirect3DSurface9_GetDC(surface2, &dc2);
8314 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8315 hr = IDirect3DSurface9_ReleaseDC(surface2, dc2);
8316 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8317 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8318 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8320 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8321 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8322 hr = IDirect3DSurface9_GetDC(surface, &dc2);
8323 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8324 hr = IDirect3DSurface9_ReleaseDC(surface, dc2);
8325 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8326 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8327 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8329 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8330 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8331 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8332 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8333 hr = IDirect3DSurface9_UnlockRect(surface2);
8334 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8335 hr = IDirect3DSurface9_UnlockRect(surface);
8336 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8338 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8339 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8340 hr = IDirect3DSurface9_GetDC(surface, &dc);
8341 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8342 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8343 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8344 hr = IDirect3DSurface9_UnlockRect(surface);
8345 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8347 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8348 ok(SUCCEEDED(hr), "Failed to map surface for format %s, hr %#x.\n", testdata[i].name, hr);
8349 hr = IDirect3DSurface9_GetDC(surface, &dc);
8350 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8351 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8352 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8353 hr = IDirect3DSurface9_UnlockRect(surface2);
8354 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8356 hr = IDirect3DSurface9_GetDC(surface, &dc);
8357 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8358 hr = IDirect3DSurface9_LockRect(surface2, &map_desc, NULL, D3DLOCK_READONLY);
8359 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8360 hr = IDirect3DSurface9_UnlockRect(surface2);
8361 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8362 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8363 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8365 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8366 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8367 hr = IDirect3DSurface9_LockRect(surface, &map_desc, NULL, D3DLOCK_READONLY);
8368 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8369 hr = IDirect3DSurface9_UnlockRect(surface);
8370 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8371 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8372 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8374 hr = IDirect3DSurface9_UnlockRect(surface);
8375 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8376 hr = IDirect3DSurface9_GetDC(surface2, &dc);
8377 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8378 hr = IDirect3DSurface9_UnlockRect(surface);
8379 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8380 hr = IDirect3DSurface9_ReleaseDC(surface2, dc);
8381 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8382 hr = IDirect3DSurface9_UnlockRect(surface);
8383 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8385 hr = IDirect3DSurface9_UnlockRect(surface2);
8386 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8387 hr = IDirect3DSurface9_GetDC(surface, &dc);
8388 ok(SUCCEEDED(hr), "Failed to get DC for format %s, hr %#x.\n", testdata[i].name, hr);
8389 hr = IDirect3DSurface9_UnlockRect(surface2);
8390 ok(SUCCEEDED(hr), "Failed to unmap surface for format %s, hr %#x.\n", testdata[i].name, hr);
8391 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8392 ok(SUCCEEDED(hr), "Failed to release DC for format %s, hr %#x.\n", testdata[i].name, hr);
8393 hr = IDirect3DSurface9_UnlockRect(surface2);
8394 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for format %s.\n", hr, testdata[i].name);
8396 IDirect3DSurface9_Release(surface2);
8397 IDirect3DSurface9_Release(surface);
8398 IDirect3DCubeTexture9_Release(cube_texture);
8401 refcount = IDirect3DDevice9_Release(device);
8402 ok(!refcount, "Device has %u references left.\n", refcount);
8404 /* Backbuffer created with D3DFMT_UNKNOWN format. */
8405 device_desc.width = 640;
8406 device_desc.height = 480;
8407 device_desc.device_window = window;
8408 device_desc.flags = CREATE_DEVICE_UNKNOWN_BACKBUFFER_FORMAT | CREATE_DEVICE_LOCKABLE_BACKBUFFER;
8410 device = create_device(d3d, window, &device_desc);
8411 ok(!!device, "Failed to create device.\n");
8413 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
8414 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
8416 dc = NULL;
8417 hr = IDirect3DSurface9_GetDC(surface, &dc);
8418 ok(!!dc, "Unexpected DC returned.\n");
8419 ok(SUCCEEDED(hr), "Failed to get backbuffer DC, hr %#x.\n", hr);
8420 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
8421 ok(SUCCEEDED(hr), "Failed to release backbuffer DC, hr %#x.\n", hr);
8423 IDirect3DSurface9_Release(surface);
8425 refcount = IDirect3DDevice9_Release(device);
8426 ok(!refcount, "Device has %u references left.\n", refcount);
8428 IDirect3D9_Release(d3d);
8429 DestroyWindow(window);
8432 static void test_surface_dimensions(void)
8434 IDirect3DSurface9 *surface;
8435 IDirect3DDevice9 *device;
8436 IDirect3D9 *d3d;
8437 ULONG refcount;
8438 HWND window;
8439 HRESULT hr;
8441 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8442 0, 0, 640, 480, 0, 0, 0, 0);
8443 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8444 ok(!!d3d, "Failed to create a D3D object.\n");
8445 if (!(device = create_device(d3d, window, NULL)))
8447 skip("Failed to create a D3D device, skipping tests.\n");
8448 IDirect3D9_Release(d3d);
8449 DestroyWindow(window);
8450 return;
8453 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 0, 1,
8454 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8455 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8456 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 1, 0,
8457 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
8458 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
8460 refcount = IDirect3DDevice9_Release(device);
8461 ok(!refcount, "Device has %u references left.\n", refcount);
8462 IDirect3D9_Release(d3d);
8463 DestroyWindow(window);
8466 static void test_surface_format_null(void)
8468 static const D3DFORMAT D3DFMT_NULL = MAKEFOURCC('N','U','L','L');
8469 IDirect3DTexture9 *texture;
8470 IDirect3DSurface9 *surface;
8471 IDirect3DSurface9 *rt, *ds;
8472 D3DLOCKED_RECT locked_rect;
8473 IDirect3DDevice9 *device;
8474 D3DSURFACE_DESC desc;
8475 IDirect3D9 *d3d;
8476 ULONG refcount;
8477 HWND window;
8478 HRESULT hr;
8480 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8481 ok(!!d3d, "Failed to create a D3D object.\n");
8483 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8484 D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL);
8485 if (hr != D3D_OK)
8487 skip("No D3DFMT_NULL support, skipping test.\n");
8488 IDirect3D9_Release(d3d);
8489 return;
8492 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8493 0, 0, 640, 480, 0, 0, 0, 0);
8494 if (!(device = create_device(d3d, window, NULL)))
8496 skip("Failed to create a D3D device, skipping tests.\n");
8497 IDirect3D9_Release(d3d);
8498 DestroyWindow(window);
8499 return;
8502 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8503 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, D3DFMT_NULL);
8504 ok(hr == D3D_OK, "D3DFMT_NULL should be supported for render target textures, hr %#x.\n", hr);
8506 hr = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8507 D3DFMT_NULL, D3DFMT_D24S8);
8508 ok(SUCCEEDED(hr), "Depth stencil match failed for D3DFMT_NULL, hr %#x.\n", hr);
8510 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_NULL,
8511 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
8512 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
8514 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
8515 ok(SUCCEEDED(hr), "Failed to get original render target, hr %#x.\n", hr);
8517 hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds);
8518 ok(SUCCEEDED(hr), "Failed to get original depth/stencil, hr %#x.\n", hr);
8520 hr = IDirect3DDevice9_SetRenderTarget(device, 0, NULL);
8521 ok(FAILED(hr), "Succeeded in setting render target 0 to NULL, should fail.\n");
8523 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8524 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8526 hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
8527 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8529 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
8530 ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8532 hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8533 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
8535 hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
8536 ok(SUCCEEDED(hr), "Failed to set depth/stencil, hr %#x.\n", hr);
8538 IDirect3DSurface9_Release(rt);
8539 IDirect3DSurface9_Release(ds);
8541 hr = IDirect3DSurface9_GetDesc(surface, &desc);
8542 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
8543 ok(desc.Width == 128, "Expected width 128, got %u.\n", desc.Width);
8544 ok(desc.Height == 128, "Expected height 128, got %u.\n", desc.Height);
8546 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
8547 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
8548 ok(locked_rect.Pitch, "Expected non-zero pitch, got %u.\n", locked_rect.Pitch);
8549 ok(!!locked_rect.pBits, "Expected non-NULL pBits, got %p.\n", locked_rect.pBits);
8551 hr = IDirect3DSurface9_UnlockRect(surface);
8552 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8554 IDirect3DSurface9_Release(surface);
8556 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 0, D3DUSAGE_RENDERTARGET,
8557 D3DFMT_NULL, D3DPOOL_DEFAULT, &texture, NULL);
8558 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8559 IDirect3DTexture9_Release(texture);
8561 refcount = IDirect3DDevice9_Release(device);
8562 ok(!refcount, "Device has %u references left.\n", refcount);
8563 IDirect3D9_Release(d3d);
8564 DestroyWindow(window);
8567 static void test_surface_double_unlock(void)
8569 static const D3DPOOL pools[] =
8571 D3DPOOL_DEFAULT,
8572 D3DPOOL_SCRATCH,
8573 D3DPOOL_SYSTEMMEM,
8575 IDirect3DSurface9 *surface;
8576 IDirect3DDevice9 *device;
8577 D3DLOCKED_RECT lr;
8578 IDirect3D9 *d3d;
8579 unsigned int i;
8580 ULONG refcount;
8581 HWND window;
8582 HRESULT hr;
8584 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8585 0, 0, 640, 480, 0, 0, 0, 0);
8586 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8587 ok(!!d3d, "Failed to create a D3D object.\n");
8588 if (!(device = create_device(d3d, window, NULL)))
8590 skip("Failed to create a D3D device, skipping tests.\n");
8591 IDirect3D9_Release(d3d);
8592 DestroyWindow(window);
8593 return;
8596 for (i = 0; i < ARRAY_SIZE(pools); ++i)
8598 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
8599 D3DFMT_X8R8G8B8, pools[i], &surface, NULL);
8600 ok(SUCCEEDED(hr), "Failed to create surface in pool %#x, hr %#x.\n", pools[i], hr);
8602 hr = IDirect3DSurface9_UnlockRect(surface);
8603 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8604 hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
8605 ok(SUCCEEDED(hr), "Failed to lock surface in pool %#x, hr %#x.\n", pools[i], hr);
8606 hr = IDirect3DSurface9_UnlockRect(surface);
8607 ok(SUCCEEDED(hr), "Failed to unlock surface in pool %#x, hr %#x.\n", pools[i], hr);
8608 hr = IDirect3DSurface9_UnlockRect(surface);
8609 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x, for surface in pool %#x.\n", hr, pools[i]);
8611 IDirect3DSurface9_Release(surface);
8614 refcount = IDirect3DDevice9_Release(device);
8615 ok(!refcount, "Device has %u references left.\n", refcount);
8616 IDirect3D9_Release(d3d);
8617 DestroyWindow(window);
8620 static void test_surface_blocks(void)
8622 static const struct
8624 D3DFORMAT fmt;
8625 const char *name;
8626 unsigned int block_width;
8627 unsigned int block_height;
8628 BOOL broken;
8629 BOOL create_size_checked, core_fmt;
8631 formats[] =
8633 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, FALSE, TRUE, TRUE },
8634 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, FALSE, TRUE, TRUE },
8635 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, FALSE, TRUE, TRUE },
8636 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, FALSE, TRUE, TRUE },
8637 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, FALSE, TRUE, TRUE },
8638 /* ATI1N and ATI2N have 2x2 blocks on all AMD cards and Geforce 7 cards,
8639 * which doesn't match the format spec. On newer Nvidia cards
8640 * they have the correct 4x4 block size */
8641 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, TRUE, FALSE, FALSE},
8642 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, TRUE, FALSE, FALSE},
8643 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, FALSE, FALSE, TRUE },
8644 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, FALSE, FALSE, TRUE },
8646 static const struct
8648 D3DPOOL pool;
8649 const char *name;
8650 /* Don't check the return value, Nvidia returns D3DERR_INVALIDCALL for some formats
8651 * and E_INVALIDARG/DDERR_INVALIDPARAMS for others. */
8652 BOOL success;
8654 pools[] =
8656 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
8657 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", TRUE},
8658 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE},
8659 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
8661 static struct
8663 D3DRESOURCETYPE rtype;
8664 const char *type_name;
8665 D3DPOOL pool;
8666 const char *pool_name;
8667 BOOL need_driver_support, need_runtime_support;
8669 create_tests[] =
8671 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8672 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, TRUE },
8673 /* Managed offscreen plain surfaces are not supported */
8674 {D3DRTYPE_SURFACE, "D3DRTYPE_SURFACE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8676 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8677 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8678 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8679 {D3DRTYPE_TEXTURE, "D3DRTYPE_TEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8681 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
8682 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", TRUE, FALSE},
8683 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
8684 {D3DRTYPE_CUBETEXTURE, "D3DRTYPE_CUBETEXTURE", D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
8686 IDirect3DTexture9 *texture;
8687 IDirect3DCubeTexture9 *cube_texture;
8688 IDirect3DSurface9 *surface;
8689 D3DLOCKED_RECT locked_rect;
8690 IDirect3DDevice9 *device;
8691 unsigned int i, j, k, w, h;
8692 BOOL surface_only;
8693 IDirect3D9 *d3d;
8694 ULONG refcount;
8695 HWND window;
8696 HRESULT hr;
8697 RECT rect;
8698 BOOL tex_pow2, cube_pow2;
8699 D3DCAPS9 caps;
8700 static const RECT invalid[] =
8702 {60, 60, 60, 68}, /* 0 height */
8703 {60, 60, 68, 60}, /* 0 width */
8704 {68, 60, 60, 68}, /* left > right */
8705 {60, 68, 68, 60}, /* top > bottom */
8706 {-8, 60, 0, 68}, /* left < surface */
8707 {60, -8, 68, 0}, /* top < surface */
8708 {-16, 60, -8, 68}, /* right < surface */
8709 {60, -16, 68, -8}, /* bottom < surface */
8710 {60, 60, 136, 68}, /* right > surface */
8711 {60, 60, 68, 136}, /* bottom > surface */
8712 {136, 60, 144, 68}, /* left > surface */
8713 {60, 136, 68, 144}, /* top > surface */
8716 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
8717 0, 0, 640, 480, 0, 0, 0, 0);
8718 d3d = Direct3DCreate9(D3D_SDK_VERSION);
8719 ok(!!d3d, "Failed to create a D3D object.\n");
8720 if (!(device = create_device(d3d, window, NULL)))
8722 skip("Failed to create a D3D device, skipping tests.\n");
8723 IDirect3D9_Release(d3d);
8724 DestroyWindow(window);
8725 return;
8728 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8729 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
8730 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
8731 if (tex_pow2)
8732 tex_pow2 = !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL);
8733 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
8735 for (i = 0; i < ARRAY_SIZE(formats); ++i)
8737 BOOL tex_support, cube_support, surface_support, format_known, dynamic_tex_support;
8739 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8740 0, D3DRTYPE_TEXTURE, formats[i].fmt);
8741 tex_support = SUCCEEDED(hr);
8742 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8743 0, D3DRTYPE_CUBETEXTURE, formats[i].fmt);
8744 cube_support = SUCCEEDED(hr);
8745 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8746 0, D3DRTYPE_SURFACE, formats[i].fmt);
8747 surface_support = SUCCEEDED(hr);
8749 /* Scratch pool in general allows texture creation even if the driver does
8750 * not support the format. If the format is an extension format that is not
8751 * known to the runtime, like ATI2N, some driver support is required for
8752 * this to work.
8754 * It is also possible that Windows Vista and Windows 7 d3d9 runtimes know
8755 * about ATI2N. I cannot check this because all my Vista+ machines support
8756 * ATI2N in hardware, but none of my WinXP machines do. */
8757 format_known = tex_support || cube_support || surface_support;
8759 for (w = 1; w <= 8; w++)
8761 for (h = 1; h <= 8; h++)
8763 BOOL block_aligned = TRUE;
8764 BOOL size_is_pow2;
8766 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
8767 block_aligned = FALSE;
8769 size_is_pow2 = !(w & (w - 1) || h & (h - 1));
8771 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
8773 BOOL support, pow2;
8774 HRESULT expect_hr;
8775 BOOL may_succeed = FALSE;
8776 IUnknown **check_null;
8778 if (!formats[i].core_fmt)
8780 /* AMD warns against creating ATI2N textures smaller than
8781 * the block size because the runtime cannot calculate the
8782 * correct texture size. Generalize this for all extension
8783 * formats. */
8784 if (w < formats[i].block_width || h < formats[i].block_height)
8785 continue;
8788 texture = (IDirect3DTexture9 *)0xdeadbeef;
8789 cube_texture = (IDirect3DCubeTexture9 *)0xdeadbeef;
8790 surface = (IDirect3DSurface9 *)0xdeadbeef;
8792 switch (create_tests[j].rtype)
8794 case D3DRTYPE_TEXTURE:
8795 check_null = (IUnknown **)&texture;
8796 hr = IDirect3DDevice9_CreateTexture(device, w, h, 1, 0,
8797 formats[i].fmt, create_tests[j].pool, &texture, NULL);
8798 support = tex_support;
8799 pow2 = tex_pow2;
8800 break;
8802 case D3DRTYPE_CUBETEXTURE:
8803 if (w != h)
8804 continue;
8805 check_null = (IUnknown **)&cube_texture;
8806 hr = IDirect3DDevice9_CreateCubeTexture(device, w, 1, 0,
8807 formats[i].fmt, create_tests[j].pool, &cube_texture, NULL);
8808 support = cube_support;
8809 pow2 = cube_pow2;
8810 break;
8812 case D3DRTYPE_SURFACE:
8813 check_null = (IUnknown **)&surface;
8814 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, w, h,
8815 formats[i].fmt, create_tests[j].pool, &surface, NULL);
8816 support = surface_support;
8817 pow2 = FALSE;
8818 break;
8820 default:
8821 check_null = NULL;
8822 pow2 = FALSE;
8823 support = FALSE;
8824 break;
8827 if (create_tests[j].need_driver_support && !support)
8828 expect_hr = D3DERR_INVALIDCALL;
8829 else if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !format_known)
8830 expect_hr = D3DERR_INVALIDCALL;
8831 else if (formats[i].create_size_checked && !block_aligned)
8832 expect_hr = D3DERR_INVALIDCALL;
8833 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
8834 expect_hr = D3DERR_INVALIDCALL;
8835 else
8836 expect_hr = D3D_OK;
8838 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
8839 * does not support it. Accept scratch creation of extension formats on
8840 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
8841 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
8842 * support it. */
8843 if (!formats[i].core_fmt && !format_known && FAILED(expect_hr))
8844 may_succeed = TRUE;
8846 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
8847 "Got unexpected hr %#x for format %s, pool %s, type %s, size %ux%u.\n",
8848 hr, formats[i].name, create_tests[j].pool_name, create_tests[j].type_name, w, h);
8849 if (FAILED(hr))
8850 ok(*check_null == NULL, "Got object ptr %p, expected NULL.\n", *check_null);
8851 else
8852 IUnknown_Release(*check_null);
8857 surface_only = FALSE;
8858 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
8859 D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE, formats[i].fmt);
8860 dynamic_tex_support = SUCCEEDED(hr);
8861 if (!dynamic_tex_support)
8863 if (!surface_support)
8865 skip("Format %s not supported, skipping lockrect offset tests.\n", formats[i].name);
8866 continue;
8868 surface_only = TRUE;
8871 for (j = 0; j < ARRAY_SIZE(pools); ++j)
8873 switch (pools[j].pool)
8875 case D3DPOOL_SYSTEMMEM:
8876 case D3DPOOL_MANAGED:
8877 if (surface_only)
8878 continue;
8879 /* Fall through */
8880 case D3DPOOL_DEFAULT:
8881 if (surface_only)
8883 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8884 formats[i].fmt, pools[j].pool, &surface, NULL);
8885 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8887 else
8889 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1,
8890 pools[j].pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0,
8891 formats[i].fmt, pools[j].pool, &texture, NULL);
8892 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
8893 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
8894 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
8895 IDirect3DTexture9_Release(texture);
8897 break;
8899 case D3DPOOL_SCRATCH:
8900 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
8901 formats[i].fmt, pools[j].pool, &surface, NULL);
8902 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
8903 break;
8905 default:
8906 break;
8909 if (formats[i].block_width > 1)
8911 SetRect(&rect, formats[i].block_width >> 1, 0, formats[i].block_width, formats[i].block_height);
8912 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8913 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8914 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8915 SUCCEEDED(hr) ? "succeeded" : "failed",
8916 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8917 if (SUCCEEDED(hr))
8919 hr = IDirect3DSurface9_UnlockRect(surface);
8920 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8923 SetRect(&rect, 0, 0, formats[i].block_width >> 1, formats[i].block_height);
8924 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8925 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8926 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8927 SUCCEEDED(hr) ? "succeeded" : "failed",
8928 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8929 if (SUCCEEDED(hr))
8931 hr = IDirect3DSurface9_UnlockRect(surface);
8932 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8936 if (formats[i].block_height > 1)
8938 SetRect(&rect, 0, formats[i].block_height >> 1, formats[i].block_width, formats[i].block_height);
8939 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8940 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8941 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8942 SUCCEEDED(hr) ? "succeeded" : "failed",
8943 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8944 if (SUCCEEDED(hr))
8946 hr = IDirect3DSurface9_UnlockRect(surface);
8947 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8950 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height >> 1);
8951 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8952 ok(FAILED(hr) == !pools[j].success || broken(formats[i].broken),
8953 "Partial block lock %s, expected %s, format %s, pool %s.\n",
8954 SUCCEEDED(hr) ? "succeeded" : "failed",
8955 pools[j].success ? "success" : "failure", formats[i].name, pools[j].name);
8956 if (SUCCEEDED(hr))
8958 hr = IDirect3DSurface9_UnlockRect(surface);
8959 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8963 for (k = 0; k < ARRAY_SIZE(invalid); ++k)
8965 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &invalid[k], 0);
8966 ok(FAILED(hr) == !pools[j].success, "Invalid lock %s(%#x), expected %s, format %s, pool %s, case %u.\n",
8967 SUCCEEDED(hr) ? "succeeded" : "failed", hr, pools[j].success ? "success" : "failure",
8968 formats[i].name, pools[j].name, k);
8969 if (SUCCEEDED(hr))
8971 hr = IDirect3DSurface9_UnlockRect(surface);
8972 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8976 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
8977 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, &rect, 0);
8978 ok(SUCCEEDED(hr), "Got unexpected hr %#x for format %s, pool %s.\n", hr, formats[i].name, pools[j].name);
8979 hr = IDirect3DSurface9_UnlockRect(surface);
8980 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
8982 IDirect3DSurface9_Release(surface);
8985 if (!dynamic_tex_support)
8987 skip("Dynamic %s textures not supported, skipping mipmap test.\n", formats[i].name);
8988 continue;
8991 if (formats[i].block_width == 1 && formats[i].block_height == 1)
8992 continue;
8993 if (!formats[i].core_fmt)
8994 continue;
8996 hr = IDirect3DDevice9_CreateTexture(device, formats[i].block_width, formats[i].block_height, 2,
8997 D3DUSAGE_DYNAMIC, formats[i].fmt, D3DPOOL_DEFAULT, &texture, NULL);
8998 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, format %s.\n", hr, formats[i].name);
9000 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, NULL, 0);
9001 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9002 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9003 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9005 SetRect(&rect, 0, 0, formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1,
9006 formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1);
9007 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9008 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9009 hr = IDirect3DTexture9_UnlockRect(texture, 1);
9010 ok(SUCCEEDED(hr), "Failed lock texture, hr %#x.\n", hr);
9012 SetRect(&rect, 0, 0, formats[i].block_width, formats[i].block_height);
9013 hr = IDirect3DTexture9_LockRect(texture, 1, &locked_rect, &rect, 0);
9014 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
9015 if (SUCCEEDED(hr))
9016 IDirect3DTexture9_UnlockRect(texture, 1);
9018 IDirect3DTexture9_Release(texture);
9021 refcount = IDirect3DDevice9_Release(device);
9022 ok(!refcount, "Device has %u references left.\n", refcount);
9023 IDirect3D9_Release(d3d);
9024 DestroyWindow(window);
9027 static void test_set_palette(void)
9029 IDirect3DDevice9 *device;
9030 IDirect3D9 *d3d9;
9031 UINT refcount;
9032 HWND window;
9033 HRESULT hr;
9034 PALETTEENTRY pal[256];
9035 unsigned int i;
9036 D3DCAPS9 caps;
9038 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9039 0, 0, 640, 480, 0, 0, 0, 0);
9040 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9041 ok(!!d3d9, "Failed to create a D3D object.\n");
9042 if (!(device = create_device(d3d9, window, NULL)))
9044 skip("Failed to create a D3D device, skipping tests.\n");
9045 DestroyWindow(window);
9046 return;
9049 for (i = 0; i < ARRAY_SIZE(pal); i++)
9051 pal[i].peRed = i;
9052 pal[i].peGreen = i;
9053 pal[i].peBlue = i;
9054 pal[i].peFlags = 0xff;
9056 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9057 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9059 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9060 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
9061 for (i = 0; i < ARRAY_SIZE(pal); i++)
9063 pal[i].peRed = i;
9064 pal[i].peGreen = i;
9065 pal[i].peBlue = i;
9066 pal[i].peFlags = i;
9068 if (caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)
9070 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9071 ok(SUCCEEDED(hr), "Failed to set palette entries, hr %#x.\n", hr);
9073 else
9075 hr = IDirect3DDevice9_SetPaletteEntries(device, 0, pal);
9076 ok(hr == D3DERR_INVALIDCALL, "SetPaletteEntries returned %#x, expected D3DERR_INVALIDCALL.\n", hr);
9079 refcount = IDirect3DDevice9_Release(device);
9080 ok(!refcount, "Device has %u references left.\n", refcount);
9081 IDirect3D9_Release(d3d9);
9082 DestroyWindow(window);
9085 static void test_swvp_buffer(void)
9087 IDirect3DDevice9 *device;
9088 IDirect3D9 *d3d9;
9089 UINT refcount;
9090 HWND window;
9091 HRESULT hr;
9092 unsigned int i;
9093 IDirect3DVertexBuffer9 *buffer;
9094 static const unsigned int bufsize = 1024;
9095 D3DVERTEXBUFFER_DESC desc;
9096 struct device_desc device_desc;
9097 struct
9099 float x, y, z;
9100 } *ptr, *ptr2;
9102 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9103 0, 0, 640, 480, 0, 0, 0, 0);
9104 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9105 ok(!!d3d9, "Failed to create a D3D object.\n");
9107 device_desc.device_window = window;
9108 device_desc.width = 640;
9109 device_desc.height = 480;
9110 device_desc.flags = CREATE_DEVICE_SWVP_ONLY;
9111 if (!(device = create_device(d3d9, window, &device_desc)))
9113 skip("Failed to create a D3D device, skipping tests.\n");
9114 DestroyWindow(window);
9115 IDirect3D9_Release(d3d9);
9116 return;
9119 hr = IDirect3DDevice9_CreateVertexBuffer(device, bufsize * sizeof(*ptr), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0,
9120 D3DPOOL_DEFAULT, &buffer, NULL);
9121 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9122 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9123 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9124 ok(desc.Pool == D3DPOOL_DEFAULT, "Got pool %u, expected D3DPOOL_DEFAULT\n", desc.Pool);
9125 ok(desc.Usage == (D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY),
9126 "Got usage %u, expected D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY\n", desc.Usage);
9128 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9129 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9130 for (i = 0; i < bufsize; i++)
9132 ptr[i].x = i * 1.0f;
9133 ptr[i].y = i * 2.0f;
9134 ptr[i].z = i * 3.0f;
9136 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9137 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9139 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9140 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9141 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9142 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9143 hr = IDirect3DDevice9_BeginScene(device);
9144 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9145 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9146 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9147 hr = IDirect3DDevice9_EndScene(device);
9148 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9150 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, bufsize * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9151 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9152 ok(ptr == ptr2, "Lock returned two different pointers: %p, %p\n", ptr, ptr2);
9153 for (i = 0; i < bufsize; i++)
9155 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9157 ok(FALSE, "Vertex %u is %f,%f,%f, expected %f,%f,%f\n", i,
9158 ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9159 break;
9162 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9163 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9165 IDirect3DVertexBuffer9_Release(buffer);
9166 refcount = IDirect3DDevice9_Release(device);
9167 ok(!refcount, "Device has %u references left.\n", refcount);
9168 IDirect3D9_Release(d3d9);
9169 DestroyWindow(window);
9172 static void test_managed_buffer(void)
9174 static const unsigned int vertex_count = 1024;
9175 IDirect3DVertexBuffer9 *buffer;
9176 D3DVERTEXBUFFER_DESC desc;
9177 IDirect3DDevice9 *device;
9178 struct vec3 *ptr, *ptr2;
9179 IDirect3D9 *d3d9;
9180 unsigned int i;
9181 UINT refcount;
9182 HWND window;
9183 HRESULT hr;
9185 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9186 0, 0, 640, 480, 0, 0, 0, 0);
9187 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9188 ok(!!d3d9, "Failed to create a D3D object.\n");
9189 if (!(device = create_device(d3d9, window, NULL)))
9191 skip("Failed to create a D3D device, skipping tests.\n");
9192 IDirect3D9_Release(d3d9);
9193 DestroyWindow(window);
9194 return;
9197 hr = IDirect3DDevice9_CreateVertexBuffer(device, vertex_count * sizeof(*ptr),
9198 0, 0, D3DPOOL_MANAGED, &buffer, NULL);
9199 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
9200 hr = IDirect3DVertexBuffer9_GetDesc(buffer, &desc);
9201 ok(SUCCEEDED(hr), "Failed to get desc, hr %#x.\n", hr);
9202 ok(desc.Pool == D3DPOOL_MANAGED, "Got unexpected pool %#x.\n", desc.Pool);
9203 ok(!desc.Usage, "Got unexpected usage %#x.\n", desc.Usage);
9205 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr), (void **)&ptr, D3DLOCK_DISCARD);
9206 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9207 for (i = 0; i < vertex_count; ++i)
9209 ptr[i].x = i * 1.0f;
9210 ptr[i].y = i * 2.0f;
9211 ptr[i].z = i * 3.0f;
9213 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9214 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9216 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
9217 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
9218 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*ptr));
9219 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
9220 hr = IDirect3DDevice9_BeginScene(device);
9221 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
9222 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLELIST, 0, 2);
9223 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
9224 hr = IDirect3DDevice9_EndScene(device);
9225 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
9227 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, vertex_count * sizeof(*ptr2), (void **)&ptr2, D3DLOCK_DISCARD);
9228 ok(SUCCEEDED(hr), "Failed to lock buffer, hr %#x.\n", hr);
9229 ok(ptr2 == ptr, "Got unexpected ptr2 %p, expected %p.\n", ptr2, ptr);
9230 for (i = 0; i < vertex_count; ++i)
9232 if (ptr2[i].x != i * 1.0f || ptr2[i].y != i * 2.0f || ptr2[i].z != i * 3.0f)
9234 ok(FALSE, "Got unexpected vertex %u {%.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e}.\n",
9235 i, ptr2[i].x, ptr2[i].y, ptr2[i].z, i * 1.0f, i * 2.0f, i * 3.0f);
9236 break;
9239 hr = IDirect3DVertexBuffer9_Unlock(buffer);
9240 ok(SUCCEEDED(hr), "Failed to unlock buffer, hr %#x.\n", hr);
9242 IDirect3DVertexBuffer9_Release(buffer);
9243 refcount = IDirect3DDevice9_Release(device);
9244 ok(!refcount, "Device has %u references left.\n", refcount);
9245 IDirect3D9_Release(d3d9);
9246 DestroyWindow(window);
9249 static void test_npot_textures(void)
9251 IDirect3DDevice9 *device = NULL;
9252 IDirect3D9 *d3d9;
9253 ULONG refcount;
9254 HWND window = NULL;
9255 HRESULT hr;
9256 D3DCAPS9 caps;
9257 IDirect3DTexture9 *texture;
9258 IDirect3DCubeTexture9 *cube_texture;
9259 IDirect3DVolumeTexture9 *volume_texture;
9260 struct
9262 D3DPOOL pool;
9263 const char *pool_name;
9264 HRESULT hr;
9266 pools[] =
9268 { D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", D3DERR_INVALIDCALL },
9269 { D3DPOOL_MANAGED, "D3DPOOL_MANAGED", D3DERR_INVALIDCALL },
9270 { D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", D3DERR_INVALIDCALL },
9271 { D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", D3D_OK },
9273 unsigned int i, levels;
9274 BOOL tex_pow2, cube_pow2, vol_pow2;
9276 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9277 0, 0, 640, 480, 0, 0, 0, 0);
9278 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9279 ok(!!d3d9, "Failed to create a D3D object.\n");
9280 if (!(device = create_device(d3d9, window, NULL)))
9282 skip("Failed to create a D3D device, skipping tests.\n");
9283 goto done;
9286 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9287 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9288 tex_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_POW2);
9289 cube_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2);
9290 vol_pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9291 ok(cube_pow2 == tex_pow2, "Cube texture and 2d texture pow2 restrictions mismatch.\n");
9292 ok(vol_pow2 == tex_pow2, "Volume texture and 2d texture pow2 restrictions mismatch.\n");
9294 for (i = 0; i < ARRAY_SIZE(pools); i++)
9296 for (levels = 0; levels <= 2; levels++)
9298 HRESULT expected;
9300 hr = IDirect3DDevice9_CreateTexture(device, 10, 10, levels, 0, D3DFMT_X8R8G8B8,
9301 pools[i].pool, &texture, NULL);
9302 if (!tex_pow2)
9304 expected = D3D_OK;
9306 else if (caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)
9308 if (levels == 1)
9309 expected = D3D_OK;
9310 else
9311 expected = pools[i].hr;
9313 else
9315 expected = pools[i].hr;
9317 ok(hr == expected, "CreateTexture(w=h=10, %s, levels=%u) returned hr %#x, expected %#x.\n",
9318 pools[i].pool_name, levels, hr, expected);
9320 if (SUCCEEDED(hr))
9321 IDirect3DTexture9_Release(texture);
9324 hr = IDirect3DDevice9_CreateCubeTexture(device, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9325 &cube_texture, NULL);
9326 if (tex_pow2)
9328 ok(hr == pools[i].hr, "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9329 pools[i].pool_name, hr, pools[i].hr);
9331 else
9333 ok(SUCCEEDED(hr), "CreateCubeTexture(EdgeLength=3, %s) returned hr %#x, expected %#x.\n",
9334 pools[i].pool_name, hr, D3D_OK);
9337 if (SUCCEEDED(hr))
9338 IDirect3DCubeTexture9_Release(cube_texture);
9340 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 2, 3, 1, 0, D3DFMT_X8R8G8B8, pools[i].pool,
9341 &volume_texture, NULL);
9342 if (tex_pow2)
9344 ok(hr == pools[i].hr, "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9345 pools[i].pool_name, hr, pools[i].hr);
9347 else
9349 ok(SUCCEEDED(hr), "CreateVolumeTextur(Depth=3, %s) returned hr %#x, expected %#x.\n",
9350 pools[i].pool_name, hr, D3D_OK);
9353 if (SUCCEEDED(hr))
9354 IDirect3DVolumeTexture9_Release(volume_texture);
9357 done:
9358 if (device)
9360 refcount = IDirect3DDevice9_Release(device);
9361 ok(!refcount, "Device has %u references left.\n", refcount);
9363 IDirect3D9_Release(d3d9);
9364 DestroyWindow(window);
9368 static void test_vidmem_accounting(void)
9370 IDirect3DDevice9 *device;
9371 IDirect3D9 *d3d9;
9372 ULONG refcount;
9373 HWND window;
9374 HRESULT hr = D3D_OK;
9375 IDirect3DTexture9 *textures[20];
9376 unsigned int i;
9377 UINT vidmem_start, vidmem_end, diff;
9379 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9380 0, 0, 640, 480, 0, 0, 0, 0);
9381 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9382 ok(!!d3d9, "Failed to create a D3D object.\n");
9383 if (!(device = create_device(d3d9, window, NULL)))
9385 skip("Failed to create a D3D device, skipping tests.\n");
9386 IDirect3D9_Release(d3d9);
9387 DestroyWindow(window);
9388 return;
9391 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
9392 memset(textures, 0, sizeof(textures));
9393 for (i = 0; i < ARRAY_SIZE(textures); i++)
9395 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
9396 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
9397 /* D3DERR_OUTOFVIDEOMEMORY is returned when the card runs out of video memory
9398 * E_FAIL is returned on address space or system memory exhaustion */
9399 ok(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY,
9400 "Failed to create texture, hr %#x.\n", hr);
9402 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
9404 ok(vidmem_start > vidmem_end, "Expected available texture memory to decrease during texture creation.\n");
9405 diff = vidmem_start - vidmem_end;
9406 ok(diff > 1024 * 1024 * 2 * i, "Expected a video memory difference of at least %u MB, got %u MB.\n",
9407 2 * i, diff / 1024 / 1024);
9409 for (i = 0; i < ARRAY_SIZE(textures); i++)
9411 if (textures[i])
9412 IDirect3DTexture9_Release(textures[i]);
9415 refcount = IDirect3DDevice9_Release(device);
9416 ok(!refcount, "Device has %u references left.\n", refcount);
9417 IDirect3D9_Release(d3d9);
9418 DestroyWindow(window);
9421 static void test_volume_locking(void)
9423 IDirect3DDevice9 *device;
9424 IDirect3D9 *d3d9;
9425 HWND window;
9426 HRESULT hr;
9427 IDirect3DVolumeTexture9 *texture;
9428 unsigned int i;
9429 D3DLOCKED_BOX locked_box;
9430 ULONG refcount;
9431 D3DCAPS9 caps;
9432 static const struct
9434 D3DPOOL pool;
9435 DWORD usage;
9436 HRESULT create_hr, lock_hr;
9438 tests[] =
9440 { D3DPOOL_DEFAULT, 0, D3D_OK, D3DERR_INVALIDCALL },
9441 { D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9442 { D3DPOOL_SYSTEMMEM, 0, D3D_OK, D3D_OK },
9443 { D3DPOOL_SYSTEMMEM, D3DUSAGE_DYNAMIC, D3D_OK, D3D_OK },
9444 { D3DPOOL_MANAGED, 0, D3D_OK, D3D_OK },
9445 { D3DPOOL_MANAGED, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9446 { D3DPOOL_SCRATCH, 0, D3D_OK, D3D_OK },
9447 { D3DPOOL_SCRATCH, D3DUSAGE_DYNAMIC, D3DERR_INVALIDCALL, D3D_OK },
9450 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9451 0, 0, 640, 480, 0, 0, 0, 0);
9452 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9453 ok(!!d3d9, "Failed to create a D3D object.\n");
9454 if (!(device = create_device(d3d9, window, NULL)))
9456 skip("Failed to create a D3D device, skipping tests.\n");
9457 IDirect3D9_Release(d3d9);
9458 DestroyWindow(window);
9459 return;
9462 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9463 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9464 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9466 skip("Volume textures not supported, skipping test.\n");
9467 goto out;
9470 for (i = 0; i < ARRAY_SIZE(tests); i++)
9472 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 1, tests[i].usage,
9473 D3DFMT_A8R8G8B8, tests[i].pool, &texture, NULL);
9474 ok(hr == tests[i].create_hr, "Creating volume texture pool=%u, usage=%#x returned %#x, expected %#x.\n",
9475 tests[i].pool, tests[i].usage, hr, tests[i].create_hr);
9476 if (FAILED(hr))
9477 continue;
9479 locked_box.pBits = (void *)0xdeadbeef;
9480 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9481 ok(hr == tests[i].lock_hr, "Lock returned %#x, expected %#x.\n", hr, tests[i].lock_hr);
9482 if (SUCCEEDED(hr))
9484 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9485 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9487 else
9489 ok(locked_box.pBits == NULL, "Failed lock set pBits = %p, expected NULL.\n", locked_box.pBits);
9491 IDirect3DVolumeTexture9_Release(texture);
9494 out:
9495 refcount = IDirect3DDevice9_Release(device);
9496 ok(!refcount, "Device has %u references left.\n", refcount);
9497 IDirect3D9_Release(d3d9);
9498 DestroyWindow(window);
9501 static void test_update_volumetexture(void)
9503 IDirect3DDevice9 *device;
9504 IDirect3D9 *d3d9;
9505 HWND window;
9506 HRESULT hr;
9507 IDirect3DVolumeTexture9 *src, *dst;
9508 unsigned int i;
9509 D3DLOCKED_BOX locked_box;
9510 ULONG refcount;
9511 D3DCAPS9 caps;
9512 static const struct
9514 D3DPOOL src_pool, dst_pool;
9515 HRESULT hr;
9517 tests[] =
9519 { D3DPOOL_DEFAULT, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9520 { D3DPOOL_MANAGED, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9521 { D3DPOOL_SYSTEMMEM, D3DPOOL_DEFAULT, D3D_OK },
9522 { D3DPOOL_SCRATCH, D3DPOOL_DEFAULT, D3DERR_INVALIDCALL },
9524 { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9525 { D3DPOOL_MANAGED, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9526 { D3DPOOL_SYSTEMMEM, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9527 { D3DPOOL_SCRATCH, D3DPOOL_MANAGED, D3DERR_INVALIDCALL },
9529 { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9530 { D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9531 { D3DPOOL_SYSTEMMEM, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9532 { D3DPOOL_SCRATCH, D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL },
9534 { D3DPOOL_DEFAULT, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9535 { D3DPOOL_MANAGED, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9536 { D3DPOOL_SYSTEMMEM, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9537 { D3DPOOL_SCRATCH, D3DPOOL_SCRATCH, D3DERR_INVALIDCALL },
9539 static const struct
9541 UINT src_size, dst_size;
9542 UINT src_lvl, dst_lvl;
9543 D3DFORMAT src_fmt, dst_fmt;
9545 tests2[] =
9547 { 8, 8, 0, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9548 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9549 { 8, 8, 2, 2, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9550 { 8, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9551 { 8, 8, 4, 0, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 },
9552 { 8, 8, 1, 4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different level count */
9553 { 4, 8, 1, 1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8 }, /* Different size */
9554 { 8, 8, 4, 4, D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8 }, /* Different format */
9557 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9558 0, 0, 640, 480, 0, 0, 0, 0);
9559 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9560 ok(!!d3d9, "Failed to create a D3D object.\n");
9561 if (!(device = create_device(d3d9, window, NULL)))
9563 skip("Failed to create a D3D device, skipping tests.\n");
9564 IDirect3D9_Release(d3d9);
9565 DestroyWindow(window);
9566 return;
9569 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9570 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9571 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
9573 skip("Volume textures not supported, skipping test.\n");
9574 goto out;
9577 for (i = 0; i < ARRAY_SIZE(tests); i++)
9579 DWORD src_usage = tests[i].src_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9580 DWORD dst_usage = tests[i].dst_pool == D3DPOOL_DEFAULT ? D3DUSAGE_DYNAMIC : 0;
9582 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, src_usage,
9583 D3DFMT_A8R8G8B8, tests[i].src_pool, &src, NULL);
9584 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9585 hr = IDirect3DDevice9_CreateVolumeTexture(device, 1, 1, 1, 1, dst_usage,
9586 D3DFMT_A8R8G8B8, tests[i].dst_pool, &dst, NULL);
9587 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9589 hr = IDirect3DVolumeTexture9_LockBox(src, 0, &locked_box, NULL, 0);
9590 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9591 *((DWORD *)locked_box.pBits) = 0x11223344;
9592 hr = IDirect3DVolumeTexture9_UnlockBox(src, 0);
9593 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9595 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9596 ok(hr == tests[i].hr, "UpdateTexture returned %#x, expected %#x, src pool %x, dst pool %u.\n",
9597 hr, tests[i].hr, tests[i].src_pool, tests[i].dst_pool);
9599 if (SUCCEEDED(hr))
9601 DWORD content = *((DWORD *)locked_box.pBits);
9602 hr = IDirect3DVolumeTexture9_LockBox(dst, 0, &locked_box, NULL, 0);
9603 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
9604 ok(content == 0x11223344, "Dest texture contained %#x, expected 0x11223344.\n", content);
9605 hr = IDirect3DVolumeTexture9_UnlockBox(dst, 0);
9606 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9608 IDirect3DVolumeTexture9_Release(src);
9609 IDirect3DVolumeTexture9_Release(dst);
9612 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
9614 skip("Mipmapped volume maps not supported.\n");
9615 goto out;
9618 for (i = 0; i < ARRAY_SIZE(tests2); i++)
9620 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9621 tests2[i].src_size, tests2[i].src_size, tests2[i].src_size,
9622 tests2[i].src_lvl, 0, tests2[i].src_fmt, D3DPOOL_SYSTEMMEM, &src, NULL);
9623 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9624 hr = IDirect3DDevice9_CreateVolumeTexture(device,
9625 tests2[i].dst_size, tests2[i].dst_size, tests2[i].dst_size,
9626 tests2[i].dst_lvl, 0, tests2[i].dst_fmt, D3DPOOL_DEFAULT, &dst, NULL);
9627 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x, case %u.\n", hr, i);
9629 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)src, (IDirect3DBaseTexture9 *)dst);
9630 todo_wine_if (FAILED(hr))
9631 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x, case %u.\n", hr, i);
9633 IDirect3DVolumeTexture9_Release(src);
9634 IDirect3DVolumeTexture9_Release(dst);
9637 /* As far as I can see, UpdateTexture on non-matching texture behaves like a memcpy. The raw data
9638 * stays the same in a format change, a 2x2x1 texture is copied into the first row of a 4x4x1 texture,
9639 * etc. I could not get it to segfault, but the nonexistent 5th pixel of a 2x2x1 texture is copied into
9640 * pixel 1x2x1 of a 4x4x1 texture, demonstrating a read beyond the texture's end. I suspect any bad
9641 * memory access is silently ignored by the runtime, in the kernel or on the GPU.
9643 * I'm not adding tests for this behavior until an application needs it. */
9645 out:
9646 refcount = IDirect3DDevice9_Release(device);
9647 ok(!refcount, "Device has %u references left.\n", refcount);
9648 IDirect3D9_Release(d3d9);
9649 DestroyWindow(window);
9652 static void test_create_rt_ds_fail(void)
9654 IDirect3DDevice9 *device;
9655 HWND window;
9656 HRESULT hr;
9657 ULONG refcount;
9658 IDirect3D9 *d3d9;
9659 IDirect3DSurface9 *surface;
9661 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9662 0, 0, 640, 480, 0, 0, 0, 0);
9663 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9664 ok(!!d3d9, "Failed to create a D3D object.\n");
9665 if (!(device = create_device(d3d9, window, NULL)))
9667 skip("Failed to create a D3D device, skipping tests.\n");
9668 IDirect3D9_Release(d3d9);
9669 DestroyWindow(window);
9670 return;
9673 /* Output pointer == NULL segfaults on Windows. */
9675 surface = (IDirect3DSurface9 *)0xdeadbeef;
9676 hr = IDirect3DDevice9_CreateRenderTarget(device, 4, 4, D3DFMT_D16,
9677 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
9678 ok(hr == D3DERR_INVALIDCALL, "Creating a D16 render target returned hr %#x.\n", hr);
9679 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9680 if (SUCCEEDED(hr))
9681 IDirect3DSurface9_Release(surface);
9683 surface = (IDirect3DSurface9 *)0xdeadbeef;
9684 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 4, 4, D3DFMT_A8R8G8B8,
9685 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
9686 ok(hr == D3DERR_INVALIDCALL, "Creating a A8R8G8B8 depth stencil returned hr %#x.\n", hr);
9687 ok(surface == NULL, "Got pointer %p, expected NULL.\n", surface);
9688 if (SUCCEEDED(hr))
9689 IDirect3DSurface9_Release(surface);
9691 refcount = IDirect3DDevice9_Release(device);
9692 ok(!refcount, "Device has %u references left.\n", refcount);
9693 IDirect3D9_Release(d3d9);
9694 DestroyWindow(window);
9697 static void test_volume_blocks(void)
9699 IDirect3DDevice9 *device;
9700 IDirect3D9 *d3d9;
9701 UINT refcount;
9702 HWND window;
9703 HRESULT hr;
9704 D3DCAPS9 caps;
9705 IDirect3DVolumeTexture9 *texture;
9706 unsigned int w, h, d, i, j;
9707 static const struct
9709 D3DFORMAT fmt;
9710 const char *name;
9711 unsigned int block_width;
9712 unsigned int block_height;
9713 unsigned int block_depth;
9714 unsigned int block_size;
9715 unsigned int broken;
9716 BOOL create_size_checked, core_fmt;
9718 formats[] =
9720 /* Scratch volumes enforce DXTn block locks, unlike their surface counterparts.
9721 * ATI2N and YUV blocks are not enforced on any tested card (r200, gtx 460). */
9722 {D3DFMT_DXT1, "D3DFMT_DXT1", 4, 4, 1, 8, 0, TRUE, TRUE },
9723 {D3DFMT_DXT2, "D3DFMT_DXT2", 4, 4, 1, 16, 0, TRUE, TRUE },
9724 {D3DFMT_DXT3, "D3DFMT_DXT3", 4, 4, 1, 16, 0, TRUE, TRUE },
9725 {D3DFMT_DXT4, "D3DFMT_DXT4", 4, 4, 1, 16, 0, TRUE, TRUE },
9726 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9727 {D3DFMT_DXT5, "D3DFMT_DXT5", 4, 4, 1, 16, 0, TRUE, TRUE },
9728 /* ATI2N has 2x2 blocks on all AMD cards and Geforce 7 cards,
9729 * which doesn't match the format spec. On newer Nvidia cards
9730 * it has the correct 4x4 block size.
9731 * ATI1N volume textures are only supported by AMD GPUs right
9732 * now and locking offsets seem just wrong. */
9733 {MAKEFOURCC('A','T','I','1'), "ATI1N", 4, 4, 1, 8, 2, FALSE, FALSE},
9734 {MAKEFOURCC('A','T','I','2'), "ATI2N", 4, 4, 1, 16, 1, FALSE, FALSE},
9735 {D3DFMT_YUY2, "D3DFMT_YUY2", 2, 1, 1, 4, 1, FALSE, TRUE },
9736 {D3DFMT_UYVY, "D3DFMT_UYVY", 2, 1, 1, 4, 1, FALSE, TRUE },
9738 static const struct
9740 D3DPOOL pool;
9741 const char *name;
9742 BOOL need_driver_support, need_runtime_support;
9744 create_tests[] =
9746 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", TRUE, FALSE},
9747 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE, TRUE },
9748 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM",TRUE, FALSE},
9749 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE, FALSE},
9751 static const struct
9753 unsigned int x, y, z, x2, y2, z2;
9755 offset_tests[] =
9757 {0, 0, 0, 8, 8, 8},
9758 {0, 0, 3, 8, 8, 8},
9759 {0, 4, 0, 8, 8, 8},
9760 {0, 4, 3, 8, 8, 8},
9761 {4, 0, 0, 8, 8, 8},
9762 {4, 0, 3, 8, 8, 8},
9763 {4, 4, 0, 8, 8, 8},
9764 {4, 4, 3, 8, 8, 8},
9766 D3DBOX box;
9767 D3DLOCKED_BOX locked_box;
9768 BYTE *base;
9769 INT expected_row_pitch, expected_slice_pitch;
9770 BOOL support;
9771 BOOL pow2;
9772 unsigned int offset, expected_offset;
9774 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
9775 0, 0, 640, 480, 0, 0, 0, 0);
9776 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
9777 ok(!!d3d9, "Failed to create a D3D object.\n");
9778 if (!(device = create_device(d3d9, window, NULL)))
9780 skip("Failed to create a D3D device, skipping tests.\n");
9781 IDirect3D9_Release(d3d9);
9782 DestroyWindow(window);
9783 return;
9785 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9786 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
9787 pow2 = !!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2);
9789 for (i = 0; i < ARRAY_SIZE(formats); i++)
9791 hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9792 0, D3DRTYPE_VOLUMETEXTURE, formats[i].fmt);
9793 support = SUCCEEDED(hr);
9795 /* Test creation restrictions */
9796 for (w = 1; w <= 8; w++)
9798 for (h = 1; h <= 8; h++)
9800 for (d = 1; d <= 8; d++)
9802 HRESULT expect_hr;
9803 BOOL size_is_pow2;
9804 BOOL block_aligned = TRUE;
9806 if (w & (formats[i].block_width - 1) || h & (formats[i].block_height - 1))
9807 block_aligned = FALSE;
9809 size_is_pow2 = !((w & (w - 1)) || (h & (h - 1)) || (d & (d - 1)));
9811 for (j = 0; j < ARRAY_SIZE(create_tests); j++)
9813 BOOL may_succeed = FALSE;
9815 if (create_tests[j].need_runtime_support && !formats[i].core_fmt && !support)
9816 expect_hr = D3DERR_INVALIDCALL;
9817 else if (formats[i].create_size_checked && !block_aligned)
9818 expect_hr = D3DERR_INVALIDCALL;
9819 else if (pow2 && !size_is_pow2 && create_tests[j].need_driver_support)
9820 expect_hr = D3DERR_INVALIDCALL;
9821 else if (create_tests[j].need_driver_support && !support)
9822 expect_hr = D3DERR_INVALIDCALL;
9823 else
9824 expect_hr = D3D_OK;
9826 texture = (IDirect3DVolumeTexture9 *)0xdeadbeef;
9827 hr = IDirect3DDevice9_CreateVolumeTexture(device, w, h, d, 1, 0,
9828 formats[i].fmt, create_tests[j].pool, &texture, NULL);
9830 /* Wine knows about ATI2N and happily creates a scratch resource even if GL
9831 * does not support it. Accept scratch creation of extension formats on
9832 * Windows as well if it occurs. We don't really care if e.g. a Windows 7
9833 * on an r200 GPU creates scratch ATI2N texture even though the card doesn't
9834 * support it. */
9835 if (!formats[i].core_fmt && !support && FAILED(expect_hr))
9836 may_succeed = TRUE;
9838 ok(hr == expect_hr || ((SUCCEEDED(hr) && may_succeed)),
9839 "Got unexpected hr %#x for format %s, pool %s, size %ux%ux%u.\n",
9840 hr, formats[i].name, create_tests[j].name, w, h, d);
9842 if (FAILED(hr))
9843 ok(texture == NULL, "Got texture ptr %p, expected NULL.\n", texture);
9844 else
9845 IDirect3DVolumeTexture9_Release(texture);
9851 if (!support && !formats[i].core_fmt)
9852 continue;
9854 hr = IDirect3DDevice9_CreateVolumeTexture(device, 24, 8, 8, 1, 0,
9855 formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
9856 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
9858 /* Test lockrect offset */
9859 for (j = 0; j < ARRAY_SIZE(offset_tests); j++)
9861 unsigned int bytes_per_pixel;
9862 bytes_per_pixel = formats[i].block_size / (formats[i].block_width * formats[i].block_height);
9864 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
9865 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9867 base = locked_box.pBits;
9868 if (formats[i].broken == 1)
9870 expected_row_pitch = bytes_per_pixel * 24;
9872 else if (formats[i].broken == 2)
9874 expected_row_pitch = 24;
9876 else
9878 expected_row_pitch = (24 /* tex width */ + formats[i].block_height - 1) / formats[i].block_width
9879 * formats[i].block_size;
9881 ok(locked_box.RowPitch == expected_row_pitch, "Got unexpected row pitch %d for format %s, expected %d.\n",
9882 locked_box.RowPitch, formats[i].name, expected_row_pitch);
9884 if (formats[i].broken)
9886 expected_slice_pitch = expected_row_pitch * 8;
9888 else
9890 expected_slice_pitch = (8 /* tex height */ + formats[i].block_depth - 1) / formats[i].block_height
9891 * expected_row_pitch;
9893 ok(locked_box.SlicePitch == expected_slice_pitch,
9894 "Got unexpected slice pitch %d for format %s, expected %d.\n",
9895 locked_box.SlicePitch, formats[i].name, expected_slice_pitch);
9897 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9898 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x, j %u.\n", hr, j);
9900 box.Left = offset_tests[j].x;
9901 box.Top = offset_tests[j].y;
9902 box.Front = offset_tests[j].z;
9903 box.Right = offset_tests[j].x2;
9904 box.Bottom = offset_tests[j].y2;
9905 box.Back = offset_tests[j].z2;
9906 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9907 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x, j %u.\n", hr, j);
9909 offset = (BYTE *)locked_box.pBits - base;
9910 if (formats[i].broken == 1)
9912 expected_offset = box.Front * expected_slice_pitch
9913 + box.Top * expected_row_pitch
9914 + box.Left * bytes_per_pixel;
9916 else if (formats[i].broken == 2)
9918 expected_offset = box.Front * expected_slice_pitch
9919 + box.Top * expected_row_pitch
9920 + box.Left;
9922 else
9924 expected_offset = (box.Front / formats[i].block_depth) * expected_slice_pitch
9925 + (box.Top / formats[i].block_height) * expected_row_pitch
9926 + (box.Left / formats[i].block_width) * formats[i].block_size;
9928 ok(offset == expected_offset, "Got unexpected offset %u for format %s, expected %u, box start %ux%ux%u.\n",
9929 offset, formats[i].name, expected_offset, box.Left, box.Top, box.Front);
9931 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9932 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9935 /* Test partial block locks */
9936 box.Front = 0;
9937 box.Back = 1;
9938 if (formats[i].block_width > 1)
9940 box.Left = formats[i].block_width >> 1;
9941 box.Top = 0;
9942 box.Right = formats[i].block_width;
9943 box.Bottom = formats[i].block_height;
9944 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9945 ok(FAILED(hr) || broken(formats[i].broken),
9946 "Partial block lock succeeded, expected failure, format %s.\n",
9947 formats[i].name);
9948 if (SUCCEEDED(hr))
9950 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9951 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9954 box.Left = 0;
9955 box.Top = 0;
9956 box.Right = formats[i].block_width >> 1;
9957 box.Bottom = formats[i].block_height;
9958 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9959 ok(FAILED(hr) || broken(formats[i].broken),
9960 "Partial block lock succeeded, expected failure, format %s.\n",
9961 formats[i].name);
9962 if (SUCCEEDED(hr))
9964 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9965 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9969 if (formats[i].block_height > 1)
9971 box.Left = 0;
9972 box.Top = formats[i].block_height >> 1;
9973 box.Right = formats[i].block_width;
9974 box.Bottom = formats[i].block_height;
9975 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9976 ok(FAILED(hr) || broken(formats[i].broken),
9977 "Partial block lock succeeded, expected failure, format %s.\n",
9978 formats[i].name);
9979 if (SUCCEEDED(hr))
9981 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9982 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
9985 box.Left = 0;
9986 box.Top = 0;
9987 box.Right = formats[i].block_width;
9988 box.Bottom = formats[i].block_height >> 1;
9989 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
9990 ok(FAILED(hr) || broken(formats[i].broken),
9991 "Partial block lock succeeded, expected failure, format %s.\n",
9992 formats[i].name);
9993 if (SUCCEEDED(hr))
9995 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
9996 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10000 /* Test full block lock */
10001 box.Left = 0;
10002 box.Top = 0;
10003 box.Right = formats[i].block_width;
10004 box.Bottom = formats[i].block_height;
10005 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &box, 0);
10006 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10007 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10008 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10010 IDirect3DVolumeTexture9_Release(texture);
10012 /* Test mipmap locks. Don't do this with ATI2N, AMD warns that the runtime
10013 * does not allocate surfaces smaller than the blocksize properly. */
10014 if ((formats[i].block_width > 1 || formats[i].block_height > 1) && formats[i].core_fmt)
10016 hr = IDirect3DDevice9_CreateVolumeTexture(device, formats[i].block_width, formats[i].block_height,
10017 2, 2, 0, formats[i].fmt, D3DPOOL_SCRATCH, &texture, NULL);
10018 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10020 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, NULL, 0);
10021 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10022 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10023 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10025 box.Left = box.Top = box.Front = 0;
10026 box.Right = formats[i].block_width == 1 ? 1 : formats[i].block_width >> 1;
10027 box.Bottom = formats[i].block_height == 1 ? 1 : formats[i].block_height >> 1;
10028 box.Back = 1;
10029 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10030 ok(SUCCEEDED(hr), "Failed to lock volume texture mipmap, hr %#x.\n", hr);
10031 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10032 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10034 box.Right = formats[i].block_width;
10035 box.Bottom = formats[i].block_height;
10036 hr = IDirect3DVolumeTexture9_LockBox(texture, 1, &locked_box, &box, 0);
10037 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10038 if (SUCCEEDED(hr))
10039 IDirect3DVolumeTexture9_UnlockBox(texture, 1);
10041 IDirect3DVolumeTexture9_Release(texture);
10045 refcount = IDirect3DDevice9_Release(device);
10046 ok(!refcount, "Device has %u references left.\n", refcount);
10047 IDirect3D9_Release(d3d9);
10048 DestroyWindow(window);
10051 static void test_lockbox_invalid(void)
10053 static const struct
10055 D3DBOX box;
10056 HRESULT result;
10058 test_data[] =
10060 {{0, 0, 2, 2, 0, 1}, D3D_OK}, /* Valid */
10061 {{0, 0, 4, 4, 0, 1}, D3D_OK}, /* Valid */
10062 {{0, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* 0 height */
10063 {{0, 0, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* 0 width */
10064 {{0, 0, 4, 4, 1, 1}, D3DERR_INVALIDCALL}, /* 0 depth */
10065 {{4, 0, 0, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > right */
10066 {{0, 4, 4, 0, 0, 1}, D3DERR_INVALIDCALL}, /* top > bottom */
10067 {{0, 0, 4, 4, 1, 0}, D3DERR_INVALIDCALL}, /* back > front */
10068 {{0, 0, 8, 4, 0, 1}, D3DERR_INVALIDCALL}, /* right > surface */
10069 {{0, 0, 4, 8, 0, 1}, D3DERR_INVALIDCALL}, /* bottom > surface */
10070 {{0, 0, 4, 4, 0, 3}, D3DERR_INVALIDCALL}, /* back > surface */
10071 {{8, 0, 16, 4, 0, 1}, D3DERR_INVALIDCALL}, /* left > surface */
10072 {{0, 8, 4, 16, 0, 1}, D3DERR_INVALIDCALL}, /* top > surface */
10073 {{0, 0, 4, 4, 2, 4}, D3DERR_INVALIDCALL}, /* top > surface */
10075 static const D3DBOX test_boxt_2 = {2, 2, 4, 4, 0, 1};
10076 IDirect3DVolumeTexture9 *texture = NULL;
10077 D3DLOCKED_BOX locked_box;
10078 IDirect3DDevice9 *device;
10079 IDirect3D9 *d3d;
10080 unsigned int i;
10081 ULONG refcount;
10082 HWND window;
10083 BYTE *base;
10084 HRESULT hr;
10086 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10087 0, 0, 640, 480, 0, 0, 0, 0);
10088 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10089 ok(!!d3d, "Failed to create a D3D object.\n");
10090 if (!(device = create_device(d3d, window, NULL)))
10092 skip("Failed to create a D3D device, skipping tests.\n");
10093 IDirect3D9_Release(d3d);
10094 DestroyWindow(window);
10095 return;
10098 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 2, 1, 0,
10099 D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &texture, NULL);
10100 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10101 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10102 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10103 base = locked_box.pBits;
10104 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10105 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10107 for (i = 0; i < ARRAY_SIZE(test_data); ++i)
10109 unsigned int offset, expected_offset;
10110 const D3DBOX *box = &test_data[i].box;
10112 locked_box.pBits = (BYTE *)0xdeadbeef;
10113 locked_box.RowPitch = 0xdeadbeef;
10114 locked_box.SlicePitch = 0xdeadbeef;
10116 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, box, 0);
10117 /* Unlike surfaces, volumes properly check the box even in Windows XP */
10118 ok(hr == test_data[i].result,
10119 "Got unexpected hr %#x with box [%u, %u, %u]->[%u, %u, %u], expected %#x.\n",
10120 hr, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back,
10121 test_data[i].result);
10122 if (FAILED(hr))
10123 continue;
10125 offset = (BYTE *)locked_box.pBits - base;
10126 expected_offset = box->Front * locked_box.SlicePitch + box->Top * locked_box.RowPitch + box->Left * 4;
10127 ok(offset == expected_offset,
10128 "Got unexpected offset %u (expected %u) for rect [%u, %u, %u]->[%u, %u, %u].\n",
10129 offset, expected_offset, box->Left, box->Top, box->Front, box->Right, box->Bottom, box->Back);
10131 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10132 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10135 /* locked_box = NULL throws an exception on Windows */
10136 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10137 ok(SUCCEEDED(hr), "Failed to lock volume texture, hr %#x.\n", hr);
10138 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, NULL, 0);
10139 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10140 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10141 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10142 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10143 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10145 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10146 ok(hr == D3D_OK, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10147 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10148 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10149 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_data[0].box, 0);
10150 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10151 hr, test_data[0].box.Left, test_data[0].box.Top, test_data[0].box.Front,
10152 test_data[0].box.Right, test_data[0].box.Bottom, test_data[0].box.Back);
10153 hr = IDirect3DVolumeTexture9_LockBox(texture, 0, &locked_box, &test_boxt_2, 0);
10154 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x for rect [%u, %u, %u]->[%u, %u, %u].\n",
10155 hr, test_boxt_2.Left, test_boxt_2.Top, test_boxt_2.Front,
10156 test_boxt_2.Right, test_boxt_2.Bottom, test_boxt_2.Back);
10157 hr = IDirect3DVolumeTexture9_UnlockBox(texture, 0);
10158 ok(SUCCEEDED(hr), "Failed to unlock volume texture, hr %#x.\n", hr);
10160 IDirect3DVolumeTexture9_Release(texture);
10161 refcount = IDirect3DDevice9_Release(device);
10162 ok(!refcount, "Device has %u references left.\n", refcount);
10163 IDirect3D9_Release(d3d);
10164 DestroyWindow(window);
10167 static void test_shared_handle(void)
10169 IDirect3DDevice9 *device;
10170 IDirect3D9 *d3d;
10171 ULONG refcount;
10172 HWND window;
10173 HRESULT hr;
10174 /* Native d3d9ex refuses to create a shared texture if the texture pointer
10175 * is not initialized to NULL. Make sure this doesn't cause issues here. */
10176 IDirect3DTexture9 *texture = NULL;
10177 IDirect3DSurface9 *surface = NULL;
10178 IDirect3DVertexBuffer9 *vertex_buffer = NULL;
10179 IDirect3DIndexBuffer9 *index_buffer = NULL;
10180 HANDLE handle = NULL;
10181 void *mem;
10182 D3DCAPS9 caps;
10184 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10185 0, 0, 640, 480, 0, 0, 0, 0);
10186 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10187 ok(!!d3d, "Failed to create a D3D object.\n");
10188 if (!(device = create_device(d3d, window, NULL)))
10190 skip("Failed to create a D3D device, skipping tests.\n");
10191 IDirect3D9_Release(d3d);
10192 DestroyWindow(window);
10193 return;
10196 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10197 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
10198 mem = HeapAlloc(GetProcessHeap(), 0, 128 * 128 * 4);
10200 /* Windows XP returns E_NOTIMPL, Windows 7 returns INVALIDCALL, except for
10201 * CreateVertexBuffer, where it returns NOTAVAILABLE. */
10202 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10203 D3DPOOL_DEFAULT, &texture, &handle);
10204 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10205 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
10206 D3DPOOL_SYSTEMMEM, &texture, &mem);
10207 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10209 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10210 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, &handle);
10211 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10212 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
10213 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, &mem);
10214 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10216 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10217 &vertex_buffer, &handle);
10218 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10219 hr = IDirect3DDevice9_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10220 &vertex_buffer, &mem);
10221 ok(hr == E_NOTIMPL || broken(hr == D3DERR_NOTAVAILABLE), "Got unexpected hr %#x.\n", hr);
10223 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_DEFAULT,
10224 &index_buffer, &handle);
10225 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10226 hr = IDirect3DDevice9_CreateIndexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
10227 &index_buffer, &mem);
10228 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10230 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10232 IDirect3DCubeTexture9 *cube_texture = NULL;
10233 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10234 D3DPOOL_DEFAULT, &cube_texture, &handle);
10235 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10236 hr = IDirect3DDevice9_CreateCubeTexture(device, 8, 0, 0, D3DFMT_A8R8G8B8,
10237 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
10238 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10241 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
10243 IDirect3DVolumeTexture9 *volume_texture = NULL;
10244 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10245 D3DPOOL_DEFAULT, &volume_texture, &handle);
10246 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10247 hr = IDirect3DDevice9_CreateVolumeTexture(device, 4, 4, 4, 0, 0, D3DFMT_A8R8G8B8,
10248 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
10249 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10252 hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
10253 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10254 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10256 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24X8,
10257 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, &handle);
10258 ok(hr == E_NOTIMPL || broken(hr == D3DERR_INVALIDCALL), "Got unexpected hr %#x.\n", hr);
10260 HeapFree(GetProcessHeap(), 0, mem);
10261 refcount = IDirect3DDevice9_Release(device);
10262 ok(!refcount, "Device has %u references left.\n", refcount);
10263 IDirect3D9_Release(d3d);
10264 DestroyWindow(window);
10267 static void test_pixel_format(void)
10269 HWND hwnd, hwnd2 = NULL;
10270 HDC hdc, hdc2 = NULL;
10271 HMODULE gl = NULL;
10272 int format, test_format;
10273 PIXELFORMATDESCRIPTOR pfd;
10274 IDirect3D9 *d3d9 = NULL;
10275 IDirect3DDevice9 *device = NULL;
10276 HRESULT hr;
10277 static const float point[3] = {0.0, 0.0, 0.0};
10279 hwnd = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10280 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10281 if (!hwnd)
10283 skip("Failed to create window\n");
10284 return;
10287 hwnd2 = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
10288 100, 100, 160, 160, NULL, NULL, NULL, NULL);
10290 hdc = GetDC(hwnd);
10291 if (!hdc)
10293 skip("Failed to get DC\n");
10294 goto cleanup;
10297 if (hwnd2)
10298 hdc2 = GetDC(hwnd2);
10300 gl = LoadLibraryA("opengl32.dll");
10301 ok(!!gl, "failed to load opengl32.dll; SetPixelFormat()/GetPixelFormat() may not work right\n");
10303 format = GetPixelFormat(hdc);
10304 ok(format == 0, "new window has pixel format %d\n", format);
10306 ZeroMemory(&pfd, sizeof(pfd));
10307 pfd.nSize = sizeof(pfd);
10308 pfd.nVersion = 1;
10309 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
10310 pfd.iPixelType = PFD_TYPE_RGBA;
10311 pfd.iLayerType = PFD_MAIN_PLANE;
10312 format = ChoosePixelFormat(hdc, &pfd);
10313 if (format <= 0)
10315 skip("no pixel format available\n");
10316 goto cleanup;
10319 if (!SetPixelFormat(hdc, format, &pfd) || GetPixelFormat(hdc) != format)
10321 skip("failed to set pixel format\n");
10322 goto cleanup;
10325 if (!hdc2 || !SetPixelFormat(hdc2, format, &pfd) || GetPixelFormat(hdc2) != format)
10327 skip("failed to set pixel format on second window\n");
10328 if (hdc2)
10330 ReleaseDC(hwnd2, hdc2);
10331 hdc2 = NULL;
10335 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
10336 ok(!!d3d9, "Failed to create a D3D object.\n");
10338 test_format = GetPixelFormat(hdc);
10339 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10341 if (!(device = create_device(d3d9, hwnd, NULL)))
10343 skip("Failed to create device\n");
10344 goto cleanup;
10347 test_format = GetPixelFormat(hdc);
10348 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10350 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10351 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
10353 test_format = GetPixelFormat(hdc);
10354 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10356 hr = IDirect3DDevice9_BeginScene(device);
10357 ok(SUCCEEDED(hr), "BeginScene failed %#x\n", hr);
10359 test_format = GetPixelFormat(hdc);
10360 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10362 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, point, 3 * sizeof(float));
10363 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
10365 test_format = GetPixelFormat(hdc);
10366 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10368 hr = IDirect3DDevice9_EndScene(device);
10369 ok(SUCCEEDED(hr), "EndScene failed %#x\n", hr);
10371 test_format = GetPixelFormat(hdc);
10372 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10374 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10375 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10377 test_format = GetPixelFormat(hdc);
10378 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10380 if (hdc2)
10382 hr = IDirect3DDevice9_Present(device, NULL, NULL, hwnd2, NULL);
10383 ok(SUCCEEDED(hr), "Present failed %#x\n", hr);
10385 test_format = GetPixelFormat(hdc);
10386 ok(test_format == format, "window has pixel format %d, expected %d\n", test_format, format);
10388 test_format = GetPixelFormat(hdc2);
10389 ok(test_format == format, "second window has pixel format %d, expected %d\n", test_format, format);
10392 cleanup:
10393 if (device)
10395 UINT refcount = IDirect3DDevice9_Release(device);
10396 ok(!refcount, "Device has %u references left.\n", refcount);
10398 if (d3d9) IDirect3D9_Release(d3d9);
10399 if (gl) FreeLibrary(gl);
10400 if (hdc) ReleaseDC(hwnd, hdc);
10401 if (hdc2) ReleaseDC(hwnd2, hdc2);
10402 if (hwnd) DestroyWindow(hwnd);
10403 if (hwnd2) DestroyWindow(hwnd2);
10406 static void test_begin_end_state_block(void)
10408 IDirect3DStateBlock9 *stateblock;
10409 IDirect3DDevice9 *device;
10410 IDirect3D9 *d3d;
10411 ULONG refcount;
10412 HWND window;
10413 HRESULT hr;
10415 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10416 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10417 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10418 ok(!!d3d, "Failed to create a D3D object.\n");
10419 if (!(device = create_device(d3d, window, NULL)))
10421 skip("Failed to create a D3D device, skipping tests.\n");
10422 IDirect3D9_Release(d3d);
10423 DestroyWindow(window);
10424 return;
10427 /* Should succeed. */
10428 hr = IDirect3DDevice9_BeginStateBlock(device);
10429 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10431 /* Calling BeginStateBlock() while recording should return
10432 * D3DERR_INVALIDCALL. */
10433 hr = IDirect3DDevice9_BeginStateBlock(device);
10434 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10436 /* Should succeed. */
10437 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10438 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10439 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10440 ok(!!stateblock && stateblock != (IDirect3DStateBlock9 *)0xdeadbeef,
10441 "Got unexpected stateblock %p.\n", stateblock);
10442 IDirect3DStateBlock9_Release(stateblock);
10444 /* Calling EndStateBlock() while not recording should return
10445 * D3DERR_INVALIDCALL. stateblock should not be touched. */
10446 stateblock = (IDirect3DStateBlock9 *)0xdeadbeef;
10447 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10448 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
10449 ok(stateblock == (IDirect3DStateBlock9 *)0xdeadbeef,
10450 "Got unexpected stateblock %p.\n", stateblock);
10452 refcount = IDirect3DDevice9_Release(device);
10453 ok(!refcount, "Device has %u references left.\n", refcount);
10454 IDirect3D9_Release(d3d);
10455 DestroyWindow(window);
10458 static void test_shader_constant_apply(void)
10460 static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
10461 static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
10462 static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
10463 IDirect3DStateBlock9 *stateblock;
10464 DWORD vs_version, ps_version;
10465 IDirect3DDevice9 *device;
10466 IDirect3D9 *d3d;
10467 ULONG refcount;
10468 D3DCAPS9 caps;
10469 float ret[4];
10470 HWND window;
10471 HRESULT hr;
10473 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10474 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10475 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10476 ok(!!d3d, "Failed to create a D3D object.\n");
10477 if (!(device = create_device(d3d, window, NULL)))
10479 skip("Failed to create a D3D device, skipping tests.\n");
10480 IDirect3D9_Release(d3d);
10481 DestroyWindow(window);
10482 return;
10485 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10486 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10487 vs_version = caps.VertexShaderVersion & 0xffff;
10488 ps_version = caps.PixelShaderVersion & 0xffff;
10490 if (vs_version)
10492 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, initial, 1);
10493 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10494 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, initial, 1);
10495 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10497 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10498 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10499 ok(!memcmp(ret, initial, sizeof(initial)),
10500 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10501 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10502 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10503 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10504 ok(!memcmp(ret, initial, sizeof(initial)),
10505 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10506 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10508 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, vs_const, 1);
10509 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10511 if (ps_version)
10513 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, initial, 1);
10514 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10515 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, initial, 1);
10516 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10518 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10519 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10520 ok(!memcmp(ret, initial, sizeof(initial)),
10521 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10522 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10523 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10524 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10525 ok(!memcmp(ret, initial, sizeof(initial)),
10526 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10527 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10529 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, ps_const, 1);
10530 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10533 hr = IDirect3DDevice9_BeginStateBlock(device);
10534 ok(SUCCEEDED(hr), "Failed to begin stateblock, hr %#x.\n", hr);
10536 if (vs_version)
10538 hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, vs_const, 1);
10539 ok(SUCCEEDED(hr), "Failed to set vertex shader constant, hr %#x.\n", hr);
10541 if (ps_version)
10543 hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, ps_const, 1);
10544 ok(SUCCEEDED(hr), "Failed to set pixel shader constant, hr %#x.\n", hr);
10547 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10548 ok(SUCCEEDED(hr), "Failed to end stateblock, hr %#x.\n", hr);
10550 if (vs_version)
10552 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10553 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10554 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10555 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10556 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10557 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10558 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10559 ok(!memcmp(ret, initial, sizeof(initial)),
10560 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10561 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10563 if (ps_version)
10565 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10566 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10567 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10568 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10569 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10570 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10571 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10572 ok(!memcmp(ret, initial, sizeof(initial)),
10573 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10574 ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
10577 /* Apply doesn't overwrite constants that aren't explicitly set on the
10578 * source stateblock. */
10579 hr = IDirect3DStateBlock9_Apply(stateblock);
10580 ok(SUCCEEDED(hr), "Failed to apply stateblock, hr %#x.\n", hr);
10582 if (vs_version)
10584 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, ret, 1);
10585 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10586 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10587 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10588 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10589 hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 1, ret, 1);
10590 ok(SUCCEEDED(hr), "Failed to get vertex shader constant, hr %#x.\n", hr);
10591 ok(!memcmp(ret, vs_const, sizeof(vs_const)),
10592 "Got unexpected vertex shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10593 ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
10595 if (ps_version)
10597 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, ret, 1);
10598 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10599 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10600 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10601 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10602 hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 1, ret, 1);
10603 ok(SUCCEEDED(hr), "Failed to get pixel shader constant, hr %#x.\n", hr);
10604 ok(!memcmp(ret, ps_const, sizeof(ps_const)),
10605 "Got unexpected pixel shader constant {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
10606 ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
10609 IDirect3DStateBlock9_Release(stateblock);
10610 refcount = IDirect3DDevice9_Release(device);
10611 ok(!refcount, "Device has %u references left.\n", refcount);
10612 IDirect3D9_Release(d3d);
10613 DestroyWindow(window);
10616 static void test_vdecl_apply(void)
10618 IDirect3DVertexDeclaration9 *declaration, *declaration1, *declaration2;
10619 IDirect3DStateBlock9 *stateblock;
10620 IDirect3DDevice9 *device;
10621 IDirect3D9 *d3d;
10622 ULONG refcount;
10623 HWND window;
10624 HRESULT hr;
10626 static const D3DVERTEXELEMENT9 decl1[] =
10628 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10629 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10630 D3DDECL_END(),
10633 static const D3DVERTEXELEMENT9 decl2[] =
10635 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
10636 {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
10637 {0, 16, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
10638 D3DDECL_END(),
10641 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10642 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10643 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10644 ok(!!d3d, "Failed to create a D3D object.\n");
10645 if (!(device = create_device(d3d, window, NULL)))
10647 skip("Failed to create a D3D device, skipping tests.\n");
10648 IDirect3D9_Release(d3d);
10649 DestroyWindow(window);
10650 return;
10653 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl1, &declaration1);
10654 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10656 hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl2, &declaration2);
10657 ok(SUCCEEDED(hr), "CreateVertexDeclaration failed, hr %#x.\n", hr);
10659 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10660 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10661 hr = IDirect3DDevice9_BeginStateBlock(device);
10662 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
10663 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10664 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10665 hr = IDirect3DDevice9_EndStateBlock(device, &stateblock);
10666 ok(SUCCEEDED(hr), "EndStateBlock failed, hr %#x.\n", hr);
10667 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10668 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10669 hr = IDirect3DStateBlock9_Apply(stateblock);
10670 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10671 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10672 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10673 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10674 declaration, declaration1);
10675 IDirect3DVertexDeclaration9_Release(declaration);
10677 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10678 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10679 hr = IDirect3DStateBlock9_Capture(stateblock);
10680 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10681 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10682 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10683 hr = IDirect3DStateBlock9_Apply(stateblock);
10684 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10685 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10686 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10687 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10688 declaration, declaration2);
10689 IDirect3DVertexDeclaration9_Release(declaration);
10691 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10692 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10693 hr = IDirect3DStateBlock9_Capture(stateblock);
10694 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10695 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10696 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10697 hr = IDirect3DStateBlock9_Apply(stateblock);
10698 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10699 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10700 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10701 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10702 declaration, declaration2);
10703 IDirect3DVertexDeclaration9_Release(declaration);
10705 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10706 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10707 hr = IDirect3DStateBlock9_Capture(stateblock);
10708 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10709 hr = IDirect3DStateBlock9_Apply(stateblock);
10710 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10711 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10712 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10713 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10715 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10716 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10717 hr = IDirect3DStateBlock9_Capture(stateblock);
10718 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10719 hr = IDirect3DStateBlock9_Apply(stateblock);
10720 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10721 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10722 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10723 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10724 declaration, declaration2);
10725 IDirect3DVertexDeclaration9_Release(declaration);
10727 IDirect3DStateBlock9_Release(stateblock);
10728 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration1);
10729 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10730 hr = IDirect3DDevice9_CreateStateBlock(device, D3DSBT_VERTEXSTATE, &stateblock);
10731 ok(SUCCEEDED(hr), "CreateStateBlock failed, hr %#x.\n", hr);
10732 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10733 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10734 hr = IDirect3DStateBlock9_Apply(stateblock);
10735 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10736 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10737 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10738 ok(declaration == declaration1, "Got unexpected vertex declaration %p, expected %p.\n",
10739 declaration, declaration1);
10740 IDirect3DVertexDeclaration9_Release(declaration);
10742 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10743 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10744 hr = IDirect3DStateBlock9_Capture(stateblock);
10745 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10746 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10747 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10748 hr = IDirect3DStateBlock9_Apply(stateblock);
10749 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10750 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10751 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10752 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10753 declaration, declaration2);
10754 IDirect3DVertexDeclaration9_Release(declaration);
10756 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10757 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10758 hr = IDirect3DStateBlock9_Capture(stateblock);
10759 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10760 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10761 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10762 hr = IDirect3DStateBlock9_Apply(stateblock);
10763 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10764 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10765 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10766 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10767 declaration, declaration2);
10768 IDirect3DVertexDeclaration9_Release(declaration);
10770 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10771 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10772 hr = IDirect3DStateBlock9_Capture(stateblock);
10773 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10774 hr = IDirect3DStateBlock9_Apply(stateblock);
10775 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10776 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10777 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10778 ok(!declaration, "Got unexpected vertex declaration %p.\n", declaration);
10780 hr = IDirect3DDevice9_SetVertexDeclaration(device, declaration2);
10781 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10782 hr = IDirect3DStateBlock9_Capture(stateblock);
10783 ok(SUCCEEDED(hr), "Capture failed, hr %#x.\n", hr);
10784 hr = IDirect3DStateBlock9_Apply(stateblock);
10785 ok(SUCCEEDED(hr), "Apply failed, hr %#x.\n", hr);
10786 hr = IDirect3DDevice9_GetVertexDeclaration(device, &declaration);
10787 ok(SUCCEEDED(hr), "GetVertexDeclaration failed, hr %#x.\n", hr);
10788 ok(declaration == declaration2, "Got unexpected vertex declaration %p, expected %p.\n",
10789 declaration, declaration2);
10790 IDirect3DVertexDeclaration9_Release(declaration);
10792 hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
10793 ok(SUCCEEDED(hr), "SetVertexDeclaration failed, hr %#x.\n", hr);
10794 IDirect3DVertexDeclaration9_Release(declaration1);
10795 IDirect3DVertexDeclaration9_Release(declaration2);
10796 IDirect3DStateBlock9_Release(stateblock);
10797 refcount = IDirect3DDevice9_Release(device);
10798 ok(!refcount, "Device has %u references left.\n", refcount);
10799 IDirect3D9_Release(d3d);
10800 DestroyWindow(window);
10803 static void test_resource_type(void)
10805 IDirect3DDevice9 *device;
10806 IDirect3DSurface9 *surface;
10807 IDirect3DTexture9 *texture;
10808 IDirect3DCubeTexture9 *cube_texture;
10809 IDirect3DVolume9 *volume;
10810 IDirect3DVolumeTexture9 *volume_texture;
10811 D3DSURFACE_DESC surface_desc;
10812 D3DVOLUME_DESC volume_desc;
10813 D3DRESOURCETYPE type;
10814 IDirect3D9 *d3d;
10815 ULONG refcount;
10816 HWND window;
10817 HRESULT hr;
10818 D3DCAPS9 caps;
10820 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10821 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10822 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10823 ok(!!d3d, "Failed to create a D3D object.\n");
10824 if (!(device = create_device(d3d, window, NULL)))
10826 skip("Failed to create a D3D device, skipping tests.\n");
10827 IDirect3D9_Release(d3d);
10828 DestroyWindow(window);
10829 return;
10832 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10833 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10835 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 4, 4, D3DFMT_X8R8G8B8,
10836 D3DPOOL_SYSTEMMEM, &surface, NULL);
10837 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
10838 type = IDirect3DSurface9_GetType(surface);
10839 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10840 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10841 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10842 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10843 surface_desc.Type);
10844 IDirect3DSurface9_Release(surface);
10846 hr = IDirect3DDevice9_CreateTexture(device, 2, 8, 4, 0, D3DFMT_X8R8G8B8,
10847 D3DPOOL_SYSTEMMEM, &texture, NULL);
10848 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
10849 type = IDirect3DTexture9_GetType(texture);
10850 ok(type == D3DRTYPE_TEXTURE, "Expected type D3DRTYPE_TEXTURE, got %u.\n", type);
10852 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
10853 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10854 /* The following code crashes, for the sake of completeness:
10855 * type = texture->lpVtbl->GetType((IDirect3DTexture9 *)surface);
10856 * ok(type == D3DRTYPE_PONIES, "Expected type D3DRTYPE_PONIES, got %u.\n", type);
10858 * So applications will not depend on getting the "right" resource type - whatever it
10859 * may be - from the "wrong" vtable. */
10860 type = IDirect3DSurface9_GetType(surface);
10861 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10862 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10863 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10864 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10865 surface_desc.Type);
10866 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10867 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10868 hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &surface_desc);
10869 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10870 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10871 surface_desc.Type);
10872 ok(surface_desc.Width == 2, "Expected width 2, got %u.\n", surface_desc.Width);
10873 ok(surface_desc.Height == 8, "Expected height 8, got %u.\n", surface_desc.Height);
10874 IDirect3DSurface9_Release(surface);
10876 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
10877 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
10878 type = IDirect3DSurface9_GetType(surface);
10879 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10880 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10881 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10882 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10883 surface_desc.Type);
10884 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10885 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10886 hr = IDirect3DTexture9_GetLevelDesc(texture, 2, &surface_desc);
10887 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10888 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10889 surface_desc.Type);
10890 ok(surface_desc.Width == 1, "Expected width 1, got %u.\n", surface_desc.Width);
10891 ok(surface_desc.Height == 2, "Expected height 2, got %u.\n", surface_desc.Height);
10892 IDirect3DSurface9_Release(surface);
10893 IDirect3DTexture9_Release(texture);
10895 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10897 hr = IDirect3DDevice9_CreateCubeTexture(device, 1, 1, 0, D3DFMT_X8R8G8B8,
10898 D3DPOOL_SYSTEMMEM, &cube_texture, NULL);
10899 ok(SUCCEEDED(hr), "Failed to create cube texture, hr %#x.\n", hr);
10900 type = IDirect3DCubeTexture9_GetType(cube_texture);
10901 ok(type == D3DRTYPE_CUBETEXTURE, "Expected type D3DRTYPE_CUBETEXTURE, got %u.\n", type);
10903 hr = IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture,
10904 D3DCUBEMAP_FACE_NEGATIVE_X, 0, &surface);
10905 ok(SUCCEEDED(hr), "Failed to get cube map surface, hr %#x.\n", hr);
10906 type = IDirect3DSurface9_GetType(surface);
10907 ok(type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n", type);
10908 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
10909 ok(SUCCEEDED(hr), "Failed to get surface description, hr %#x.\n", hr);
10910 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10911 surface_desc.Type);
10912 hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
10913 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10914 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Expected type D3DRTYPE_SURFACE, got %u.\n",
10915 surface_desc.Type);
10916 IDirect3DSurface9_Release(surface);
10917 IDirect3DCubeTexture9_Release(cube_texture);
10919 else
10920 skip("Cube maps not supported.\n");
10922 if (caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP)
10924 hr = IDirect3DDevice9_CreateVolumeTexture(device, 2, 4, 8, 4, 0, D3DFMT_X8R8G8B8,
10925 D3DPOOL_SYSTEMMEM, &volume_texture, NULL);
10926 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
10927 type = IDirect3DVolumeTexture9_GetType(volume_texture);
10928 ok(type == D3DRTYPE_VOLUMETEXTURE, "Expected type D3DRTYPE_VOLUMETEXTURE, got %u.\n", type);
10930 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 0, &volume);
10931 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10932 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10933 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10934 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10935 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10936 volume_desc.Type);
10937 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10938 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10939 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10940 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 0, &volume_desc);
10941 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10942 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10943 volume_desc.Type);
10944 ok(volume_desc.Width == 2, "Expected width 2, got %u.\n", volume_desc.Width);
10945 ok(volume_desc.Height == 4, "Expected height 4, got %u.\n", volume_desc.Height);
10946 ok(volume_desc.Depth == 8, "Expected depth 8, got %u.\n", volume_desc.Depth);
10947 IDirect3DVolume9_Release(volume);
10949 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, 2, &volume);
10950 ok(SUCCEEDED(hr), "Failed to get volume level, hr %#x.\n", hr);
10951 /* IDirect3DVolume9 is not an IDirect3DResource9 and has no GetType method. */
10952 hr = IDirect3DVolume9_GetDesc(volume, &volume_desc);
10953 ok(SUCCEEDED(hr), "Failed to get volume description, hr %#x.\n", hr);
10954 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10955 volume_desc.Type);
10956 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10957 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10958 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10959 hr = IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, 2, &volume_desc);
10960 ok(SUCCEEDED(hr), "Failed to get level description, hr %#x.\n", hr);
10961 ok(volume_desc.Type == D3DRTYPE_VOLUME, "Expected type D3DRTYPE_VOLUME, got %u.\n",
10962 volume_desc.Type);
10963 ok(volume_desc.Width == 1, "Expected width 1, got %u.\n", volume_desc.Width);
10964 ok(volume_desc.Height == 1, "Expected height 1, got %u.\n", volume_desc.Height);
10965 ok(volume_desc.Depth == 2, "Expected depth 2, got %u.\n", volume_desc.Depth);
10966 IDirect3DVolume9_Release(volume);
10967 IDirect3DVolumeTexture9_Release(volume_texture);
10969 else
10970 skip("Mipmapped volume maps not supported.\n");
10972 refcount = IDirect3DDevice9_Release(device);
10973 ok(!refcount, "Device has %u references left.\n", refcount);
10974 IDirect3D9_Release(d3d);
10975 DestroyWindow(window);
10978 static void test_mipmap_lock(void)
10980 IDirect3DDevice9 *device;
10981 IDirect3DSurface9 *surface, *surface2, *surface_dst, *surface_dst2;
10982 IDirect3DTexture9 *texture, *texture_dst;
10983 IDirect3D9 *d3d;
10984 ULONG refcount;
10985 HWND window;
10986 HRESULT hr;
10987 D3DLOCKED_RECT locked_rect;
10989 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
10990 0, 0, 640, 480, NULL, NULL, NULL, NULL);
10991 d3d = Direct3DCreate9(D3D_SDK_VERSION);
10992 ok(!!d3d, "Failed to create a D3D object.\n");
10993 if (!(device = create_device(d3d, window, NULL)))
10995 skip("Failed to create a D3D device, skipping tests.\n");
10996 IDirect3D9_Release(d3d);
10997 DestroyWindow(window);
10998 return;
11001 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11002 D3DPOOL_DEFAULT, &texture_dst, NULL);
11003 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11004 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 0, &surface_dst);
11005 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11006 hr = IDirect3DTexture9_GetSurfaceLevel(texture_dst, 1, &surface_dst2);
11007 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11009 hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 2, 0, D3DFMT_X8R8G8B8,
11010 D3DPOOL_SYSTEMMEM, &texture, NULL);
11011 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
11012 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11013 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11014 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface2);
11015 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11017 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
11018 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11019 hr = IDirect3DSurface9_LockRect(surface2, &locked_rect, NULL, 0);
11020 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
11021 hr = IDirect3DSurface9_UnlockRect(surface);
11022 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11024 hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, surface_dst, NULL);
11025 ok(SUCCEEDED(hr), "Failed to update surface, hr %#x.\n", hr);
11026 hr = IDirect3DDevice9_UpdateSurface(device, surface2, NULL, surface_dst2, NULL);
11027 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11029 /* Apparently there's no validation on the container. */
11030 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
11031 (IDirect3DBaseTexture9 *)texture_dst);
11032 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
11034 hr = IDirect3DSurface9_UnlockRect(surface2);
11035 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
11037 IDirect3DSurface9_Release(surface_dst2);
11038 IDirect3DSurface9_Release(surface_dst);
11039 IDirect3DSurface9_Release(surface2);
11040 IDirect3DSurface9_Release(surface);
11041 IDirect3DTexture9_Release(texture_dst);
11042 IDirect3DTexture9_Release(texture);
11044 refcount = IDirect3DDevice9_Release(device);
11045 ok(!refcount, "Device has %u references left.\n", refcount);
11046 IDirect3D9_Release(d3d);
11047 DestroyWindow(window);
11050 static void test_writeonly_resource(void)
11052 IDirect3D9 *d3d;
11053 IDirect3DDevice9 *device;
11054 IDirect3DVertexBuffer9 *buffer;
11055 ULONG refcount;
11056 HWND window;
11057 HRESULT hr;
11058 void *ptr;
11059 static const struct
11061 struct vec3 pos;
11063 quad[] =
11065 {{-1.0f, -1.0f, 0.0f}},
11066 {{-1.0f, 1.0f, 0.0f}},
11067 {{ 1.0f, -1.0f, 0.0f}},
11068 {{ 1.0f, 1.0f, 0.0f}}
11071 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11072 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11073 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11074 ok(!!d3d, "Failed to create a D3D object.\n");
11075 if (!(device = create_device(d3d, window, NULL)))
11077 skip("Failed to create a D3D device, skipping tests.\n");
11078 IDirect3D9_Release(d3d);
11079 DestroyWindow(window);
11080 return;
11083 hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad),
11084 D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer, NULL);
11085 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x.\n", hr);
11087 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_DISCARD);
11088 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11089 memcpy(ptr, quad, sizeof(quad));
11090 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11091 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11092 hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quad));
11093 ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
11094 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
11095 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
11097 hr = IDirect3DDevice9_BeginScene(device);
11098 ok(SUCCEEDED(hr), "Failed to begin scene %#x\n", hr);
11099 hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
11100 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
11101 hr = IDirect3DDevice9_EndScene(device);
11102 ok(SUCCEEDED(hr), "Failed to end scene %#x\n", hr);
11104 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, 0);
11105 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11106 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11107 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11108 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11110 hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &ptr, D3DLOCK_READONLY);
11111 ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
11112 ok(!memcmp(ptr, quad, sizeof(quad)), "Got unexpected vertex buffer data.\n");
11113 hr = IDirect3DVertexBuffer9_Unlock(buffer);
11114 ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
11116 refcount = IDirect3DVertexBuffer9_Release(buffer);
11117 ok(!refcount, "Vertex buffer has %u references left.\n", refcount);
11118 refcount = IDirect3DDevice9_Release(device);
11119 ok(!refcount, "Device has %u references left.\n", refcount);
11120 IDirect3D9_Release(d3d);
11121 DestroyWindow(window);
11124 static void test_lost_device(void)
11126 struct device_desc device_desc;
11127 IDirect3DDevice9 *device;
11128 IDirect3D9 *d3d;
11129 ULONG refcount;
11130 HWND window;
11131 HRESULT hr;
11132 BOOL ret;
11134 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11135 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11136 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11137 ok(!!d3d, "Failed to create a D3D object.\n");
11138 device_desc.device_window = window;
11139 device_desc.width = registry_mode.dmPelsWidth;
11140 device_desc.height = registry_mode.dmPelsHeight;
11141 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11142 if (!(device = create_device(d3d, window, &device_desc)))
11144 skip("Failed to create a D3D device, skipping tests.\n");
11145 goto done;
11148 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11149 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11150 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11151 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11153 ret = SetForegroundWindow(GetDesktopWindow());
11154 ok(ret, "Failed to set foreground window.\n");
11155 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11156 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11157 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11158 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11160 ret = ShowWindow(window, SW_RESTORE);
11161 ok(ret, "Failed to restore window.\n");
11162 ret = SetForegroundWindow(window);
11163 ok(ret, "Failed to set foreground window.\n");
11164 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11165 ok(hr == D3DERR_DEVICENOTRESET, "Got unexpected hr %#x.\n", hr);
11166 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11167 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11169 hr = reset_device(device, &device_desc);
11170 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11171 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11172 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11173 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11174 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11176 device_desc.flags = 0;
11177 hr = reset_device(device, &device_desc);
11178 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11179 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11180 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11181 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11182 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11184 ret = SetForegroundWindow(GetDesktopWindow());
11185 ok(ret, "Failed to set foreground window.\n");
11186 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11187 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11188 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11189 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11191 ret = ShowWindow(window, SW_RESTORE);
11192 ok(ret, "Failed to restore window.\n");
11193 ret = SetForegroundWindow(window);
11194 ok(ret, "Failed to set foreground window.\n");
11195 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11196 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11197 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11198 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11200 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
11201 hr = reset_device(device, &device_desc);
11202 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11203 hr = IDirect3DDevice9_TestCooperativeLevel(device);
11204 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11205 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11206 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11208 ret = SetForegroundWindow(GetDesktopWindow());
11209 ok(ret, "Failed to set foreground window.\n");
11210 hr = reset_device(device, &device_desc);
11211 ok(hr == D3DERR_DEVICELOST, "Got unexpected hr %#x.\n", hr);
11212 ret = ShowWindow(window, SW_RESTORE);
11213 ok(ret, "Failed to restore window.\n");
11214 ret = SetForegroundWindow(window);
11215 ok(ret, "Failed to set foreground window.\n");
11216 hr = reset_device(device, &device_desc);
11217 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11219 refcount = IDirect3DDevice9_Release(device);
11220 ok(!refcount, "Device has %u references left.\n", refcount);
11221 done:
11222 IDirect3D9_Release(d3d);
11223 DestroyWindow(window);
11226 static void test_resource_priority(void)
11228 IDirect3DDevice9 *device;
11229 IDirect3DSurface9 *surface;
11230 IDirect3DTexture9 *texture;
11231 IDirect3DVertexBuffer9 *buffer;
11232 IDirect3D9 *d3d;
11233 ULONG refcount;
11234 HWND window;
11235 HRESULT hr;
11236 static const struct
11238 D3DPOOL pool;
11239 const char *name;
11240 BOOL can_set_priority;
11242 test_data[] =
11244 {D3DPOOL_DEFAULT, "D3DPOOL_DEFAULT", FALSE},
11245 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM", FALSE},
11246 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED", TRUE},
11247 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH", FALSE}
11249 unsigned int i;
11250 DWORD priority;
11252 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11253 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11254 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11255 ok(!!d3d, "Failed to create a D3D object.\n");
11256 if (!(device = create_device(d3d, window, NULL)))
11258 skip("Failed to create a D3D device, skipping tests.\n");
11259 IDirect3D9_Release(d3d);
11260 DestroyWindow(window);
11261 return;
11264 for (i = 0; i < ARRAY_SIZE(test_data); i++)
11266 hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 0, 0, D3DFMT_X8R8G8B8,
11267 test_data[i].pool, &texture, NULL);
11268 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x, pool %s.\n", hr, test_data[i].name);
11269 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
11270 ok(SUCCEEDED(hr), "Failed to get surface level, hr %#x.\n", hr);
11272 priority = IDirect3DTexture9_GetPriority(texture);
11273 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11274 priority = IDirect3DTexture9_SetPriority(texture, 1);
11275 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11276 priority = IDirect3DTexture9_GetPriority(texture);
11277 if (test_data[i].can_set_priority)
11279 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11280 priority = IDirect3DTexture9_SetPriority(texture, 2);
11281 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11283 else
11284 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11286 priority = IDirect3DSurface9_GetPriority(surface);
11287 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11288 priority = IDirect3DSurface9_SetPriority(surface, 1);
11289 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11290 priority = IDirect3DSurface9_GetPriority(surface);
11291 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11293 IDirect3DSurface9_Release(surface);
11294 IDirect3DTexture9_Release(texture);
11296 if (test_data[i].pool != D3DPOOL_MANAGED)
11298 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16, D3DFMT_X8R8G8B8,
11299 test_data[i].pool, &surface, NULL);
11300 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x, pool %s.\n", hr, test_data[i].name);
11302 priority = IDirect3DSurface9_GetPriority(surface);
11303 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11304 priority = IDirect3DSurface9_SetPriority(surface, 1);
11305 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11306 priority = IDirect3DSurface9_GetPriority(surface);
11307 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11309 IDirect3DSurface9_Release(surface);
11312 if (test_data[i].pool != D3DPOOL_SCRATCH)
11314 hr = IDirect3DDevice9_CreateVertexBuffer(device, 256, 0, 0,
11315 test_data[i].pool, &buffer, NULL);
11316 ok(SUCCEEDED(hr), "Failed to create buffer, hr %#x, pool %s.\n", hr, test_data[i].name);
11318 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11319 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11320 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 1);
11321 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11322 priority = IDirect3DVertexBuffer9_GetPriority(buffer);
11323 if (test_data[i].can_set_priority)
11325 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11326 priority = IDirect3DVertexBuffer9_SetPriority(buffer, 0);
11327 ok(priority == 1, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11329 else
11330 ok(priority == 0, "Got unexpected priority %u, pool %s.\n", priority, test_data[i].name);
11332 IDirect3DVertexBuffer9_Release(buffer);
11336 hr = IDirect3DDevice9_CreateRenderTarget(device, 16, 16, D3DFMT_X8R8G8B8,
11337 D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11339 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11340 priority = IDirect3DSurface9_GetPriority(surface);
11341 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11342 priority = IDirect3DSurface9_SetPriority(surface, 1);
11343 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11344 priority = IDirect3DSurface9_GetPriority(surface);
11345 ok(priority == 0, "Got unexpected priority %u.\n", priority);
11347 IDirect3DSurface9_Release(surface);
11349 refcount = IDirect3DDevice9_Release(device);
11350 ok(!refcount, "Device has %u references left.\n", refcount);
11351 IDirect3D9_Release(d3d);
11352 DestroyWindow(window);
11355 static void test_swapchain_parameters(void)
11357 IDirect3DDevice9 *device;
11358 IDirect3D9 *d3d;
11359 HWND window;
11360 HRESULT hr;
11361 unsigned int i;
11362 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
11363 IDirect3DSwapChain9 *swapchain;
11364 static const struct
11366 BOOL windowed;
11367 UINT backbuffer_count;
11368 D3DSWAPEFFECT swap_effect;
11369 HRESULT hr;
11371 tests[] =
11373 /* Swap effect 0 is not allowed. */
11374 {TRUE, 1, 0, D3DERR_INVALIDCALL},
11375 {FALSE, 1, 0, D3DERR_INVALIDCALL},
11377 /* All (non-ex) swap effects are allowed in
11378 * windowed and fullscreen mode. */
11379 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11380 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11381 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
11382 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
11383 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11385 /* Only one backbuffer in copy mode. */
11386 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
11387 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
11388 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11389 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
11391 /* Ok with the others, in fullscreen and windowed mode. */
11392 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11393 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11394 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
11395 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
11397 /* D3D9Ex swap effects. */
11398 {TRUE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11399 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11400 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11401 {FALSE, 1, D3DSWAPEFFECT_OVERLAY, D3DERR_INVALIDCALL},
11402 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3DERR_INVALIDCALL},
11403 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
11405 /* 3 is the highest allowed backbuffer count. */
11406 {TRUE, 3, D3DSWAPEFFECT_DISCARD, D3D_OK},
11407 {TRUE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11408 {TRUE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11409 {FALSE, 4, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
11410 {FALSE, 4, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
11413 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11414 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11415 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11416 ok(!!d3d, "Failed to create a D3D object.\n");
11417 if (!(device = create_device(d3d, window, NULL)))
11419 skip("Failed to create a D3D device, skipping tests.\n");
11420 IDirect3D9_Release(d3d);
11421 DestroyWindow(window);
11422 return;
11424 IDirect3DDevice9_Release(device);
11426 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
11427 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
11428 present_parameters_windowed.hDeviceWindow = window;
11429 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
11430 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
11431 present_parameters_windowed.Windowed = TRUE;
11432 present_parameters_windowed.BackBufferCount = 1;
11434 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11436 memset(&present_parameters, 0, sizeof(present_parameters));
11437 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11438 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11439 present_parameters.hDeviceWindow = window;
11440 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11442 present_parameters.SwapEffect = tests[i].swap_effect;
11443 present_parameters.Windowed = tests[i].windowed;
11444 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11446 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11447 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
11448 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11449 if (SUCCEEDED(hr))
11451 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
11453 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
11454 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
11456 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
11457 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
11458 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
11459 tests[i].swap_effect, present_parameters2.SwapEffect, i);
11460 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
11461 bb_count, present_parameters2.BackBufferCount, i);
11462 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
11463 tests[i].windowed, present_parameters2.Windowed, i);
11465 IDirect3DSwapChain9_Release(swapchain);
11466 IDirect3DDevice9_Release(device);
11469 hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
11470 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, &device);
11471 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
11473 memset(&present_parameters, 0, sizeof(present_parameters));
11474 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
11475 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
11476 present_parameters.hDeviceWindow = window;
11477 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
11479 present_parameters.SwapEffect = tests[i].swap_effect;
11480 present_parameters.Windowed = tests[i].windowed;
11481 present_parameters.BackBufferCount = tests[i].backbuffer_count;
11483 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11484 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
11486 if (FAILED(hr))
11488 hr = IDirect3DDevice9_Reset(device, &present_parameters_windowed);
11489 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
11491 IDirect3DDevice9_Release(device);
11494 IDirect3D9_Release(d3d);
11495 DestroyWindow(window);
11498 static void test_check_device_format(void)
11500 IDirect3D9 *d3d;
11501 HRESULT hr;
11503 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11504 ok(!!d3d, "Failed to create a D3D object.\n");
11506 if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11507 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK)
11509 skip("D3DFMT_A8R8G8B8 textures with SRGBWRITE not supported.\n");
11511 else
11513 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11514 D3DFMT_X8R8G8B8, D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11515 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
11516 hr = IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL,
11517 D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8);
11518 ok(FAILED(hr), "Got unexpected hr %#x.\n", hr);
11521 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11522 0, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11523 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11524 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11525 0, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11526 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11527 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11528 0, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11529 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11531 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11532 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_VERTEXBUFFER, D3DFMT_VERTEXDATA);
11533 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11534 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11535 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_VERTEXDATA);
11536 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11537 hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11538 D3DUSAGE_SOFTWAREPROCESSING, D3DRTYPE_INDEXBUFFER, D3DFMT_INDEX16);
11539 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11541 IDirect3D9_Release(d3d);
11544 static void test_miptree_layout(void)
11546 unsigned int pool_idx, format_idx, base_dimension, level_count, offset, i, j;
11547 IDirect3DCubeTexture9 *texture_cube;
11548 IDirect3DTexture9 *texture_2d;
11549 IDirect3DDevice9 *device;
11550 D3DLOCKED_RECT map_desc;
11551 BYTE *base = NULL;
11552 IDirect3D9 *d3d;
11553 D3DCAPS9 caps;
11554 UINT refcount;
11555 HWND window;
11556 HRESULT hr;
11558 static const struct
11560 D3DFORMAT format;
11561 const char *name;
11563 formats[] =
11565 {D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8"},
11566 {D3DFMT_A8, "D3DFMT_A8"},
11567 {D3DFMT_L8, "D3DFMT_L8"},
11568 {MAKEFOURCC('A','T','I','1'), "D3DFMT_ATI1"},
11569 {MAKEFOURCC('A','T','I','2'), "D3DFMT_ATI2"},
11571 static const struct
11573 D3DPOOL pool;
11574 const char *name;
11576 pools[] =
11578 {D3DPOOL_MANAGED, "D3DPOOL_MANAGED"},
11579 {D3DPOOL_SYSTEMMEM, "D3DPOOL_SYSTEMMEM"},
11580 {D3DPOOL_SCRATCH, "D3DPOOL_SCRATCH"},
11583 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11584 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11585 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11586 ok(!!d3d, "Failed to create a D3D object.\n");
11587 if (!(device = create_device(d3d, window, NULL)))
11589 skip("Failed to create a D3D device, skipping tests.\n");
11590 goto done;
11593 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11594 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
11596 base_dimension = 257;
11597 if (caps.TextureCaps & (D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_CUBEMAP_POW2))
11599 skip("Using power of two base dimension.\n");
11600 base_dimension = 256;
11603 for (format_idx = 0; format_idx < ARRAY_SIZE(formats); ++format_idx)
11605 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11606 D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, formats[format_idx].format)))
11608 skip("%s textures not supported, skipping tests.\n", formats[format_idx].name);
11609 continue;
11612 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11614 hr = IDirect3DDevice9_CreateTexture(device, base_dimension, base_dimension, 0, 0,
11615 formats[format_idx].format, pools[pool_idx].pool, &texture_2d, NULL);
11616 ok(SUCCEEDED(hr), "Failed to create a %s %s texture, hr %#x.\n",
11617 pools[pool_idx].name, formats[format_idx].name, hr);
11619 level_count = IDirect3DTexture9_GetLevelCount(texture_2d);
11620 for (i = 0, offset = 0; i < level_count; ++i)
11622 hr = IDirect3DTexture9_LockRect(texture_2d, i, &map_desc, NULL, 0);
11623 ok(SUCCEEDED(hr), "%s, %s: Failed to lock level %u, hr %#x.\n",
11624 pools[pool_idx].name, formats[format_idx].name, i, hr);
11626 if (!i)
11627 base = map_desc.pBits;
11628 else
11629 ok(map_desc.pBits == base + offset,
11630 "%s, %s, level %u: Got unexpected pBits %p, expected %p.\n",
11631 pools[pool_idx].name, formats[format_idx].name, i, map_desc.pBits, base + offset);
11632 offset += (base_dimension >> i) * map_desc.Pitch;
11634 hr = IDirect3DTexture9_UnlockRect(texture_2d, i);
11635 ok(SUCCEEDED(hr), "%s, %s Failed to unlock level %u, hr %#x.\n",
11636 pools[pool_idx].name, formats[format_idx].name, i, hr);
11639 IDirect3DTexture9_Release(texture_2d);
11642 if (FAILED(hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
11643 D3DFMT_X8R8G8B8, 0, D3DRTYPE_CUBETEXTURE, formats[format_idx].format)))
11645 skip("%s cube textures not supported, skipping tests.\n", formats[format_idx].name);
11646 continue;
11649 for (pool_idx = 0; pool_idx < ARRAY_SIZE(pools); ++pool_idx)
11651 hr = IDirect3DDevice9_CreateCubeTexture(device, base_dimension, 0, 0,
11652 formats[format_idx].format, pools[pool_idx].pool, &texture_cube, NULL);
11653 ok(SUCCEEDED(hr), "Failed to create a %s %s cube texture, hr %#x.\n",
11654 pools[pool_idx].name, formats[format_idx].name, hr);
11656 level_count = IDirect3DCubeTexture9_GetLevelCount(texture_cube);
11657 for (i = 0, offset = 0; i < 6; ++i)
11659 for (j = 0; j < level_count; ++j)
11661 hr = IDirect3DCubeTexture9_LockRect(texture_cube, i, j, &map_desc, NULL, 0);
11662 ok(SUCCEEDED(hr), "%s, %s: Failed to lock face %u, level %u, hr %#x.\n",
11663 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11665 if (!i && !j)
11666 base = map_desc.pBits;
11667 else
11668 ok(map_desc.pBits == base + offset,
11669 "%s, %s, face %u, level %u: Got unexpected pBits %p, expected %p.\n",
11670 pools[pool_idx].name, formats[format_idx].name, i, j, map_desc.pBits, base + offset);
11671 offset += (base_dimension >> j) * map_desc.Pitch;
11673 hr = IDirect3DCubeTexture9_UnlockRect(texture_cube, i, j);
11674 ok(SUCCEEDED(hr), "%s, %s: Failed to unlock face %u, level %u, hr %#x.\n",
11675 pools[pool_idx].name, formats[format_idx].name, i, j, hr);
11677 offset = (offset + 15) & ~15;
11680 IDirect3DCubeTexture9_Release(texture_cube);
11684 refcount = IDirect3DDevice9_Release(device);
11685 ok(!refcount, "Device has %u references left.\n", refcount);
11686 done:
11687 IDirect3D9_Release(d3d);
11688 DestroyWindow(window);
11691 static void test_get_render_target_data(void)
11693 IDirect3DSurface9 *offscreen_surface, *render_target;
11694 IDirect3DDevice9 *device;
11695 IDirect3D9 *d3d;
11696 UINT refcount;
11697 HWND window;
11698 HRESULT hr;
11700 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11701 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11702 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11703 ok(!!d3d, "Failed to create a D3D object.\n");
11704 if (!(device = create_device(d3d, window, NULL)))
11706 skip("Failed to create a D3D device.\n");
11707 IDirect3D9_Release(d3d);
11708 DestroyWindow(window);
11709 return;
11712 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
11713 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
11714 ok(SUCCEEDED(hr), "Failed to create offscreen surface, hr %#x.\n", hr);
11716 hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32,
11717 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL);
11718 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11720 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, NULL);
11721 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11723 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, NULL);
11724 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11726 hr = IDirect3DDevice9_GetRenderTargetData(device, NULL, offscreen_surface);
11727 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11729 hr = IDirect3DDevice9_GetRenderTargetData(device, render_target, offscreen_surface);
11730 ok(SUCCEEDED(hr), "Got unexpected hr %#x.\n", hr);
11732 IDirect3DSurface9_Release(render_target);
11733 IDirect3DSurface9_Release(offscreen_surface);
11734 refcount = IDirect3DDevice9_Release(device);
11735 ok(!refcount, "Device has %u references left.\n", refcount);
11736 IDirect3D9_Release(d3d);
11737 DestroyWindow(window);
11740 static void test_render_target_device_mismatch(void)
11742 IDirect3DDevice9 *device, *device2;
11743 IDirect3DSurface9 *surface, *rt;
11744 IDirect3D9 *d3d;
11745 UINT refcount;
11746 HWND window;
11747 HRESULT hr;
11749 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11750 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11751 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11752 ok(!!d3d, "Failed to create a D3D object.\n");
11753 if (!(device = create_device(d3d, window, NULL)))
11755 skip("Failed to create a D3D device.\n");
11756 IDirect3D9_Release(d3d);
11757 DestroyWindow(window);
11758 return;
11761 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt);
11762 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11764 device2 = create_device(d3d, window, NULL);
11765 ok(!!device2, "Failed to create a D3D device.\n");
11767 hr = IDirect3DDevice9_CreateRenderTarget(device2, 640, 480,
11768 D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &surface, NULL);
11769 ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
11771 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11772 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11774 IDirect3DSurface9_Release(surface);
11776 hr = IDirect3DDevice9_GetRenderTarget(device2, 0, &surface);
11777 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11779 hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
11780 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11782 IDirect3DSurface9_Release(surface);
11784 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
11785 ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
11786 ok(surface == rt, "Got unexpected render target %p, expected %p.\n", surface, rt);
11787 IDirect3DSurface9_Release(surface);
11788 IDirect3DSurface9_Release(rt);
11790 refcount = IDirect3DDevice9_Release(device);
11791 ok(!refcount, "Device has %u references left.\n", refcount);
11792 refcount = IDirect3DDevice9_Release(device2);
11793 ok(!refcount, "Device has %u references left.\n", refcount);
11794 IDirect3D9_Release(d3d);
11795 DestroyWindow(window);
11798 static void test_format_unknown(void)
11800 IDirect3DDevice9 *device;
11801 IDirect3D9 *d3d;
11802 UINT refcount;
11803 HWND window;
11804 void *iface;
11805 HRESULT hr;
11807 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11808 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11809 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11810 ok(!!d3d, "Failed to create a D3D object.\n");
11811 if (!(device = create_device(d3d, window, NULL)))
11813 skip("Failed to create a D3D device.\n");
11814 IDirect3D9_Release(d3d);
11815 DestroyWindow(window);
11816 return;
11819 iface = (void *)0xdeadbeef;
11820 hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64,
11821 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
11822 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11823 ok(!iface, "Got unexpected iface %p.\n", iface);
11825 iface = (void *)0xdeadbeef;
11826 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 64, 64,
11827 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
11828 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11829 ok(!iface, "Got unexpected iface %p.\n", iface);
11831 iface = (void *)0xdeadbeef;
11832 hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64,
11833 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
11834 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11835 ok(!iface, "Got unexpected iface %p.\n", iface);
11837 iface = (void *)0xdeadbeef;
11838 hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0,
11839 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
11840 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11841 ok(!iface, "Got unexpected iface %p.\n", iface);
11843 iface = (void *)0xdeadbeef;
11844 hr = IDirect3DDevice9_CreateCubeTexture(device, 64, 1, 0,
11845 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
11846 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11847 ok(!iface, "Got unexpected iface %p.\n", iface);
11849 iface = (void *)0xdeadbeef;
11850 hr = IDirect3DDevice9_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
11851 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
11852 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11853 ok(!iface, "Got unexpected iface %p.\n", iface);
11855 refcount = IDirect3DDevice9_Release(device);
11856 ok(!refcount, "Device has %u references left.\n", refcount);
11857 IDirect3D9_Release(d3d);
11858 DestroyWindow(window);
11861 static void test_destroyed_window(void)
11863 IDirect3DDevice9 *device;
11864 IDirect3D9 *d3d9;
11865 ULONG refcount;
11866 HWND window;
11867 HRESULT hr;
11869 /* No WS_VISIBLE. */
11870 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
11871 0, 0, 640, 480, NULL, NULL, NULL, NULL);
11872 ok(!!window, "Failed to create a window.\n");
11874 d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
11875 ok(!!d3d9, "Failed to create a D3D object.\n");
11876 device = create_device(d3d9, window, NULL);
11877 IDirect3D9_Release(d3d9);
11878 DestroyWindow(window);
11879 if (!device)
11881 skip("Failed to create a 3D device, skipping test.\n");
11882 return;
11885 hr = IDirect3DDevice9_BeginScene(device);
11886 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
11887 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0f, 0);
11888 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
11889 hr = IDirect3DDevice9_EndScene(device);
11890 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
11891 hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11892 ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
11894 refcount = IDirect3DDevice9_Release(device);
11895 ok(!refcount, "Device has %u references left.\n", refcount);
11898 static void test_lockable_backbuffer(void)
11900 D3DPRESENT_PARAMETERS present_parameters = {0};
11901 struct device_desc device_desc;
11902 IDirect3DSurface9 *surface;
11903 IDirect3DDevice9 *device;
11904 D3DLOCKED_RECT lockrect;
11905 IDirect3D9 *d3d;
11906 ULONG refcount;
11907 HWND window;
11908 HRESULT hr;
11909 HDC dc;
11911 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
11912 0, 0, 640, 480, 0, 0, 0, 0);
11913 d3d = Direct3DCreate9(D3D_SDK_VERSION);
11914 ok(!!d3d, "Failed to create a D3D object.\n");
11916 if (!(device = create_device(d3d, window, NULL)))
11918 skip("Failed to create a D3D device, skipping tests.\n");
11919 IDirect3D9_Release(d3d);
11920 DestroyWindow(window);
11921 return;
11924 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
11925 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
11927 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
11928 todo_wine
11929 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11931 dc = (void *)0xdeadbeef;
11932 hr = IDirect3DSurface9_GetDC(surface, &dc);
11933 ok(dc == (void *)0xdeadbeef, "Unexpected DC returned.\n");
11934 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
11936 IDirect3DSurface9_Release(surface);
11938 /* Reset with D3DPRESENTFLAG_LOCKABLE_BACKBUFFER. */
11939 present_parameters.BackBufferWidth = 640;
11940 present_parameters.BackBufferHeight = 480;
11941 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
11942 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
11943 present_parameters.hDeviceWindow = window;
11944 present_parameters.Windowed = TRUE;
11945 present_parameters.EnableAutoDepthStencil = TRUE;
11946 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
11947 present_parameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
11949 hr = IDirect3DDevice9_Reset(device, &present_parameters);
11950 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
11952 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
11953 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
11955 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
11956 todo_wine
11957 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
11958 hr = IDirect3DSurface9_UnlockRect(surface);
11959 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
11961 IDirect3DSurface9_Release(surface);
11962 refcount = IDirect3DDevice9_Release(device);
11963 ok(!refcount, "Device has %u references left.\n", refcount);
11965 device_desc.width = 640;
11966 device_desc.height = 480;
11967 device_desc.device_window = window;
11968 device_desc.flags = CREATE_DEVICE_LOCKABLE_BACKBUFFER;
11970 device = create_device(d3d, window, &device_desc);
11971 ok(!!device, "Failed to create device.\n");
11973 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
11974 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
11976 hr = IDirect3DSurface9_LockRect(surface, &lockrect, NULL, D3DLOCK_DISCARD);
11977 ok(SUCCEEDED(hr), "Failed to lock rect, hr %#x.\n", hr);
11978 hr = IDirect3DSurface9_UnlockRect(surface);
11979 ok(SUCCEEDED(hr), "Failed to unlock rect, hr %#x.\n", hr);
11981 IDirect3DSurface9_Release(surface);
11982 refcount = IDirect3DDevice9_Release(device);
11983 ok(!refcount, "Device has %u references left.\n", refcount);
11984 IDirect3D9_Release(d3d);
11985 DestroyWindow(window);
11988 static void test_clip_planes_limits(void)
11990 static const DWORD device_flags[] = {0, CREATE_DEVICE_SWVP_ONLY};
11991 IDirect3DDevice9 *device;
11992 struct device_desc desc;
11993 unsigned int i, j;
11994 IDirect3D9 *d3d;
11995 ULONG refcount;
11996 float plane[4];
11997 D3DCAPS9 caps;
11998 DWORD state;
11999 HWND window;
12000 HRESULT hr;
12002 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
12003 0, 0, 640, 480, NULL, NULL, NULL, NULL);
12004 d3d = Direct3DCreate9(D3D_SDK_VERSION);
12005 ok(!!d3d, "Failed to create a D3D object.\n");
12007 for (i = 0; i < ARRAY_SIZE(device_flags); ++i)
12009 desc.device_window = window;
12010 desc.width = 640;
12011 desc.height = 480;
12012 desc.flags = device_flags[i];
12013 if (!(device = create_device(d3d, window, &desc)))
12015 skip("Failed to create D3D device, flags %#x.\n", desc.flags);
12016 continue;
12019 memset(&caps, 0, sizeof(caps));
12020 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
12021 ok(hr == D3D_OK, "Failed to get caps, hr %#x.\n", hr);
12023 trace("Max user clip planes: %u.\n", caps.MaxUserClipPlanes);
12025 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12027 memset(plane, 0xff, sizeof(plane));
12028 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12029 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12030 ok(!plane[0] && !plane[1] && !plane[2] && !plane[3],
12031 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12032 j, plane[0], plane[1], plane[2], plane[3]);
12035 plane[0] = 2.0f;
12036 plane[1] = 8.0f;
12037 plane[2] = 5.0f;
12038 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12040 plane[3] = j;
12041 hr = IDirect3DDevice9_SetClipPlane(device, j, plane);
12042 ok(hr == D3D_OK, "Failed to set clip plane %u, hr %#x.\n", j, hr);
12044 for (j = 0; j < 2 * D3DMAXUSERCLIPPLANES; ++j)
12046 float expected_d = j >= caps.MaxUserClipPlanes - 1 ? 2 * D3DMAXUSERCLIPPLANES - 1 : j;
12047 memset(plane, 0xff, sizeof(plane));
12048 hr = IDirect3DDevice9_GetClipPlane(device, j, plane);
12049 ok(hr == D3D_OK, "Failed to get clip plane %u, hr %#x.\n", j, hr);
12050 ok(plane[0] == 2.0f && plane[1] == 8.0f && plane[2] == 5.0f && plane[3] == expected_d,
12051 "Got unexpected plane %u: %.8e, %.8e, %.8e, %.8e.\n",
12052 j, plane[0], plane[1], plane[2], plane[3]);
12055 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0xffffffff);
12056 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12057 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12058 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12059 ok(state == 0xffffffff, "Got unexpected state %#x.\n", state);
12060 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x80000000);
12061 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
12062 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_CLIPPLANEENABLE, &state);
12063 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
12064 ok(state == 0x80000000, "Got unexpected state %#x.\n", state);
12066 refcount = IDirect3DDevice9_Release(device);
12067 ok(!refcount, "Device has %u references left.\n", refcount);
12070 IDirect3D9_Release(d3d);
12071 DestroyWindow(window);
12074 START_TEST(device)
12076 WNDCLASSA wc = {0};
12077 IDirect3D9 *d3d9;
12078 DEVMODEW current_mode;
12080 memset(&current_mode, 0, sizeof(current_mode));
12081 current_mode.dmSize = sizeof(current_mode);
12082 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
12083 registry_mode.dmSize = sizeof(registry_mode);
12084 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
12085 if (registry_mode.dmPelsWidth != current_mode.dmPelsWidth
12086 || registry_mode.dmPelsHeight != current_mode.dmPelsHeight)
12088 skip("Current mode does not match registry mode, skipping test.\n");
12089 return;
12092 if (!(d3d9 = Direct3DCreate9(D3D_SDK_VERSION)))
12094 skip("could not create D3D9 object\n");
12095 return;
12097 IDirect3D9_Release(d3d9);
12099 wc.lpfnWndProc = DefWindowProcA;
12100 wc.lpszClassName = "d3d9_test_wc";
12101 RegisterClassA(&wc);
12103 test_get_set_vertex_declaration();
12104 test_get_declaration();
12105 test_fvf_decl_conversion();
12106 test_fvf_decl_management();
12107 test_vertex_declaration_alignment();
12108 test_unused_declaration_type();
12109 test_fpu_setup();
12110 test_multi_device();
12111 test_display_formats();
12112 test_display_modes();
12113 test_swapchain();
12114 test_refcount();
12115 test_mipmap_levels();
12116 test_checkdevicemultisampletype();
12117 test_invalid_multisample();
12118 test_cursor();
12119 test_cursor_pos();
12120 test_reset_fullscreen();
12121 test_reset();
12122 test_scene();
12123 test_limits();
12124 test_depthstenciltest();
12125 test_get_rt();
12126 test_draw_primitive();
12127 test_null_stream();
12128 test_lights();
12129 test_set_stream_source();
12130 test_scissor_size();
12131 test_wndproc();
12132 test_wndproc_windowed();
12133 test_window_style();
12134 test_mode_change();
12135 test_device_window_reset();
12136 test_reset_resources();
12137 test_set_rt_vp_scissor();
12138 test_volume_get_container();
12139 test_volume_resource();
12140 test_vb_lock_flags();
12141 test_vertex_buffer_alignment();
12142 test_query_support();
12143 test_occlusion_query();
12144 test_timestamp_query();
12145 test_get_set_vertex_shader();
12146 test_vertex_shader_constant();
12147 test_get_set_pixel_shader();
12148 test_pixel_shader_constant();
12149 test_unsupported_shaders();
12150 test_texture_stage_states();
12151 test_cube_textures();
12152 test_mipmap_gen();
12153 test_filter();
12154 test_get_set_texture();
12155 test_lod();
12156 test_surface_get_container();
12157 test_surface_alignment();
12158 test_lockrect_offset();
12159 test_lockrect_invalid();
12160 test_private_data();
12161 test_getdc();
12162 test_surface_dimensions();
12163 test_surface_format_null();
12164 test_surface_double_unlock();
12165 test_surface_blocks();
12166 test_set_palette();
12167 test_swvp_buffer();
12168 test_managed_buffer();
12169 test_npot_textures();
12170 test_vidmem_accounting();
12171 test_volume_locking();
12172 test_update_volumetexture();
12173 test_create_rt_ds_fail();
12174 test_volume_blocks();
12175 test_lockbox_invalid();
12176 test_shared_handle();
12177 test_pixel_format();
12178 test_begin_end_state_block();
12179 test_shader_constant_apply();
12180 test_vdecl_apply();
12181 test_resource_type();
12182 test_mipmap_lock();
12183 test_writeonly_resource();
12184 test_lost_device();
12185 test_resource_priority();
12186 test_swapchain_parameters();
12187 test_check_device_format();
12188 test_miptree_layout();
12189 test_get_render_target_data();
12190 test_render_target_device_mismatch();
12191 test_format_unknown();
12192 test_destroyed_window();
12193 test_lockable_backbuffer();
12194 test_clip_planes_limits();
12196 UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL));